| 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 |