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 <algorithm> | 5 #include <algorithm> |
6 #include <functional> | 6 #include <functional> |
7 #include <map> | 7 #include <map> |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 return Status::ErrorUnsupported(); | 375 return Status::ErrorUnsupported(); |
376 default: | 376 default: |
377 return Status::ErrorUnsupported(); | 377 return Status::ErrorUnsupported(); |
378 } | 378 } |
379 return Status::Success(); | 379 return Status::Success(); |
380 } | 380 } |
381 | 381 |
382 } // namespace | 382 } // namespace |
383 | 383 |
384 Status ImportKeyJwk(const CryptoData& key_data, | 384 Status ImportKeyJwk(const CryptoData& key_data, |
385 const blink::WebCryptoAlgorithm& algorithm_or_null, | 385 const blink::WebCryptoAlgorithm& algorithm, |
386 bool extractable, | 386 bool extractable, |
387 blink::WebCryptoKeyUsageMask usage_mask, | 387 blink::WebCryptoKeyUsageMask usage_mask, |
388 blink::WebCryptoKey* key) { | 388 blink::WebCryptoKey* key) { |
389 // TODO(padolph): Generalize this comment to include export, and move to top | 389 // TODO(padolph): Generalize this comment to include export, and move to top |
390 // of file. | 390 // of file. |
391 | 391 |
392 // The goal of this method is to extract key material and meta data from the | 392 // The goal of this method is to extract key material and meta data from the |
393 // incoming JWK, combine them with the input parameters, and ultimately import | 393 // incoming JWK, combine them with the input parameters, and ultimately import |
394 // a Web Crypto Key. | 394 // a Web Crypto Key. |
395 // | 395 // |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 // | "n" | Contains the modulus value for the RSA public key. It is | | 519 // | "n" | Contains the modulus value for the RSA public key. It is | |
520 // | | represented as the base64url encoding of the value's | | 520 // | | represented as the base64url encoding of the value's | |
521 // | | unsigned big endian representation as an octet sequence. | | 521 // | | unsigned big endian representation as an octet sequence. | |
522 // +-------+--------------------------------------------------------------+ | 522 // +-------+--------------------------------------------------------------+ |
523 // | "e" | Contains the exponent value for the RSA public key. It is | | 523 // | "e" | Contains the exponent value for the RSA public key. It is | |
524 // | | represented as the base64url encoding of the value's | | 524 // | | represented as the base64url encoding of the value's | |
525 // | | unsigned big endian representation as an octet sequence. | | 525 // | | unsigned big endian representation as an octet sequence. | |
526 // +-------+--------------------------------------------------------------+ | 526 // +-------+--------------------------------------------------------------+ |
527 // | 527 // |
528 // Consistency and conflict resolution | 528 // Consistency and conflict resolution |
529 // The 'algorithm_or_null', 'extractable', and 'usage_mask' input parameters | 529 // The 'algorithm', 'extractable', and 'usage_mask' input parameters |
530 // may be different than the corresponding values inside the JWK. The Web | 530 // may be different than the corresponding values inside the JWK. The Web |
531 // Crypto spec says that if a JWK value is present but is inconsistent with | 531 // Crypto spec says that if a JWK value is present but is inconsistent with |
532 // the input value, it is an error and the operation must fail. If no | 532 // the input value, it is an error and the operation must fail. If no |
533 // inconsistency is found, the input and JWK values are combined as follows: | 533 // inconsistency is found then the input parameters are used. |
534 // | 534 // |
535 // algorithm | 535 // algorithm |
536 // If an algorithm is provided by both the input parameter and the JWK, | 536 // If the JWK algorithm is provided, it must match the web crypto input |
537 // consistency between the two is based only on algorithm ID's (including an | 537 // algorithm (both the algorithm ID and inner hash if applicable). |
538 // inner hash algorithm if present). In this case if the consistency | |
539 // check is passed, the input algorithm is used. If only one of either the | |
540 // input algorithm and JWK alg is provided, it is used as the final | |
541 // algorithm. | |
542 // | 538 // |
543 // extractable | 539 // extractable |
544 // If the JWK ext field is true but the input parameter is false, make the | 540 // If the JWK ext field is true but the input parameter is false, make the |
545 // Web Crypto Key non-extractable. Conversely, if the JWK ext field is | 541 // Web Crypto Key non-extractable. Conversely, if the JWK ext field is |
546 // false but the input parameter is true, it is an inconsistency. If both | 542 // false but the input parameter is true, it is an inconsistency. If both |
547 // are true or both are false, use that value. | 543 // are true or both are false, use that value. |
548 // | 544 // |
549 // usage_mask | 545 // usage_mask |
550 // The input usage_mask must be a strict subset of the interpreted JWK use | 546 // The input usage_mask must be a strict subset of the interpreted JWK use |
551 // value, else it is judged inconsistent. In all cases the input usage_mask | 547 // value, else it is judged inconsistent. In all cases the input usage_mask |
(...skipping 24 matching lines...) Expand all Loading... |
576 bool jwk_ext_value = false; | 572 bool jwk_ext_value = false; |
577 bool has_jwk_ext; | 573 bool has_jwk_ext; |
578 status = | 574 status = |
579 GetOptionalJwkBool(dict_value, "ext", &jwk_ext_value, &has_jwk_ext); | 575 GetOptionalJwkBool(dict_value, "ext", &jwk_ext_value, &has_jwk_ext); |
580 if (status.IsError()) | 576 if (status.IsError()) |
581 return status; | 577 return status; |
582 if (has_jwk_ext && !jwk_ext_value && extractable) | 578 if (has_jwk_ext && !jwk_ext_value && extractable) |
583 return Status::ErrorJwkExtInconsistent(); | 579 return Status::ErrorJwkExtInconsistent(); |
584 } | 580 } |
585 | 581 |
586 // JWK "alg" (optional) --> algorithm parameter | 582 // JWK "alg" --> algorithm parameter |
587 // Note: input algorithm is also optional, so we have six cases to handle. | |
588 // 1. JWK alg present but unrecognized: error | 583 // 1. JWK alg present but unrecognized: error |
589 // 2. JWK alg valid AND input algorithm isNull: use JWK value | 584 // 2. JWK alg valid and inconsistent with input algorithm: error |
590 // 3. JWK alg valid AND input algorithm specified, but JWK value | 585 // 3. JWK alg valid and consistent with input algorithm: use input value |
591 // inconsistent with input: error | 586 // 4. JWK alg is missing: use input value |
592 // 4. JWK alg valid AND input algorithm specified, both consistent: use | |
593 // input value (because it has potentially more details) | |
594 // 5. JWK alg missing AND input algorithm isNull: error | |
595 // 6. JWK alg missing AND input algorithm specified: use input value | |
596 blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull(); | |
597 const JwkAlgorithmInfo* algorithm_info = NULL; | 587 const JwkAlgorithmInfo* algorithm_info = NULL; |
598 std::string jwk_alg_value; | 588 std::string jwk_alg_value; |
599 bool has_jwk_alg; | 589 bool has_jwk_alg; |
600 status = | 590 status = |
601 GetOptionalJwkString(dict_value, "alg", &jwk_alg_value, &has_jwk_alg); | 591 GetOptionalJwkString(dict_value, "alg", &jwk_alg_value, &has_jwk_alg); |
602 if (status.IsError()) | 592 if (status.IsError()) |
603 return status; | 593 return status; |
604 | 594 |
605 if (has_jwk_alg) { | 595 if (has_jwk_alg) { |
606 // JWK alg present | 596 // JWK alg present |
607 | 597 |
608 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can | 598 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can |
609 // only be from the RSA family. | 599 // only be from the RSA family. |
610 | 600 |
611 blink::WebCryptoAlgorithm jwk_algorithm = | 601 blink::WebCryptoAlgorithm jwk_algorithm = |
612 blink::WebCryptoAlgorithm::createNull(); | 602 blink::WebCryptoAlgorithm::createNull(); |
613 algorithm_info = jwk_alg_registry.Get().GetAlgorithmInfo(jwk_alg_value); | 603 algorithm_info = jwk_alg_registry.Get().GetAlgorithmInfo(jwk_alg_value); |
614 if (!algorithm_info || | 604 if (!algorithm_info || |
615 !algorithm_info->CreateImportAlgorithm(&jwk_algorithm)) | 605 !algorithm_info->CreateImportAlgorithm(&jwk_algorithm)) |
616 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 | 606 return Status::ErrorJwkUnrecognizedAlgorithm(); |
617 | 607 |
618 // JWK alg valid | 608 if (!ImportAlgorithmsConsistent(jwk_algorithm, algorithm)) |
619 if (algorithm_or_null.isNull()) { | 609 return Status::ErrorJwkAlgorithmInconsistent(); |
620 // input algorithm not specified | |
621 algorithm = jwk_algorithm; // case 2 | |
622 } else { | |
623 // input algorithm specified | |
624 if (!ImportAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) | |
625 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 | |
626 algorithm = algorithm_or_null; // case 4 | |
627 } | |
628 } else { | |
629 // JWK alg missing | |
630 if (algorithm_or_null.isNull()) | |
631 return Status::ErrorJwkAlgorithmMissing(); // case 5 | |
632 algorithm = algorithm_or_null; // case 6 | |
633 } | 610 } |
634 DCHECK(!algorithm.isNull()); | 611 DCHECK(!algorithm.isNull()); |
635 | 612 |
636 // JWK "key_ops" (optional) --> usage_mask parameter | 613 // JWK "key_ops" (optional) --> usage_mask parameter |
637 base::ListValue* jwk_key_ops_value = NULL; | 614 base::ListValue* jwk_key_ops_value = NULL; |
638 bool has_jwk_key_ops; | 615 bool has_jwk_key_ops; |
639 status = GetOptionalJwkList( | 616 status = GetOptionalJwkList( |
640 dict_value, "key_ops", &jwk_key_ops_value, &has_jwk_key_ops); | 617 dict_value, "key_ops", &jwk_key_ops_value, &has_jwk_key_ops); |
641 if (status.IsError()) | 618 if (status.IsError()) |
642 return status; | 619 return status; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 std::string json; | 737 std::string json; |
761 base::JSONWriter::Write(&jwk_dict, &json); | 738 base::JSONWriter::Write(&jwk_dict, &json); |
762 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), | 739 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), |
763 json.size()); | 740 json.size()); |
764 return Status::Success(); | 741 return Status::Success(); |
765 } | 742 } |
766 | 743 |
767 } // namespace webcrypto | 744 } // namespace webcrypto |
768 | 745 |
769 } // namespace content | 746 } // namespace content |
OLD | NEW |