Chromium Code Reviews| 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/shared_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 | |
| 44 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); | 25 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); |
| 45 | 26 |
| 46 class JwkAlgorithmInfo { | 27 class JwkAlgorithmInfo { |
| 47 public: | 28 public: |
| 48 JwkAlgorithmInfo() | 29 JwkAlgorithmInfo() |
| 49 : creation_func_(NULL), | 30 : creation_func_(NULL), |
| 50 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { | 31 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { |
| 51 | 32 |
| 52 } | 33 } |
| 53 | 34 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; | 68 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; |
| 88 | 69 |
| 89 class JwkAlgorithmRegistry { | 70 class JwkAlgorithmRegistry { |
| 90 public: | 71 public: |
| 91 JwkAlgorithmRegistry() { | 72 JwkAlgorithmRegistry() { |
| 92 // TODO(eroman): | 73 // TODO(eroman): |
| 93 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 | 74 // 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 | 75 // says HMAC with SHA-2 should have a key size at least as large as the |
| 95 // hash output. | 76 // hash output. |
| 96 alg_to_info_["HS256"] = JwkAlgorithmInfo( | 77 alg_to_info_["HS256"] = JwkAlgorithmInfo( |
| 97 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 78 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 98 blink::WebCryptoAlgorithmIdSha256>); | 79 blink::WebCryptoAlgorithmIdSha256>); |
| 99 alg_to_info_["HS384"] = JwkAlgorithmInfo( | 80 alg_to_info_["HS384"] = JwkAlgorithmInfo( |
| 100 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 81 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 101 blink::WebCryptoAlgorithmIdSha384>); | 82 blink::WebCryptoAlgorithmIdSha384>); |
| 102 alg_to_info_["HS512"] = JwkAlgorithmInfo( | 83 alg_to_info_["HS512"] = JwkAlgorithmInfo( |
| 103 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 84 &BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 104 blink::WebCryptoAlgorithmIdSha512>); | 85 blink::WebCryptoAlgorithmIdSha512>); |
| 105 alg_to_info_["RS256"] = JwkAlgorithmInfo( | 86 alg_to_info_["RS256"] = JwkAlgorithmInfo( |
| 106 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 87 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 107 blink::WebCryptoAlgorithmIdSha256>); | 88 blink::WebCryptoAlgorithmIdSha256>); |
| 108 alg_to_info_["RS384"] = JwkAlgorithmInfo( | 89 alg_to_info_["RS384"] = JwkAlgorithmInfo( |
| 109 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 90 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 110 blink::WebCryptoAlgorithmIdSha384>); | 91 blink::WebCryptoAlgorithmIdSha384>); |
| 111 alg_to_info_["RS512"] = JwkAlgorithmInfo( | 92 alg_to_info_["RS512"] = JwkAlgorithmInfo( |
| 112 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | 93 &BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 113 blink::WebCryptoAlgorithmIdSha512>); | 94 blink::WebCryptoAlgorithmIdSha512>); |
| 114 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 95 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
| 115 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 96 &BindAlgorithmId<CreateAlgorithm, |
| 116 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); | 97 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); |
| 117 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( | 98 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( |
| 118 &BindAlgorithmId<webcrypto::CreateRsaOaepAlgorithm, | 99 &BindAlgorithmId<CreateRsaOaepAlgorithm, |
| 119 blink::WebCryptoAlgorithmIdSha1>); | 100 blink::WebCryptoAlgorithmIdSha1>); |
| 120 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | 101 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet |
| 121 alg_to_info_["A128KW"] = | 102 alg_to_info_["A128KW"] = |
| 122 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); | 103 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); |
| 123 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | 104 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet |
| 124 alg_to_info_["A256KW"] = | 105 alg_to_info_["A256KW"] = |
| 125 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); | 106 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); |
| 126 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( | 107 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( |
| 127 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 108 &BindAlgorithmId<CreateAlgorithm, |
| 128 blink::WebCryptoAlgorithmIdAesGcm>, 128); | 109 blink::WebCryptoAlgorithmIdAesGcm>, 128); |
| 129 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( | 110 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( |
| 130 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 111 &BindAlgorithmId<CreateAlgorithm, |
| 131 blink::WebCryptoAlgorithmIdAesGcm>, 256); | 112 blink::WebCryptoAlgorithmIdAesGcm>, 256); |
| 132 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( | 113 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( |
| 133 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 114 &BindAlgorithmId<CreateAlgorithm, |
| 134 blink::WebCryptoAlgorithmIdAesCbc>, 128); | 115 blink::WebCryptoAlgorithmIdAesCbc>, 128); |
| 135 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( | 116 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( |
| 136 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 117 &BindAlgorithmId<CreateAlgorithm, |
| 137 blink::WebCryptoAlgorithmIdAesCbc>, 192); | 118 blink::WebCryptoAlgorithmIdAesCbc>, 192); |
| 138 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( | 119 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( |
| 139 &BindAlgorithmId<webcrypto::CreateAlgorithm, | 120 &BindAlgorithmId<CreateAlgorithm, |
| 140 blink::WebCryptoAlgorithmIdAesCbc>, 256); | 121 blink::WebCryptoAlgorithmIdAesCbc>, 256); |
| 141 } | 122 } |
| 142 | 123 |
| 143 // Returns NULL if the algorithm name was not registered. | 124 // Returns NULL if the algorithm name was not registered. |
| 144 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { | 125 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { |
| 145 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); | 126 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); |
| 146 if (pos == alg_to_info_.end()) | 127 if (pos == alg_to_info_.end()) |
| 147 return NULL; | 128 return NULL; |
| 148 return &pos->second; | 129 return &pos->second; |
| 149 } | 130 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 168 const blink::WebCryptoAlgorithm& alg2) { | 149 const blink::WebCryptoAlgorithm& alg2) { |
| 169 DCHECK(!alg1.isNull()); | 150 DCHECK(!alg1.isNull()); |
| 170 DCHECK(!alg2.isNull()); | 151 DCHECK(!alg2.isNull()); |
| 171 if (alg1.id() != alg2.id()) | 152 if (alg1.id() != alg2.id()) |
| 172 return false; | 153 return false; |
| 173 switch (alg1.id()) { | 154 switch (alg1.id()) { |
| 174 case blink::WebCryptoAlgorithmIdHmac: | 155 case blink::WebCryptoAlgorithmIdHmac: |
| 175 case blink::WebCryptoAlgorithmIdRsaOaep: | 156 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 176 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 157 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| 177 if (WebCryptoAlgorithmsConsistent( | 158 if (WebCryptoAlgorithmsConsistent( |
| 178 webcrypto::GetInnerHashAlgorithm(alg1), | 159 GetInnerHashAlgorithm(alg1), |
| 179 webcrypto::GetInnerHashAlgorithm(alg2))) { | 160 GetInnerHashAlgorithm(alg2))) { |
| 180 return true; | 161 return true; |
| 181 } | 162 } |
| 182 break; | 163 break; |
| 183 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 164 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| 184 case blink::WebCryptoAlgorithmIdSha1: | 165 case blink::WebCryptoAlgorithmIdSha1: |
| 185 case blink::WebCryptoAlgorithmIdSha224: | 166 case blink::WebCryptoAlgorithmIdSha224: |
| 186 case blink::WebCryptoAlgorithmIdSha256: | 167 case blink::WebCryptoAlgorithmIdSha256: |
| 187 case blink::WebCryptoAlgorithmIdSha384: | 168 case blink::WebCryptoAlgorithmIdSha384: |
| 188 case blink::WebCryptoAlgorithmIdSha512: | 169 case blink::WebCryptoAlgorithmIdSha512: |
| 189 case blink::WebCryptoAlgorithmIdAesCbc: | 170 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 | 216 // 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. | 217 // not a string, or could not be base64-decoded, returns an error. |
| 237 Status GetJwkBytes(base::DictionaryValue* dict, | 218 Status GetJwkBytes(base::DictionaryValue* dict, |
| 238 const std::string& path, | 219 const std::string& path, |
| 239 std::string* result) { | 220 std::string* result) { |
| 240 std::string base64_string; | 221 std::string base64_string; |
| 241 Status status = GetJwkString(dict, path, &base64_string); | 222 Status status = GetJwkString(dict, path, &base64_string); |
| 242 if (status.IsError()) | 223 if (status.IsError()) |
| 243 return status; | 224 return status; |
| 244 | 225 |
| 245 if (!webcrypto::Base64DecodeUrlSafe(base64_string, result)) | 226 if (!Base64DecodeUrlSafe(base64_string, result)) |
| 246 return Status::ErrorJwkBase64Decode(path); | 227 return Status::ErrorJwkBase64Decode(path); |
| 247 | 228 |
| 248 return Status::Success(); | 229 return Status::Success(); |
| 249 } | 230 } |
| 250 | 231 |
| 251 // Extracts the optional boolean property with key |path| from |dict| and saves | 232 // 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 | 233 // 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 | 234 // boolean, returns an error. Otherwise returns success, and sets |
| 254 // |*property_exists| if it was found. | 235 // |*property_exists| if it was found. |
| 255 Status GetOptionalJwkBool(base::DictionaryValue* dict, | 236 Status GetOptionalJwkBool(base::DictionaryValue* dict, |
| 256 const std::string& path, | 237 const std::string& path, |
| 257 bool* result, | 238 bool* result, |
| 258 bool* property_exists) { | 239 bool* property_exists) { |
| 259 *property_exists = false; | 240 *property_exists = false; |
| 260 base::Value* value = NULL; | 241 base::Value* value = NULL; |
| 261 if (!dict->Get(path, &value)) | 242 if (!dict->Get(path, &value)) |
| 262 return Status::Success(); | 243 return Status::Success(); |
| 263 | 244 |
| 264 if (!value->GetAsBoolean(result)) | 245 if (!value->GetAsBoolean(result)) |
| 265 return Status::ErrorJwkPropertyWrongType(path, "boolean"); | 246 return Status::ErrorJwkPropertyWrongType(path, "boolean"); |
| 266 | 247 |
| 267 *property_exists = true; | 248 *property_exists = true; |
| 268 return Status::Success(); | 249 return Status::Success(); |
| 269 } | 250 } |
| 270 | 251 |
| 271 } // namespace | 252 } // namespace |
| 272 | 253 |
| 273 WebCryptoImpl::WebCryptoImpl() { | 254 Status ImportKeyJwk( |
| 274 Init(); | 255 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, | 256 const blink::WebCryptoAlgorithm& algorithm_or_null, |
| 366 bool extractable, | 257 bool extractable, |
| 367 blink::WebCryptoKeyUsageMask usage_mask, | 258 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) { | 259 blink::WebCryptoKey* key) { |
| 454 | 260 |
| 455 // The goal of this method is to extract key material and meta data from the | 261 // 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 | 262 // incoming JWK, combine them with the input parameters, and ultimately import |
| 457 // a Web Crypto Key. | 263 // a Web Crypto Key. |
| 458 // | 264 // |
| 459 // JSON Web Key Format (JWK) | 265 // JSON Web Key Format (JWK) |
| 460 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 | 266 // 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 | 267 // TODO(padolph): Not all possible values are handled by this code right now |
| 462 // | 268 // |
| (...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 | 386 // 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 | 387 // false but the input parameter is true, it is an inconsistency. If both |
| 582 // are true or both are false, use that value. | 388 // are true or both are false, use that value. |
| 583 // | 389 // |
| 584 // usage_mask | 390 // usage_mask |
| 585 // The input usage_mask must be a strict subset of the interpreted JWK use | 391 // 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 | 392 // value, else it is judged inconsistent. In all cases the input usage_mask |
| 587 // is used as the final usage_mask. | 393 // is used as the final usage_mask. |
| 588 // | 394 // |
| 589 | 395 |
| 590 if (!key_data_size) | 396 if (!key_data.byte_length()) |
| 591 return Status::ErrorImportEmptyKeyData(); | 397 return Status::ErrorImportEmptyKeyData(); |
| 592 DCHECK(key); | 398 DCHECK(key); |
| 593 | 399 |
| 594 // Parse the incoming JWK JSON. | 400 // Parse the incoming JWK JSON. |
| 595 base::StringPiece json_string(reinterpret_cast<const char*>(key_data), | 401 base::StringPiece json_string(reinterpret_cast<const char*>(key_data.bytes()), |
| 596 key_data_size); | 402 key_data.byte_length()); |
| 597 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); | 403 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); |
| 598 // Note, bare pointer dict_value is ok since it points into scoped value. | 404 // Note, bare pointer dict_value is ok since it points into scoped value. |
| 599 base::DictionaryValue* dict_value = NULL; | 405 base::DictionaryValue* dict_value = NULL; |
| 600 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) | 406 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) |
| 601 return Status::ErrorJwkNotDictionary(); | 407 return Status::ErrorJwkNotDictionary(); |
| 602 | 408 |
| 603 // JWK "kty". Exit early if this required JWK parameter is missing. | 409 // JWK "kty". Exit early if this required JWK parameter is missing. |
| 604 std::string jwk_kty_value; | 410 std::string jwk_kty_value; |
| 605 Status status = GetJwkString(dict_value, "kty", &jwk_kty_value); | 411 Status status = GetJwkString(dict_value, "kty", &jwk_kty_value); |
| 606 if (status.IsError()) | 412 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 | 514 // string. For example "A128CBC" implies the JWK carries 128 bits |
| 709 // of key material. For such keys validate that enough bytes were provided. | 515 // 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 | 516 // 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 | 517 // different algorithm by passing a different lengthed key, since that is |
| 712 // how WebCrypto interprets things. | 518 // how WebCrypto interprets things. |
| 713 if (algorithm_info && | 519 if (algorithm_info && |
| 714 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { | 520 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { |
| 715 return Status::ErrorJwkIncorrectKeyLength(); | 521 return Status::ErrorJwkIncorrectKeyLength(); |
| 716 } | 522 } |
| 717 | 523 |
| 718 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, | 524 return ImportKey(blink::WebCryptoKeyFormatRaw, |
| 719 reinterpret_cast<const uint8*>(jwk_k_value.data()), | 525 jwk_k_value, |
| 720 jwk_k_value.size(), | 526 algorithm, |
| 721 algorithm, | 527 extractable, |
| 722 extractable, | 528 usage_mask, |
| 723 usage_mask, | 529 key); |
| 724 key); | |
| 725 } else if (jwk_kty_value == "RSA") { | 530 } else if (jwk_kty_value == "RSA") { |
| 726 | 531 |
| 727 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry | 532 // 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" | 533 // in the JWK, while an RSA private key must have those, plus at least a "d" |
| 729 // (private exponent) entry. | 534 // (private exponent) entry. |
| 730 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, | 535 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, |
| 731 // section 6.3. | 536 // section 6.3. |
| 732 | 537 |
| 733 // RSA private key import is not currently supported, so fail here if a "d" | 538 // RSA private key import is not currently supported, so fail here if a "d" |
| 734 // entry is found. | 539 // entry is found. |
| 735 // TODO(padolph): Support RSA private key import. | 540 // TODO(padolph): Support RSA private key import. |
| 736 if (dict_value->HasKey("d")) | 541 if (dict_value->HasKey("d")) |
| 737 return Status::ErrorJwkRsaPrivateKeyUnsupported(); | 542 return Status::ErrorJwkRsaPrivateKeyUnsupported(); |
| 738 | 543 |
| 739 std::string jwk_n_value; | 544 std::string jwk_n_value; |
| 740 status = GetJwkBytes(dict_value, "n", &jwk_n_value); | 545 status = GetJwkBytes(dict_value, "n", &jwk_n_value); |
| 741 if (status.IsError()) | 546 if (status.IsError()) |
| 742 return status; | 547 return status; |
| 743 std::string jwk_e_value; | 548 std::string jwk_e_value; |
| 744 status = GetJwkBytes(dict_value, "e", &jwk_e_value); | 549 status = GetJwkBytes(dict_value, "e", &jwk_e_value); |
| 745 if (status.IsError()) | 550 if (status.IsError()) |
| 746 return status; | 551 return status; |
| 747 | 552 |
| 748 return ImportRsaPublicKeyInternal( | 553 return platform::ImportRsaPublicKey(jwk_n_value, |
| 749 reinterpret_cast<const uint8*>(jwk_n_value.data()), | 554 jwk_e_value, |
| 750 jwk_n_value.size(), | 555 algorithm, |
| 751 reinterpret_cast<const uint8*>(jwk_e_value.data()), | 556 extractable, |
| 752 jwk_e_value.size(), | 557 usage_mask, |
| 753 algorithm, | 558 key); |
|
Ryan Sleevi
2014/02/07 21:26:40
alignment
eroman
2014/02/08 02:23:51
Done.
| |
| 754 extractable, | |
| 755 usage_mask, | |
| 756 key); | |
| 757 | 559 |
| 758 } else { | 560 } else { |
| 759 return Status::ErrorJwkUnrecognizedKty(); | 561 return Status::ErrorJwkUnrecognizedKty(); |
| 760 } | 562 } |
| 761 | 563 |
| 762 return Status::Success(); | 564 return Status::Success(); |
| 763 } | 565 } |
| 764 | 566 |
| 567 } // namespace webcrypto | |
| 568 | |
| 765 } // namespace content | 569 } // namespace content |
| 570 | |
| 571 | |
|
Ryan Sleevi
2014/02/07 21:26:40
unnecessary newline?
eroman
2014/02/08 02:23:51
Ick git cl format added these.
| |
| OLD | NEW |