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