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" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <map> | 9 #include <map> |
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 } | 31 } |
| 32 | 32 |
| 33 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { | 33 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { |
| 34 // TODO(padolph): include all other asymmetric algorithms once they are | 34 // TODO(padolph): include all other asymmetric algorithms once they are |
| 35 // defined, e.g. EC and DH. | 35 // defined, e.g. EC and DH. |
| 36 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | 36 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
| 37 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | 37 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
| 38 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); | 38 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); |
| 39 } | 39 } |
| 40 | 40 |
| 41 // Binds a specific key length value to a compatible factory function. | 41 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); |
| 42 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithOneShortArg)( | |
| 43 unsigned short); | |
| 44 template <AlgFactoryFuncWithOneShortArg func, unsigned short key_length> | |
| 45 blink::WebCryptoAlgorithm BindAlgFactoryWithKeyLen() { | |
| 46 return func(key_length); | |
| 47 } | |
| 48 | 42 |
| 49 // Binds a WebCryptoAlgorithmId value to a compatible factory function. | 43 class JwkAlgorithmInfo { |
|
Ryan Sleevi
2014/01/31 20:55:59
Can we not avoid having to create this class by ma
eroman
2014/01/31 21:02:50
Not sure I follow, can u explain further?
Ryan Sleevi
2014/01/31 21:15:09
Well, I was thinking you could smuggle required_ke
eroman
2014/01/31 21:51:24
I am open to moving more JWK to the blink side, so
| |
| 50 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithWebCryptoAlgIdArg)( | |
| 51 blink::WebCryptoAlgorithmId); | |
| 52 template <AlgFactoryFuncWithWebCryptoAlgIdArg func, | |
| 53 blink::WebCryptoAlgorithmId algorithm_id> | |
| 54 blink::WebCryptoAlgorithm BindAlgFactoryAlgorithmId() { | |
| 55 return func(algorithm_id); | |
| 56 } | |
| 57 | |
| 58 // Defines a map between a JWK 'alg' string ID and a corresponding Web Crypto | |
| 59 // factory function. | |
| 60 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncNoArgs)(); | |
| 61 typedef std::map<std::string, AlgFactoryFuncNoArgs> JwkAlgFactoryMap; | |
| 62 | |
| 63 class JwkAlgorithmFactoryMap { | |
| 64 public: | 44 public: |
| 65 JwkAlgorithmFactoryMap() { | 45 JwkAlgorithmInfo() : |
| 66 map_["HS256"] = | 46 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT), |
| 67 &BindAlgFactoryAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | 47 creation_func_(NULL) { |
| 68 blink::WebCryptoAlgorithmIdSha256>; | |
| 69 map_["HS384"] = | |
| 70 &BindAlgFactoryAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | |
| 71 blink::WebCryptoAlgorithmIdSha384>; | |
| 72 map_["HS512"] = | |
| 73 &BindAlgFactoryAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | |
| 74 blink::WebCryptoAlgorithmIdSha512>; | |
| 75 map_["RS256"] = | |
| 76 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | |
| 77 blink::WebCryptoAlgorithmIdSha256>; | |
| 78 map_["RS384"] = | |
| 79 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | |
| 80 blink::WebCryptoAlgorithmIdSha384>; | |
| 81 map_["RS512"] = | |
| 82 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | |
| 83 blink::WebCryptoAlgorithmIdSha512>; | |
| 84 map_["RSA1_5"] = | |
| 85 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, | |
| 86 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>; | |
| 87 map_["RSA-OAEP"] = | |
| 88 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaOaepAlgorithm, | |
| 89 blink::WebCryptoAlgorithmIdSha1>; | |
| 90 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | |
| 91 map_["A128KW"] = &blink::WebCryptoAlgorithm::createNull; | |
| 92 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | |
| 93 map_["A256KW"] = &blink::WebCryptoAlgorithm::createNull; | |
| 94 map_["A128GCM"] = | |
| 95 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, | |
| 96 blink::WebCryptoAlgorithmIdAesGcm>; | |
| 97 map_["A256GCM"] = | |
| 98 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, | |
| 99 blink::WebCryptoAlgorithmIdAesGcm>; | |
| 100 map_["A128CBC"] = | |
| 101 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, | |
| 102 blink::WebCryptoAlgorithmIdAesCbc>; | |
| 103 map_["A192CBC"] = | |
| 104 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, | |
| 105 blink::WebCryptoAlgorithmIdAesCbc>; | |
| 106 map_["A256CBC"] = | |
| 107 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm, | |
| 108 blink::WebCryptoAlgorithmIdAesCbc>; | |
| 109 } | 48 } |
| 110 | 49 |
| 111 blink::WebCryptoAlgorithm CreateAlgorithmFromName(const std::string& alg_id) | 50 explicit JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func) |
| 112 const { | 51 : required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT), |
| 113 const JwkAlgFactoryMap::const_iterator pos = map_.find(alg_id); | 52 creation_func_(algorithm_creation_func) { |
| 114 if (pos == map_.end()) | 53 } |
| 115 return blink::WebCryptoAlgorithm::createNull(); | 54 |
| 116 return pos->second(); | 55 JwkAlgorithmInfo(unsigned int required_key_length_bits, |
| 56 AlgorithmCreationFunc algorithm_creation_func) | |
| 57 : required_key_length_bytes_(required_key_length_bits / 8), | |
| 58 creation_func_(algorithm_creation_func) { | |
| 59 DCHECK((required_key_length_bits % 8) == 0); | |
| 60 } | |
| 61 | |
| 62 bool CreateAlgorithm(blink::WebCryptoAlgorithm* algorithm) const { | |
| 63 *algorithm = creation_func_(); | |
| 64 return !algorithm->isNull(); | |
| 65 } | |
| 66 | |
| 67 bool IsInvalidKeyByteLength(size_t byte_length) const { | |
| 68 if (required_key_length_bytes_ == NO_KEY_SIZE_REQUIREMENT) | |
| 69 return false; | |
| 70 return required_key_length_bytes_ != byte_length; | |
|
Ryan Sleevi
2014/01/31 21:15:09
nit: delete extra " "
| |
| 117 } | 71 } |
| 118 | 72 |
| 119 private: | 73 private: |
| 120 JwkAlgFactoryMap map_; | 74 enum {NO_KEY_SIZE_REQUIREMENT = UINT_MAX}; |
| 75 | |
| 76 // The expected key size for the algorithm or NO_KEY_SIZE_REQUIREMENT. | |
| 77 unsigned int required_key_length_bytes_; | |
| 78 | |
| 79 AlgorithmCreationFunc creation_func_; | |
|
Ryan Sleevi
2014/01/31 21:15:09
pedantic nit: It seems a little structurally clean
| |
| 121 }; | 80 }; |
| 122 | 81 |
| 123 base::LazyInstance<JwkAlgorithmFactoryMap> jwk_alg_factory = | 82 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; |
| 83 | |
| 84 class JwkAlgorithmRegistry { | |
| 85 public: | |
| 86 JwkAlgorithmRegistry() { | |
| 87 // TODO(eroman): | |
| 88 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 | |
| 89 // says HMAC with SHA-2 should have a key size at least as large as the | |
| 90 // hash output. | |
| 91 alg_to_info_["HS256"] = JwkAlgorithmInfo( | |
| 92 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | |
| 93 blink::WebCryptoAlgorithmIdSha256>); | |
| 94 alg_to_info_["HS384"] = JwkAlgorithmInfo( | |
| 95 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | |
| 96 blink::WebCryptoAlgorithmIdSha384>); | |
| 97 alg_to_info_["HS512"] = JwkAlgorithmInfo( | |
| 98 &BindAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId, | |
| 99 blink::WebCryptoAlgorithmIdSha512>); | |
| 100 alg_to_info_["RS256"] = JwkAlgorithmInfo( | |
| 101 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | |
| 102 blink::WebCryptoAlgorithmIdSha256>); | |
| 103 alg_to_info_["RS384"] = JwkAlgorithmInfo( | |
| 104 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | |
| 105 blink::WebCryptoAlgorithmIdSha384>); | |
| 106 alg_to_info_["RS512"] = JwkAlgorithmInfo( | |
| 107 &BindAlgorithmId<webcrypto::CreateRsaSsaAlgorithm, | |
| 108 blink::WebCryptoAlgorithmIdSha512>); | |
| 109 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | |
| 110 &BindAlgorithmId<webcrypto::CreateAlgorithm, | |
| 111 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); | |
| 112 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( | |
| 113 &BindAlgorithmId<webcrypto::CreateRsaOaepAlgorithm, | |
| 114 blink::WebCryptoAlgorithmIdSha1>); | |
| 115 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | |
| 116 alg_to_info_["A128KW"] = | |
| 117 JwkAlgorithmInfo(128, &blink::WebCryptoAlgorithm::createNull); | |
| 118 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | |
| 119 alg_to_info_["A256KW"] = | |
| 120 JwkAlgorithmInfo(256, &blink::WebCryptoAlgorithm::createNull); | |
| 121 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( | |
| 122 128, | |
| 123 &BindAlgorithmId<webcrypto::CreateAlgorithm, | |
| 124 blink::WebCryptoAlgorithmIdAesGcm>); | |
| 125 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( | |
| 126 256, | |
| 127 &BindAlgorithmId<webcrypto::CreateAlgorithm, | |
| 128 blink::WebCryptoAlgorithmIdAesGcm>); | |
| 129 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( | |
| 130 128, | |
| 131 &BindAlgorithmId<webcrypto::CreateAlgorithm, | |
| 132 blink::WebCryptoAlgorithmIdAesCbc>); | |
| 133 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( | |
| 134 192, | |
| 135 &BindAlgorithmId<webcrypto::CreateAlgorithm, | |
| 136 blink::WebCryptoAlgorithmIdAesCbc>); | |
| 137 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( | |
| 138 256, | |
| 139 &BindAlgorithmId<webcrypto::CreateAlgorithm, | |
| 140 blink::WebCryptoAlgorithmIdAesCbc>); | |
| 141 } | |
| 142 | |
| 143 // Returns NULL if the algorithm name was not registered. | |
| 144 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { | |
| 145 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); | |
| 146 if (pos == alg_to_info_.end()) | |
| 147 return NULL; | |
| 148 return &pos->second; | |
| 149 } | |
| 150 | |
| 151 private: | |
| 152 // Binds a WebCryptoAlgorithmId value to a compatible factory function. | |
| 153 typedef blink::WebCryptoAlgorithm (*FuncWithWebCryptoAlgIdArg)( | |
| 154 blink::WebCryptoAlgorithmId); | |
| 155 template <FuncWithWebCryptoAlgIdArg func, | |
| 156 blink::WebCryptoAlgorithmId algorithm_id> | |
| 157 static blink::WebCryptoAlgorithm BindAlgorithmId() { | |
| 158 return func(algorithm_id); | |
| 159 } | |
| 160 | |
| 161 JwkAlgorithmInfoMap alg_to_info_; | |
| 162 }; | |
| 163 | |
| 164 base::LazyInstance<JwkAlgorithmRegistry> jwk_alg_registry = | |
| 124 LAZY_INSTANCE_INITIALIZER; | 165 LAZY_INSTANCE_INITIALIZER; |
| 125 | 166 |
| 126 bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, | 167 bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, |
| 127 const blink::WebCryptoAlgorithm& alg2) { | 168 const blink::WebCryptoAlgorithm& alg2) { |
| 128 DCHECK(!alg1.isNull()); | 169 DCHECK(!alg1.isNull()); |
| 129 DCHECK(!alg2.isNull()); | 170 DCHECK(!alg2.isNull()); |
| 130 if (alg1.id() != alg2.id()) | 171 if (alg1.id() != alg2.id()) |
| 131 return false; | 172 return false; |
| 132 switch (alg1.id()) { | 173 switch (alg1.id()) { |
| 133 case blink::WebCryptoAlgorithmIdHmac: | 174 case blink::WebCryptoAlgorithmIdHmac: |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 154 break; | 195 break; |
| 155 } | 196 } |
| 156 return false; | 197 return false; |
| 157 } | 198 } |
| 158 | 199 |
| 159 bool GetDecodedUrl64ValueByKey( | 200 bool GetDecodedUrl64ValueByKey( |
| 160 const base::DictionaryValue& dict, | 201 const base::DictionaryValue& dict, |
| 161 const std::string& key, | 202 const std::string& key, |
| 162 std::string* decoded) { | 203 std::string* decoded) { |
| 163 std::string value_url64; | 204 std::string value_url64; |
| 164 if (!dict.GetString(key, &value_url64) || | 205 return dict.GetString(key, &value_url64) && |
| 165 !webcrypto::Base64DecodeUrlSafe(value_url64, decoded) || | 206 webcrypto::Base64DecodeUrlSafe(value_url64, decoded); |
| 166 !decoded->size()) { | |
| 167 return false; | |
| 168 } | |
| 169 return true; | |
| 170 } | 207 } |
| 171 | 208 |
| 172 } // namespace | 209 } // namespace |
| 173 | 210 |
| 174 WebCryptoImpl::WebCryptoImpl() { | 211 WebCryptoImpl::WebCryptoImpl() { |
| 175 Init(); | 212 Init(); |
| 176 } | 213 } |
| 177 | 214 |
| 178 void WebCryptoImpl::encrypt( | 215 void WebCryptoImpl::encrypt( |
| 179 const blink::WebCryptoAlgorithm& algorithm, | 216 const blink::WebCryptoAlgorithm& algorithm, |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 // 1. JWK alg present but unrecognized: error | 566 // 1. JWK alg present but unrecognized: error |
| 530 // 2. JWK alg valid AND input algorithm isNull: use JWK value | 567 // 2. JWK alg valid AND input algorithm isNull: use JWK value |
| 531 // 3. JWK alg valid AND input algorithm specified, but JWK value | 568 // 3. JWK alg valid AND input algorithm specified, but JWK value |
| 532 // inconsistent with input: error | 569 // inconsistent with input: error |
| 533 // 4. JWK alg valid AND input algorithm specified, both consistent: use | 570 // 4. JWK alg valid AND input algorithm specified, both consistent: use |
| 534 // input value (because it has potentially more details) | 571 // input value (because it has potentially more details) |
| 535 // 5. JWK alg missing AND input algorithm isNull: error | 572 // 5. JWK alg missing AND input algorithm isNull: error |
| 536 // 6. JWK alg missing AND input algorithm specified: use input value | 573 // 6. JWK alg missing AND input algorithm specified: use input value |
| 537 // TODO(eroman): Should error if "alg" was specified but not a string. | 574 // TODO(eroman): Should error if "alg" was specified but not a string. |
| 538 blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull(); | 575 blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull(); |
| 576 const JwkAlgorithmInfo* algorithm_info = NULL; | |
| 539 std::string jwk_alg_value; | 577 std::string jwk_alg_value; |
| 540 if (dict_value->GetString("alg", &jwk_alg_value)) { | 578 if (dict_value->GetString("alg", &jwk_alg_value)) { |
| 541 // JWK alg present | 579 // JWK alg present |
| 542 | 580 |
| 543 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can | 581 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can |
| 544 // only be from the RSA family. | 582 // only be from the RSA family. |
| 545 | 583 |
| 546 const blink::WebCryptoAlgorithm jwk_algorithm = | 584 blink::WebCryptoAlgorithm jwk_algorithm = |
| 547 jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value); | 585 blink::WebCryptoAlgorithm::createNull(); |
| 548 if (jwk_algorithm.isNull()) { | 586 algorithm_info = jwk_alg_registry.Get().GetAlgorithmInfo(jwk_alg_value); |
| 549 // JWK alg unrecognized | 587 if (!algorithm_info || !algorithm_info->CreateAlgorithm(&jwk_algorithm)) |
| 550 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 | 588 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 |
| 551 } | 589 |
| 552 // JWK alg valid | 590 // JWK alg valid |
| 553 if (algorithm_or_null.isNull()) { | 591 if (algorithm_or_null.isNull()) { |
| 554 // input algorithm not specified | 592 // input algorithm not specified |
| 555 algorithm = jwk_algorithm; // case 2 | 593 algorithm = jwk_algorithm; // case 2 |
| 556 } else { | 594 } else { |
| 557 // input algorithm specified | 595 // input algorithm specified |
| 558 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) | 596 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) |
| 559 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 | 597 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 |
| 560 algorithm = algorithm_or_null; // case 4 | 598 algorithm = algorithm_or_null; // case 4 |
| 561 } | 599 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 590 } | 628 } |
| 591 } | 629 } |
| 592 | 630 |
| 593 // JWK keying material --> ImportKeyInternal() | 631 // JWK keying material --> ImportKeyInternal() |
| 594 if (jwk_kty_value == "oct") { | 632 if (jwk_kty_value == "oct") { |
| 595 | 633 |
| 596 std::string jwk_k_value; | 634 std::string jwk_k_value; |
| 597 if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value)) | 635 if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value)) |
| 598 return Status::ErrorJwkDecodeK(); | 636 return Status::ErrorJwkDecodeK(); |
| 599 | 637 |
| 600 // TODO(padolph): Some JWK alg ID's embed information about the key length | 638 // Some JWK alg ID's embed information about the key length in the alg ID |
| 601 // in the alg ID string. For example "A128" implies the JWK carries 128 bits | 639 // string. For example "A128CBC" implies the JWK carries 128 bits |
| 602 // of key material, and "HS512" implies the JWK carries _at least_ 512 bits | 640 // of key material. For such keys validate that enough bytes were provided. |
| 603 // of key material. For such keys validate the actual key length against the | 641 // If this validation is not done, then it would be possible to select a |
| 604 // value in the ID. | 642 // different algorithm by passing a different lengthed key, since that is |
| 643 // how WebCrypto interprets things. | |
| 644 if (algorithm_info && | |
| 645 algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) { | |
| 646 return Status::ErrorJwkIncorrectKeyLength(); | |
| 647 } | |
| 605 | 648 |
| 606 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, | 649 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, |
| 607 reinterpret_cast<const uint8*>(jwk_k_value.data()), | 650 reinterpret_cast<const uint8*>(jwk_k_value.data()), |
| 608 jwk_k_value.size(), | 651 jwk_k_value.size(), |
| 609 algorithm, | 652 algorithm, |
| 610 extractable, | 653 extractable, |
| 611 usage_mask, | 654 usage_mask, |
| 612 key); | 655 key); |
| 613 } else if (jwk_kty_value == "RSA") { | 656 } else if (jwk_kty_value == "RSA") { |
| 614 | 657 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 642 key); | 685 key); |
| 643 | 686 |
| 644 } else { | 687 } else { |
| 645 return Status::ErrorJwkUnrecognizedKty(); | 688 return Status::ErrorJwkUnrecognizedKty(); |
| 646 } | 689 } |
| 647 | 690 |
| 648 return Status::Success(); | 691 return Status::Success(); |
| 649 } | 692 } |
| 650 | 693 |
| 651 } // namespace content | 694 } // namespace content |
| OLD | NEW |