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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 GetInnerHashAlgorithm(alg2))) { | 126 GetInnerHashAlgorithm(alg2))) { |
127 return true; | 127 return true; |
128 } | 128 } |
129 return false; | 129 return false; |
130 } | 130 } |
131 return true; | 131 return true; |
132 } | 132 } |
133 return false; | 133 return false; |
134 } | 134 } |
135 | 135 |
| 136 bool GetDecodedUrl64ValueByKey( |
| 137 const base::DictionaryValue& dict, |
| 138 const std::string& key, |
| 139 std::string* decoded) { |
| 140 std::string value_url64; |
| 141 if (!dict.GetString(key, &value_url64) || |
| 142 !Base64DecodeUrlSafe(value_url64, decoded) || |
| 143 !decoded->size()) { |
| 144 return false; |
| 145 } |
| 146 return true; |
| 147 } |
| 148 |
136 } // namespace | 149 } // namespace |
137 | 150 |
138 WebCryptoImpl::WebCryptoImpl() { | 151 WebCryptoImpl::WebCryptoImpl() { |
139 Init(); | 152 Init(); |
140 } | 153 } |
141 | 154 |
142 void WebCryptoImpl::encrypt( | 155 void WebCryptoImpl::encrypt( |
143 const blink::WebCryptoAlgorithm& algorithm, | 156 const blink::WebCryptoAlgorithm& algorithm, |
144 const blink::WebCryptoKey& key, | 157 const blink::WebCryptoKey& key, |
145 const unsigned char* data, | 158 const unsigned char* data, |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 // inconsistent with input: error | 489 // inconsistent with input: error |
477 // 4. JWK alg valid AND input algorithm specified, both consistent: use | 490 // 4. JWK alg valid AND input algorithm specified, both consistent: use |
478 // input value (because it has potentially more details) | 491 // input value (because it has potentially more details) |
479 // 5. JWK alg missing AND input algorithm isNull: error | 492 // 5. JWK alg missing AND input algorithm isNull: error |
480 // 6. JWK alg missing AND input algorithm specified: use input value | 493 // 6. JWK alg missing AND input algorithm specified: use input value |
481 blink::WebCryptoAlgorithm algorithm = | 494 blink::WebCryptoAlgorithm algorithm = |
482 blink::WebCryptoAlgorithm::createNull(); | 495 blink::WebCryptoAlgorithm::createNull(); |
483 std::string jwk_alg_value; | 496 std::string jwk_alg_value; |
484 if (dict_value->GetString("alg", &jwk_alg_value)) { | 497 if (dict_value->GetString("alg", &jwk_alg_value)) { |
485 // JWK alg present | 498 // JWK alg present |
| 499 |
| 500 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can |
| 501 // only be from the RSA family. |
| 502 |
486 const blink::WebCryptoAlgorithm jwk_algorithm = | 503 const blink::WebCryptoAlgorithm jwk_algorithm = |
487 jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value); | 504 jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value); |
488 if (jwk_algorithm.isNull()) { | 505 if (jwk_algorithm.isNull()) { |
489 // JWK alg unrecognized | 506 // JWK alg unrecognized |
490 return false; // case 1 | 507 return false; // case 1 |
491 } | 508 } |
492 // JWK alg valid | 509 // JWK alg valid |
493 if (algorithm_or_null.isNull()) { | 510 if (algorithm_or_null.isNull()) { |
494 // input algorithm not specified | 511 // input algorithm not specified |
495 algorithm = jwk_algorithm; // case 2 | 512 algorithm = jwk_algorithm; // case 2 |
(...skipping 28 matching lines...) Expand all Loading... |
524 return false; | 541 return false; |
525 } | 542 } |
526 if ((jwk_usage_mask & usage_mask) != usage_mask) { | 543 if ((jwk_usage_mask & usage_mask) != usage_mask) { |
527 // A usage_mask must be a subset of jwk_usage_mask. | 544 // A usage_mask must be a subset of jwk_usage_mask. |
528 return false; | 545 return false; |
529 } | 546 } |
530 } | 547 } |
531 | 548 |
532 // JWK keying material --> ImportKeyInternal() | 549 // JWK keying material --> ImportKeyInternal() |
533 if (jwk_kty_value == "oct") { | 550 if (jwk_kty_value == "oct") { |
534 std::string jwk_k_value_url64; | 551 |
535 if (!dict_value->GetString("k", &jwk_k_value_url64)) | 552 std::string jwk_k_value; |
| 553 if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value)) |
536 return false; | 554 return false; |
537 std::string jwk_k_value; | |
538 if (!Base64DecodeUrlSafe(jwk_k_value_url64, &jwk_k_value) || | |
539 !jwk_k_value.size()) { | |
540 return false; | |
541 } | |
542 | 555 |
543 // TODO(padolph): Some JWK alg ID's embed information about the key length | 556 // TODO(padolph): Some JWK alg ID's embed information about the key length |
544 // in the alg ID string. For example "A128" implies the JWK carries 128 bits | 557 // in the alg ID string. For example "A128" implies the JWK carries 128 bits |
545 // of key material, and "HS512" implies the JWK carries _at least_ 512 bits | 558 // of key material, and "HS512" implies the JWK carries _at least_ 512 bits |
546 // of key material. For such keys validate the actual key length against the | 559 // of key material. For such keys validate the actual key length against the |
547 // value in the ID. | 560 // value in the ID. |
548 | 561 |
549 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, | 562 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, |
550 reinterpret_cast<const uint8*>(jwk_k_value.data()), | 563 reinterpret_cast<const uint8*>(jwk_k_value.data()), |
551 jwk_k_value.size(), | 564 jwk_k_value.size(), |
552 algorithm, | 565 algorithm, |
553 extractable, | 566 extractable, |
554 usage_mask, | 567 usage_mask, |
555 key); | 568 key); |
556 } else if (jwk_kty_value == "RSA") { | 569 } else if (jwk_kty_value == "RSA") { |
557 // TODO(padolph): JWK import RSA public key | 570 |
558 return false; | 571 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry |
| 572 // in the JWK, while an RSA private key must have those, plus at least a "d" |
| 573 // (private exponent) entry. |
| 574 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, |
| 575 // section 6.3. |
| 576 |
| 577 // RSA private key import is not currently supported, so fail here if a "d" |
| 578 // entry is found. |
| 579 // TODO(padolph): Support RSA private key import. |
| 580 if (dict_value->HasKey("d")) |
| 581 return false; |
| 582 |
| 583 std::string jwk_n_value; |
| 584 if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value)) |
| 585 return false; |
| 586 std::string jwk_e_value; |
| 587 if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value)) |
| 588 return false; |
| 589 |
| 590 return ImportRsaPublicKeyInternal( |
| 591 reinterpret_cast<const uint8*>(jwk_n_value.data()), |
| 592 jwk_n_value.size(), |
| 593 reinterpret_cast<const uint8*>(jwk_e_value.data()), |
| 594 jwk_e_value.size(), |
| 595 algorithm, |
| 596 extractable, |
| 597 usage_mask, |
| 598 key); |
| 599 |
559 } else { | 600 } else { |
560 return false; | 601 return false; |
561 } | 602 } |
562 | 603 |
563 return true; | 604 return true; |
564 } | 605 } |
565 | 606 |
566 } // namespace content | 607 } // namespace content |
OLD | NEW |