| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/webcrypto/webcrypto_impl.h" | |
| 6 | |
| 7 #include <algorithm> | 5 #include <algorithm> |
| 8 #include <functional> | 6 #include <functional> |
| 9 #include <map> | 7 #include <map> |
| 10 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
| 11 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 12 #include "base/logging.h" | 10 #include "base/logging.h" |
| 13 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
| 15 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "content/renderer/webcrypto/crypto_data.h" |
| 15 #include "content/renderer/webcrypto/platform_crypto.h" |
| 16 #include "content/renderer/webcrypto/platform_crypto.h" |
| 16 #include "content/renderer/webcrypto/webcrypto_util.h" | 17 #include "content/renderer/webcrypto/webcrypto_util.h" |
| 17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | |
| 18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
| 19 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | |
| 20 #include "third_party/WebKit/public/platform/WebString.h" | |
| 21 | 18 |
| 22 namespace content { | 19 namespace content { |
| 23 | 20 |
| 24 using webcrypto::Status; | 21 namespace webcrypto { |
| 25 | 22 |
| 26 namespace { | 23 namespace { |
| 27 | 24 |
| 28 void CompleteWithError(const Status& status, blink::WebCryptoResult* result) { | |
| 29 DCHECK(status.IsError()); | |
| 30 if (status.HasErrorDetails()) | |
| 31 result->completeWithError(blink::WebString::fromUTF8(status.ToString())); | |
| 32 else | |
| 33 result->completeWithError(); | |
| 34 } | |
| 35 | |
| 36 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { | |
| 37 // TODO(padolph): include all other asymmetric algorithms once they are | |
| 38 // defined, e.g. EC and DH. | |
| 39 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | |
| 40 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | |
| 41 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); | |
| 42 } | |
| 43 | 25 |
| 44 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); | 26 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); |
| 45 | 27 |
| 46 class JwkAlgorithmInfo { | 28 class JwkAlgorithmInfo { |
| 47 public: | 29 public: |
| 48 JwkAlgorithmInfo() | 30 JwkAlgorithmInfo() |
| 49 : creation_func_(NULL), | 31 : creation_func_(NULL), |
| 50 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { | 32 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { |
| 51 | 33 |
| 52 } | 34 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; | 69 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; |
| 88 | 70 |
| 89 class JwkAlgorithmRegistry { | 71 class JwkAlgorithmRegistry { |
| 90 public: | 72 public: |
| 91 JwkAlgorithmRegistry() { | 73 JwkAlgorithmRegistry() { |
| 92 // TODO(eroman): | 74 // TODO(eroman): |
| 93 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 | 75 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 |
| 94 // says HMAC with SHA-2 should have a key size at least as large as the | 76 // says HMAC with SHA-2 should have a key size at least as large as the |
| 95 // hash output. | 77 // hash output. |
| 96 alg_to_info_["HS256"] = JwkAlgorithmInfo( | 78 alg_to_info_["HS256"] = JwkAlgorithmInfo( |
| 97 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 79 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 98 blink::WebCryptoAlgorithmIdSha256>); | 80 blink::WebCryptoAlgorithmIdSha256>); |
| 99 alg_to_info_["HS384"] = JwkAlgorithmInfo( | 81 alg_to_info_["HS384"] = JwkAlgorithmInfo( |
| 100 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 82 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 101 blink::WebCryptoAlgorithmIdSha384>); | 83 blink::WebCryptoAlgorithmIdSha384>); |
| 102 alg_to_info_["HS512"] = JwkAlgorithmInfo( | 84 alg_to_info_["HS512"] = JwkAlgorithmInfo( |
| 103 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 85 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 104 blink::WebCryptoAlgorithmIdSha512>); | 86 blink::WebCryptoAlgorithmIdSha512>); |
| 105 alg_to_info_["RS256"] = JwkAlgorithmInfo( | 87 alg_to_info_["RS256"] = JwkAlgorithmInfo( |
| 106 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 88 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 107 blink::WebCryptoAlgorithmIdSha256>); | 89 blink::WebCryptoAlgorithmIdSha256>); |
| 108 alg_to_info_["RS384"] = JwkAlgorithmInfo( | 90 alg_to_info_["RS384"] = JwkAlgorithmInfo( |
| 109 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 91 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 110 blink::WebCryptoAlgorithmIdSha384>); | 92 blink::WebCryptoAlgorithmIdSha384>); |
| 111 alg_to_info_["RS512"] = JwkAlgorithmInfo( | 93 alg_to_info_["RS512"] = JwkAlgorithmInfo( |
| 112 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 94 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 113 blink::WebCryptoAlgorithmIdSha512>); | 95 blink::WebCryptoAlgorithmIdSha512>); |
| 114 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 96 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
| 115 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 97 &BindAlgorithmId<CreateAlgorithm, |
| 116 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); | 98 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); |
| 117 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( | 99 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( |
| 118 &BindAlgorithmId<webcrypto::CreateRsaOaepAlgorithm, | 100 &BindAlgorithmId<CreateRsaOaepAlgorithm, |
| 119 blink::WebCryptoAlgorithmIdSha1>); | 101 blink::WebCryptoAlgorithmIdSha1>); |
| 120 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | 102 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet |
| 121 alg_to_info_["A128KW"] = | 103 alg_to_info_["A128KW"] = |
| 122 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); | 104 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); |
| 123 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | 105 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet |
| 124 alg_to_info_["A256KW"] = | 106 alg_to_info_["A256KW"] = |
| 125 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); | 107 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); |
| 126 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( | 108 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( |
| 127 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 109 &BindAlgorithmId<CreateAlgorithm, |
| 128 blink::WebCryptoAlgorithmIdAesGcm>, 128); | 110 blink::WebCryptoAlgorithmIdAesGcm>, 128); |
| 129 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( | 111 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( |
| 130 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 112 &BindAlgorithmId<CreateAlgorithm, |
| 131 blink::WebCryptoAlgorithmIdAesGcm>, 256); | 113 blink::WebCryptoAlgorithmIdAesGcm>, 256); |
| 132 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( | 114 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( |
| 133 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 115 &BindAlgorithmId<CreateAlgorithm, |
| 134 blink::WebCryptoAlgorithmIdAesCbc>, 128); | 116 blink::WebCryptoAlgorithmIdAesCbc>, 128); |
| 135 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( | 117 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( |
| 136 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 118 &BindAlgorithmId<CreateAlgorithm, |
| 137 blink::WebCryptoAlgorithmIdAesCbc>, 192); | 119 blink::WebCryptoAlgorithmIdAesCbc>, 192); |
| 138 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( | 120 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( |
| 139 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 121 &BindAlgorithmId<CreateAlgorithm, |
| 140 blink::WebCryptoAlgorithmIdAesCbc>, 256); | 122 blink::WebCryptoAlgorithmIdAesCbc>, 256); |
| 141 } | 123 } |
| 142 | 124 |
| 143 // Returns NULL if the algorithm name was not registered. | 125 // Returns NULL if the algorithm name was not registered. |
| 144 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { | 126 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { |
| 145 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); | 127 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); |
| 146 if (pos == alg_to_info_.end()) | 128 if (pos == alg_to_info_.end()) |
| 147 return NULL; | 129 return NULL; |
| 148 return &pos->second; | 130 return &pos->second; |
| 149 } | 131 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 168 const blink::WebCryptoAlgorithm& alg2) { | 150 const blink::WebCryptoAlgorithm& alg2) { |
| 169 DCHECK(!alg1.isNull()); | 151 DCHECK(!alg1.isNull()); |
| 170 DCHECK(!alg2.isNull()); | 152 DCHECK(!alg2.isNull()); |
| 171 if (alg1.id() != alg2.id()) | 153 if (alg1.id() != alg2.id()) |
| 172 return false; | 154 return false; |
| 173 switch (alg1.id()) { | 155 switch (alg1.id()) { |
| 174 case blink::WebCryptoAlgorithmIdHmac: | 156 case blink::WebCryptoAlgorithmIdHmac: |
| 175 case blink::WebCryptoAlgorithmIdRsaOaep: | 157 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 176 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 158 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| 177 if (WebCryptoAlgorithmsConsistent( | 159 if (WebCryptoAlgorithmsConsistent( |
| 178 webcrypto::GetInnerHashAlgorithm(alg1), | 160 GetInnerHashAlgorithm(alg1), |
| 179 webcrypto::GetInnerHashAlgorithm(alg2))) { | 161 GetInnerHashAlgorithm(alg2))) { |
| 180 return true; | 162 return true; |
| 181 } | 163 } |
| 182 break; | 164 break; |
| 183 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 165 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| 184 case blink::WebCryptoAlgorithmIdSha1: | 166 case blink::WebCryptoAlgorithmIdSha1: |
| 185 case blink::WebCryptoAlgorithmIdSha224: | 167 case blink::WebCryptoAlgorithmIdSha224: |
| 186 case blink::WebCryptoAlgorithmIdSha256: | 168 case blink::WebCryptoAlgorithmIdSha256: |
| 187 case blink::WebCryptoAlgorithmIdSha384: | 169 case blink::WebCryptoAlgorithmIdSha384: |
| 188 case blink::WebCryptoAlgorithmIdSha512: | 170 case blink::WebCryptoAlgorithmIdSha512: |
| 189 case blink::WebCryptoAlgorithmIdAesCbc: | 171 case blink::WebCryptoAlgorithmIdAesCbc: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 // the base64-decoded bytes to |*result|. If the property does not exist or is | 217 // the base64-decoded bytes to |*result|. If the property does not exist or is |
| 236 // not a string, or could not be base64-decoded, returns an error. | 218 // not a string, or could not be base64-decoded, returns an error. |
| 237 Status GetJwkBytes(base::DictionaryValue* dict, | 219 Status GetJwkBytes(base::DictionaryValue* dict, |
| 238 const std::string& path, | 220 const std::string& path, |
| 239 std::string* result) { | 221 std::string* result) { |
| 240 std::string base64_string; | 222 std::string base64_string; |
| 241 Status status = GetJwkString(dict, path, &base64_string); | 223 Status status = GetJwkString(dict, path, &base64_string); |
| 242 if (status.IsError()) | 224 if (status.IsError()) |
| 243 return status; | 225 return status; |
| 244 | 226 |
| 245 if (!webcrypto::Base64DecodeUrlSafe(base64_string, result)) | 227 if (!Base64DecodeUrlSafe(base64_string, result)) |
| 246 return Status::ErrorJwkBase64Decode(path); | 228 return Status::ErrorJwkBase64Decode(path); |
| 247 | 229 |
| 248 return Status::Success(); | 230 return Status::Success(); |
| 249 } | 231 } |
| 250 | 232 |
| 251 // Extracts the optional boolean property with key |path| from |dict| and saves | 233 // Extracts the optional boolean property with key |path| from |dict| and saves |
| 252 // the result to |*result| if it was found. If the property exists and is not a | 234 // the result to |*result| if it was found. If the property exists and is not a |
| 253 // boolean, returns an error. Otherwise returns success, and sets | 235 // boolean, returns an error. Otherwise returns success, and sets |
| 254 // |*property_exists| if it was found. | 236 // |*property_exists| if it was found. |
| 255 Status GetOptionalJwkBool(base::DictionaryValue* dict, | 237 Status GetOptionalJwkBool(base::DictionaryValue* dict, |
| 256 const std::string& path, | 238 const std::string& path, |
| 257 bool* result, | 239 bool* result, |
| 258 bool* property_exists) { | 240 bool* property_exists) { |
| 259 *property_exists = false; | 241 *property_exists = false; |
| 260 base::Value* value = NULL; | 242 base::Value* value = NULL; |
| 261 if (!dict->Get(path, &value)) | 243 if (!dict->Get(path, &value)) |
| 262 return Status::Success(); | 244 return Status::Success(); |
| 263 | 245 |
| 264 if (!value->GetAsBoolean(result)) | 246 if (!value->GetAsBoolean(result)) |
| 265 return Status::ErrorJwkPropertyWrongType(path, "boolean"); | 247 return Status::ErrorJwkPropertyWrongType(path, "boolean"); |
| 266 | 248 |
| 267 *property_exists = true; | 249 *property_exists = true; |
| 268 return Status::Success(); | 250 return Status::Success(); |
| 269 } | 251 } |
| 270 | 252 |
| 271 } // namespace | 253 } // namespace |
| 272 | 254 |
| 273 WebCryptoImpl::WebCryptoImpl() { | 255 Status PlatformCrypto::ImportKeyJwk( |
| 274 Init(); | 256 const CryptoData& key_data, |
| 275 } | |
| 276 | |
| 277 void WebCryptoImpl::encrypt( | |
| 278 const blink::WebCryptoAlgorithm& algorithm, | |
| 279 const blink::WebCryptoKey& key, | |
| 280 const unsigned char* data, | |
| 281 unsigned int data_size, | |
| 282 blink::WebCryptoResult result) { | |
| 283 DCHECK(!algorithm.isNull()); | |
| 284 blink::WebArrayBuffer buffer; | |
| 285 Status status = EncryptInternal(algorithm, key, data, data_size, &buffer); | |
| 286 if (status.IsError()) | |
| 287 CompleteWithError(status, &result); | |
| 288 else | |
| 289 result.completeWithBuffer(buffer); | |
| 290 } | |
| 291 | |
| 292 void WebCryptoImpl::decrypt( | |
| 293 const blink::WebCryptoAlgorithm& algorithm, | |
| 294 const blink::WebCryptoKey& key, | |
| 295 const unsigned char* data, | |
| 296 unsigned int data_size, | |
| 297 blink::WebCryptoResult result) { | |
| 298 DCHECK(!algorithm.isNull()); | |
| 299 blink::WebArrayBuffer buffer; | |
| 300 Status status = DecryptInternal(algorithm, key, data, data_size, &buffer); | |
| 301 if (status.IsError()) | |
| 302 CompleteWithError(status, &result); | |
| 303 else | |
| 304 result.completeWithBuffer(buffer); | |
| 305 } | |
| 306 | |
| 307 void WebCryptoImpl::digest( | |
| 308 const blink::WebCryptoAlgorithm& algorithm, | |
| 309 const unsigned char* data, | |
| 310 unsigned int data_size, | |
| 311 blink::WebCryptoResult result) { | |
| 312 DCHECK(!algorithm.isNull()); | |
| 313 blink::WebArrayBuffer buffer; | |
| 314 Status status = DigestInternal(algorithm, data, data_size, &buffer); | |
| 315 if (status.IsError()) | |
| 316 CompleteWithError(status, &result); | |
| 317 else | |
| 318 result.completeWithBuffer(buffer); | |
| 319 } | |
| 320 | |
| 321 void WebCryptoImpl::generateKey( | |
| 322 const blink::WebCryptoAlgorithm& algorithm, | |
| 323 bool extractable, | |
| 324 blink::WebCryptoKeyUsageMask usage_mask, | |
| 325 blink::WebCryptoResult result) { | |
| 326 DCHECK(!algorithm.isNull()); | |
| 327 if (IsAlgorithmAsymmetric(algorithm)) { | |
| 328 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); | |
| 329 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); | |
| 330 Status status = GenerateKeyPairInternal( | |
| 331 algorithm, extractable, usage_mask, &public_key, &private_key); | |
| 332 if (status.IsError()) { | |
| 333 CompleteWithError(status, &result); | |
| 334 } else { | |
| 335 DCHECK(public_key.handle()); | |
| 336 DCHECK(private_key.handle()); | |
| 337 DCHECK_EQ(algorithm.id(), public_key.algorithm().id()); | |
| 338 DCHECK_EQ(algorithm.id(), private_key.algorithm().id()); | |
| 339 DCHECK_EQ(true, public_key.extractable()); | |
| 340 DCHECK_EQ(extractable, private_key.extractable()); | |
| 341 DCHECK_EQ(usage_mask, public_key.usages()); | |
| 342 DCHECK_EQ(usage_mask, private_key.usages()); | |
| 343 result.completeWithKeyPair(public_key, private_key); | |
| 344 } | |
| 345 } else { | |
| 346 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | |
| 347 Status status = GenerateSecretKeyInternal( | |
| 348 algorithm, extractable, usage_mask, &key); | |
| 349 if (status.IsError()) { | |
| 350 CompleteWithError(status, &result); | |
| 351 } else { | |
| 352 DCHECK(key.handle()); | |
| 353 DCHECK_EQ(algorithm.id(), key.algorithm().id()); | |
| 354 DCHECK_EQ(extractable, key.extractable()); | |
| 355 DCHECK_EQ(usage_mask, key.usages()); | |
| 356 result.completeWithKey(key); | |
| 357 } | |
| 358 } | |
| 359 } | |
| 360 | |
| 361 void WebCryptoImpl::importKey( | |
| 362 blink::WebCryptoKeyFormat format, | |
| 363 const unsigned char* key_data, | |
| 364 unsigned int key_data_size, | |
| 365 const blink::WebCryptoAlgorithm& algorithm_or_null, | 257 const blink::WebCryptoAlgorithm& algorithm_or_null, |
| 366 bool extractable, | 258 bool extractable, |
| 367 blink::WebCryptoKeyUsageMask usage_mask, | 259 blink::WebCryptoKeyUsageMask usage_mask, |
| 368 blink::WebCryptoResult result) { | |
| 369 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | |
| 370 Status status = Status::Error(); | |
| 371 if (format == blink::WebCryptoKeyFormatJwk) { | |
| 372 status = ImportKeyJwk(key_data, | |
| 373 key_data_size, | |
| 374 algorithm_or_null, | |
| 375 extractable, | |
| 376 usage_mask, | |
| 377 &key); | |
| 378 } else { | |
| 379 status = ImportKeyInternal(format, | |
| 380 key_data, | |
| 381 key_data_size, | |
| 382 algorithm_or_null, | |
| 383 extractable, | |
| 384 usage_mask, | |
| 385 &key); | |
| 386 } | |
| 387 if (status.IsError()) { | |
| 388 CompleteWithError(status, &result); | |
| 389 } else { | |
| 390 DCHECK(key.handle()); | |
| 391 DCHECK(!key.algorithm().isNull()); | |
| 392 DCHECK_EQ(extractable, key.extractable()); | |
| 393 result.completeWithKey(key); | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 void WebCryptoImpl::exportKey( | |
| 398 blink::WebCryptoKeyFormat format, | |
| 399 const blink::WebCryptoKey& key, | |
| 400 blink::WebCryptoResult result) { | |
| 401 blink::WebArrayBuffer buffer; | |
| 402 Status status = ExportKeyInternal(format, key, &buffer); | |
| 403 if (status.IsError()) | |
| 404 CompleteWithError(status, &result); | |
| 405 else | |
| 406 result.completeWithBuffer(buffer); | |
| 407 } | |
| 408 | |
| 409 void WebCryptoImpl::sign( | |
| 410 const blink::WebCryptoAlgorithm& algorithm, | |
| 411 const blink::WebCryptoKey& key, | |
| 412 const unsigned char* data, | |
| 413 unsigned int data_size, | |
| 414 blink::WebCryptoResult result) { | |
| 415 DCHECK(!algorithm.isNull()); | |
| 416 blink::WebArrayBuffer buffer; | |
| 417 Status status = SignInternal(algorithm, key, data, data_size, &buffer); | |
| 418 if (status.IsError()) | |
| 419 CompleteWithError(status, &result); | |
| 420 else | |
| 421 result.completeWithBuffer(buffer); | |
| 422 } | |
| 423 | |
| 424 void WebCryptoImpl::verifySignature( | |
| 425 const blink::WebCryptoAlgorithm& algorithm, | |
| 426 const blink::WebCryptoKey& key, | |
| 427 const unsigned char* signature, | |
| 428 unsigned int signature_size, | |
| 429 const unsigned char* data, | |
| 430 unsigned int data_size, | |
| 431 blink::WebCryptoResult result) { | |
| 432 DCHECK(!algorithm.isNull()); | |
| 433 bool signature_match = false; | |
| 434 Status status = VerifySignatureInternal(algorithm, | |
| 435 key, | |
| 436 signature, | |
| 437 signature_size, | |
| 438 data, | |
| 439 data_size, | |
| 440 &signature_match); | |
| 441 if (status.IsError()) | |
| 442 CompleteWithError(status, &result); | |
| 443 else | |
| 444 result.completeWithBoolean(signature_match); | |
| 445 } | |
| 446 | |
| 447 Status WebCryptoImpl::ImportKeyJwk( | |
| 448 const unsigned char* key_data, | |
| 449 unsigned int key_data_size, | |
| 450 const blink::WebCryptoAlgorithm& algorithm_or_null, | |
| 451 bool extractable, | |
| 452 blink::WebCryptoKeyUsageMask usage_mask, | |
| 453 blink::WebCryptoKey* key) { | 260 blink::WebCryptoKey* key) { |
| 454 | 261 |
| 455 // The goal of this method is to extract key material and meta data from the | 262 // The goal of this method is to extract key material and meta data from the |
| 456 // incoming JWK, combine them with the input parameters, and ultimately import | 263 // incoming JWK, combine them with the input parameters, and ultimately import |
| 457 // a Web Crypto Key. | 264 // a Web Crypto Key. |
| 458 // | 265 // |
| 459 // JSON Web Key Format (JWK) | 266 // JSON Web Key Format (JWK) |
| 460 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 | 267 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 |
| 461 // TODO(padolph): Not all possible values are handled by this code right now | 268 // TODO(padolph): Not all possible values are handled by this code right now |
| 462 // | 269 // |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 // Web Crypto Key non-extractable. Conversely, if the JWK extractable is | 387 // Web Crypto Key non-extractable. Conversely, if the JWK extractable is |
| 581 // false but the input parameter is true, it is an inconsistency. If both | 388 // false but the input parameter is true, it is an inconsistency. If both |
| 582 // are true or both are false, use that value. | 389 // are true or both are false, use that value. |
| 583 // | 390 // |
| 584 // usage_mask | 391 // usage_mask |
| 585 // The input usage_mask must be a strict subset of the interpreted JWK use | 392 // The input usage_mask must be a strict subset of the interpreted JWK use |
| 586 // value, else it is judged inconsistent. In all cases the input usage_mask | 393 // value, else it is judged inconsistent. In all cases the input usage_mask |
| 587 // is used as the final usage_mask. | 394 // is used as the final usage_mask. |
| 588 // | 395 // |
| 589 | 396 |
| 590 if (!key_data_size) | 397 if (!key_data.byte_length()) |
| 591 return Status::ErrorImportEmptyKeyData(); | 398 return Status::ErrorImportEmptyKeyData(); |
| 592 DCHECK(key); | 399 DCHECK(key); |
| 593 | 400 |
| 594 // Parse the incoming JWK JSON. | 401 // Parse the incoming JWK JSON. |
| 595 base::StringPiece json_string(reinterpret_cast<const char*>(key_data), | 402 base::StringPiece json_string(reinterpret_cast<const char*>(key_data.bytes()), |
| 596 key_data_size); | 403 key_data.byte_length()); |
| 597 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); | 404 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); |
| 598 // Note, bare pointer dict_value is ok since it points into scoped value. | 405 // Note, bare pointer dict_value is ok since it points into scoped value. |
| 599 base::DictionaryValue* dict_value = NULL; | 406 base::DictionaryValue* dict_value = NULL; |
| 600 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) | 407 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) |
| 601 return Status::ErrorJwkNotDictionary(); | 408 return Status::ErrorJwkNotDictionary(); |
| 602 | 409 |
| 603 // JWK "kty". Exit early if this required JWK parameter is missing. | 410 // JWK "kty". Exit early if this required JWK parameter is missing. |
| 604 std::string jwk_kty_value; | 411 std::string jwk_kty_value; |
| 605 Status status = GetJwkString(dict_value, "kty", &jwk_kty_value); | 412 Status status = GetJwkString(dict_value, "kty", &jwk_kty_value); |
| 606 if (status.IsError()) | 413 if (status.IsError()) |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 // string. For example "A128CBC" implies the JWK carries 128 bits | 515 // string. For example "A128CBC" implies the JWK carries 128 bits |
| 709 // of key material. For such keys validate that enough bytes were provided. | 516 // of key material. For such keys validate that enough bytes were provided. |
| 710 // If this validation is not done, then it would be possible to select a | 517 // If this validation is not done, then it would be possible to select a |
| 711 // different algorithm by passing a different lengthed key, since that is | 518 // different algorithm by passing a different lengthed key, since that is |
| 712 // how WebCrypto interprets things. | 519 // how WebCrypto interprets things. |
| 713 if (algorithm_info && | 520 if (algorithm_info && |
| 714 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { | 521 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { |
| 715 return Status::ErrorJwkIncorrectKeyLength(); | 522 return Status::ErrorJwkIncorrectKeyLength(); |
| 716 } | 523 } |
| 717 | 524 |
| 718 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, | 525 return ImportKey(blink::WebCryptoKeyFormatRaw, |
| 719 reinterpret_cast<const uint8*>(jwk_k_value.data()), | 526 jwk_k_value, |
| 720 jwk_k_value.size(), | 527 algorithm, |
| 721 algorithm, | 528 extractable, |
| 722 extractable, | 529 usage_mask, |
| 723 usage_mask, | 530 key); |
| 724 key); | |
| 725 } else if (jwk_kty_value == "RSA") { | 531 } else if (jwk_kty_value == "RSA") { |
| 726 | 532 |
| 727 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry | 533 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry |
| 728 // in the JWK, while an RSA private key must have those, plus at least a "d" | 534 // in the JWK, while an RSA private key must have those, plus at least a "d" |
| 729 // (private exponent) entry. | 535 // (private exponent) entry. |
| 730 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, | 536 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, |
| 731 // section 6.3. | 537 // section 6.3. |
| 732 | 538 |
| 733 // RSA private key import is not currently supported, so fail here if a "d" | 539 // RSA private key import is not currently supported, so fail here if a "d" |
| 734 // entry is found. | 540 // entry is found. |
| 735 // TODO(padolph): Support RSA private key import. | 541 // TODO(padolph): Support RSA private key import. |
| 736 if (dict_value->HasKey("d")) | 542 if (dict_value->HasKey("d")) |
| 737 return Status::ErrorJwkRsaPrivateKeyUnsupported(); | 543 return Status::ErrorJwkRsaPrivateKeyUnsupported(); |
| 738 | 544 |
| 739 std::string jwk_n_value; | 545 std::string jwk_n_value; |
| 740 status = GetJwkBytes(dict_value, "n", &jwk_n_value); | 546 status = GetJwkBytes(dict_value, "n", &jwk_n_value); |
| 741 if (status.IsError()) | 547 if (status.IsError()) |
| 742 return status; | 548 return status; |
| 743 std::string jwk_e_value; | 549 std::string jwk_e_value; |
| 744 status = GetJwkBytes(dict_value, "e", &jwk_e_value); | 550 status = GetJwkBytes(dict_value, "e", &jwk_e_value); |
| 745 if (status.IsError()) | 551 if (status.IsError()) |
| 746 return status; | 552 return status; |
| 747 | 553 |
| 748 return ImportRsaPublicKeyInternal( | 554 return PlatformImportRsaPublicKey(jwk_n_value, |
| 749 reinterpret_cast<const uint8*>(jwk_n_value.data()), | 555 jwk_e_value, |
| 750 jwk_n_value.size(), | 556 algorithm, |
| 751 reinterpret_cast<const uint8*>(jwk_e_value.data()), | 557 extractable, |
| 752 jwk_e_value.size(), | 558 usage_mask, |
| 753 algorithm, | 559 key); |
| 754 extractable, | |
| 755 usage_mask, | |
| 756 key); | |
| 757 | 560 |
| 758 } else { | 561 } else { |
| 759 return Status::ErrorJwkUnrecognizedKty(); | 562 return Status::ErrorJwkUnrecognizedKty(); |
| 760 } | 563 } |
| 761 | 564 |
| 762 return Status::Success(); | 565 return Status::Success(); |
| 763 } | 566 } |
| 764 | 567 |
| 568 } // namespace webcrypto |
| 569 |
| 765 } // namespace content | 570 } // namespace content |
| OLD | NEW |