OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/child/webcrypto/shared_crypto.h" | 5 #include "content/child/webcrypto/shared_crypto.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
9 #include "content/child/webcrypto/platform_crypto.h" | 9 #include "content/child/webcrypto/platform_crypto.h" |
10 #include "content/child/webcrypto/webcrypto_util.h" | 10 #include "content/child/webcrypto/webcrypto_util.h" |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 return Status::Error(); | 226 return Status::Error(); |
227 // Fallthrough intentional! | 227 // Fallthrough intentional! |
228 case blink::WebCryptoAlgorithmIdHmac: | 228 case blink::WebCryptoAlgorithmIdHmac: |
229 return platform::ImportKeyRaw( | 229 return platform::ImportKeyRaw( |
230 algorithm_or_null, key_data, extractable, usage_mask, key); | 230 algorithm_or_null, key_data, extractable, usage_mask, key); |
231 default: | 231 default: |
232 return Status::ErrorUnsupported(); | 232 return Status::ErrorUnsupported(); |
233 } | 233 } |
234 } | 234 } |
235 | 235 |
| 236 // Returns the key format to use for structured cloning. |
| 237 blink::WebCryptoKeyFormat GetCloneFormatForKeyType( |
| 238 blink::WebCryptoKeyType type) { |
| 239 switch (type) { |
| 240 case blink::WebCryptoKeyTypeSecret: |
| 241 return blink::WebCryptoKeyFormatRaw; |
| 242 case blink::WebCryptoKeyTypePublic: |
| 243 return blink::WebCryptoKeyFormatSpki; |
| 244 case blink::WebCryptoKeyTypePrivate: |
| 245 return blink::WebCryptoKeyFormatPkcs8; |
| 246 } |
| 247 |
| 248 NOTREACHED(); |
| 249 return blink::WebCryptoKeyFormatRaw; |
| 250 } |
| 251 |
| 252 // Converts a KeyAlgorithm into an equivalent Algorithm for import. |
| 253 blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm( |
| 254 const blink::WebCryptoKeyAlgorithm& algorithm) { |
| 255 switch (algorithm.paramsType()) { |
| 256 case blink::WebCryptoKeyAlgorithmParamsTypeAes: |
| 257 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
| 258 return CreateAlgorithm(algorithm.id()); |
| 259 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: |
| 260 return CreateHmacImportAlgorithm(algorithm.hmacParams()->hash().id()); |
| 261 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
| 262 return CreateRsaHashedImportAlgorithm( |
| 263 algorithm.id(), algorithm.rsaHashedParams()->hash().id()); |
| 264 case blink::WebCryptoKeyAlgorithmParamsTypeNone: |
| 265 break; |
| 266 } |
| 267 return blink::WebCryptoAlgorithm::createNull(); |
| 268 } |
| 269 |
| 270 // There is some duplicated information in the serialized format used by |
| 271 // structured clone (since the KeyAlgorithm is serialized separately from the |
| 272 // key data). Use this extra information to further validate what was |
| 273 // deserialized from the key data. |
| 274 // |
| 275 // A failure here implies either a bug in the code, or that the serialized data |
| 276 // was corrupted. |
| 277 Status ValidateDeserializedKey(const blink::WebCryptoKey& key, |
| 278 const blink::WebCryptoKeyAlgorithm& algorithm, |
| 279 blink::WebCryptoKeyType type) { |
| 280 if (algorithm.id() != key.algorithm().id()) |
| 281 return Status::ErrorUnexpected(); |
| 282 |
| 283 if (key.type() != type) |
| 284 return Status::ErrorUnexpected(); |
| 285 |
| 286 switch (algorithm.paramsType()) { |
| 287 case blink::WebCryptoKeyAlgorithmParamsTypeAes: |
| 288 if (algorithm.aesParams()->lengthBits() != |
| 289 key.algorithm().aesParams()->lengthBits()) |
| 290 return Status::ErrorUnexpected(); |
| 291 break; |
| 292 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
| 293 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
| 294 if (algorithm.rsaParams()->modulusLengthBits() != |
| 295 key.algorithm().rsaParams()->modulusLengthBits()) |
| 296 return Status::ErrorUnexpected(); |
| 297 if (algorithm.rsaParams()->publicExponent().size() != |
| 298 key.algorithm().rsaParams()->publicExponent().size()) |
| 299 return Status::ErrorUnexpected(); |
| 300 if (memcmp(algorithm.rsaParams()->publicExponent().data(), |
| 301 key.algorithm().rsaParams()->publicExponent().data(), |
| 302 key.algorithm().rsaParams()->publicExponent().size()) != 0) |
| 303 return Status::ErrorUnexpected(); |
| 304 break; |
| 305 case blink::WebCryptoKeyAlgorithmParamsTypeNone: |
| 306 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: |
| 307 break; |
| 308 } |
| 309 |
| 310 return Status::Success(); |
| 311 } |
| 312 |
236 } // namespace | 313 } // namespace |
237 | 314 |
238 void Init() { platform::Init(); } | 315 void Init() { platform::Init(); } |
239 | 316 |
240 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 317 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
241 const blink::WebCryptoKey& key, | 318 const blink::WebCryptoKey& key, |
242 const CryptoData& data, | 319 const CryptoData& data, |
243 blink::WebArrayBuffer* buffer) { | 320 blink::WebArrayBuffer* buffer) { |
244 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) | 321 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) |
245 return Status::ErrorUnexpected(); | 322 return Status::ErrorUnexpected(); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 return platform::ImportKeyPkcs8( | 479 return platform::ImportKeyPkcs8( |
403 algorithm_or_null, key_data, extractable, usage_mask, key); | 480 algorithm_or_null, key_data, extractable, usage_mask, key); |
404 case blink::WebCryptoKeyFormatJwk: | 481 case blink::WebCryptoKeyFormatJwk: |
405 return ImportKeyJwk( | 482 return ImportKeyJwk( |
406 key_data, algorithm_or_null, extractable, usage_mask, key); | 483 key_data, algorithm_or_null, extractable, usage_mask, key); |
407 default: | 484 default: |
408 return Status::ErrorUnsupported(); | 485 return Status::ErrorUnsupported(); |
409 } | 486 } |
410 } | 487 } |
411 | 488 |
412 Status ExportKey(blink::WebCryptoKeyFormat format, | 489 // TODO(eroman): Move this to anonymous namespace. |
413 const blink::WebCryptoKey& key, | 490 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format, |
414 blink::WebArrayBuffer* buffer) { | 491 const blink::WebCryptoKey& key, |
415 if (!key.extractable()) | 492 blink::WebArrayBuffer* buffer) { |
416 return Status::ErrorKeyNotExtractable(); | |
417 | |
418 switch (format) { | 493 switch (format) { |
419 case blink::WebCryptoKeyFormatRaw: { | 494 case blink::WebCryptoKeyFormatRaw: { |
420 platform::SymKey* sym_key; | 495 platform::SymKey* sym_key; |
421 Status status = ToPlatformSymKey(key, &sym_key); | 496 Status status = ToPlatformSymKey(key, &sym_key); |
422 if (status.IsError()) | 497 if (status.IsError()) |
423 return status; | 498 return status; |
424 return platform::ExportKeyRaw(sym_key, buffer); | 499 return platform::ExportKeyRaw(sym_key, buffer); |
425 } | 500 } |
426 case blink::WebCryptoKeyFormatSpki: { | 501 case blink::WebCryptoKeyFormatSpki: { |
427 platform::PublicKey* public_key; | 502 platform::PublicKey* public_key; |
428 Status status = ToPlatformPublicKey(key, &public_key); | 503 Status status = ToPlatformPublicKey(key, &public_key); |
429 if (status.IsError()) | 504 if (status.IsError()) |
430 return status; | 505 return status; |
431 return platform::ExportKeySpki(public_key, buffer); | 506 return platform::ExportKeySpki(public_key, buffer); |
432 } | 507 } |
433 case blink::WebCryptoKeyFormatPkcs8: | 508 case blink::WebCryptoKeyFormatPkcs8: |
434 case blink::WebCryptoKeyFormatJwk: | 509 case blink::WebCryptoKeyFormatJwk: |
435 // TODO(eroman): | 510 // TODO(eroman): |
436 return Status::ErrorUnsupported(); | 511 return Status::ErrorUnsupported(); |
437 default: | 512 default: |
438 return Status::ErrorUnsupported(); | 513 return Status::ErrorUnsupported(); |
439 } | 514 } |
440 } | 515 } |
441 | 516 |
| 517 Status ExportKey(blink::WebCryptoKeyFormat format, |
| 518 const blink::WebCryptoKey& key, |
| 519 blink::WebArrayBuffer* buffer) { |
| 520 if (!key.extractable()) |
| 521 return Status::ErrorKeyNotExtractable(); |
| 522 return ExportKeyDontCheckExtractability(format, key, buffer); |
| 523 } |
| 524 |
442 Status Sign(const blink::WebCryptoAlgorithm& algorithm, | 525 Status Sign(const blink::WebCryptoAlgorithm& algorithm, |
443 const blink::WebCryptoKey& key, | 526 const blink::WebCryptoKey& key, |
444 const CryptoData& data, | 527 const CryptoData& data, |
445 blink::WebArrayBuffer* buffer) { | 528 blink::WebArrayBuffer* buffer) { |
446 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) | 529 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) |
447 return Status::ErrorUnexpected(); | 530 return Status::ErrorUnexpected(); |
448 if (algorithm.id() != key.algorithm().id()) | 531 if (algorithm.id() != key.algorithm().id()) |
449 return Status::ErrorUnexpected(); | 532 return Status::ErrorUnexpected(); |
450 | 533 |
451 switch (algorithm.id()) { | 534 switch (algorithm.id()) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 algorithm_or_null, | 646 algorithm_or_null, |
564 extractable, | 647 extractable, |
565 usage_mask, | 648 usage_mask, |
566 key); | 649 key); |
567 } | 650 } |
568 default: | 651 default: |
569 return Status::ErrorUnsupported(); | 652 return Status::ErrorUnsupported(); |
570 } | 653 } |
571 } | 654 } |
572 | 655 |
| 656 Status SerializeKeyForClone(const blink::WebCryptoKey& key, |
| 657 blink::WebVector<unsigned char>* data) { |
| 658 blink::WebArrayBuffer buffer; |
| 659 Status status = ExportKeyDontCheckExtractability( |
| 660 GetCloneFormatForKeyType(key.type()), key, &buffer); |
| 661 if (status.IsError()) |
| 662 return status; |
| 663 data->assign( |
| 664 reinterpret_cast<unsigned char*>(buffer.data()), buffer.byteLength()); |
| 665 return Status::Success(); |
| 666 } |
| 667 |
| 668 Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm, |
| 669 blink::WebCryptoKeyType type, |
| 670 bool extractable, |
| 671 blink::WebCryptoKeyUsageMask usage_mask, |
| 672 const CryptoData& key_data, |
| 673 blink::WebCryptoKey* key) { |
| 674 Status status = ImportKey(GetCloneFormatForKeyType(type), |
| 675 key_data, |
| 676 KeyAlgorithmToImportAlgorithm(algorithm), |
| 677 extractable, |
| 678 usage_mask, |
| 679 key); |
| 680 if (status.IsError()) |
| 681 return status; |
| 682 |
| 683 return ValidateDeserializedKey(*key, algorithm, type); |
| 684 } |
| 685 |
573 } // namespace webcrypto | 686 } // namespace webcrypto |
574 | 687 |
575 } // namespace content | 688 } // namespace content |
OLD | NEW |