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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 blink::WebCryptoAlgorithmIdSha1>); | 85 blink::WebCryptoAlgorithmIdSha1>); |
86 alg_to_info_["HS256"] = | 86 alg_to_info_["HS256"] = |
87 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, | 87 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
88 blink::WebCryptoAlgorithmIdSha256>); | 88 blink::WebCryptoAlgorithmIdSha256>); |
89 alg_to_info_["HS384"] = | 89 alg_to_info_["HS384"] = |
90 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, | 90 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
91 blink::WebCryptoAlgorithmIdSha384>); | 91 blink::WebCryptoAlgorithmIdSha384>); |
92 alg_to_info_["HS512"] = | 92 alg_to_info_["HS512"] = |
93 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, | 93 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
94 blink::WebCryptoAlgorithmIdSha512>); | 94 blink::WebCryptoAlgorithmIdSha512>); |
| 95 alg_to_info_["RS1"] = |
| 96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
| 97 blink::WebCryptoAlgorithmIdSha1>); |
95 alg_to_info_["RS256"] = | 98 alg_to_info_["RS256"] = |
96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | 99 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
97 blink::WebCryptoAlgorithmIdSha256>); | 100 blink::WebCryptoAlgorithmIdSha256>); |
98 alg_to_info_["RS384"] = | 101 alg_to_info_["RS384"] = |
99 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | 102 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
100 blink::WebCryptoAlgorithmIdSha384>); | 103 blink::WebCryptoAlgorithmIdSha384>); |
101 alg_to_info_["RS512"] = | 104 alg_to_info_["RS512"] = |
102 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | 105 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
103 blink::WebCryptoAlgorithmIdSha512>); | 106 blink::WebCryptoAlgorithmIdSha512>); |
104 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 107 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 // base64url encoding of the raw key. | 291 // base64url encoding of the raw key. |
289 DCHECK(!raw_key.isNull()); | 292 DCHECK(!raw_key.isNull()); |
290 DCHECK(raw_key.data()); | 293 DCHECK(raw_key.data()); |
291 DCHECK(raw_key.byteLength()); | 294 DCHECK(raw_key.byteLength()); |
292 unsigned int key_length_bytes = raw_key.byteLength(); | 295 unsigned int key_length_bytes = raw_key.byteLength(); |
293 const base::StringPiece key_str(static_cast<const char*>(raw_key.data()), | 296 const base::StringPiece key_str(static_cast<const char*>(raw_key.data()), |
294 key_length_bytes); | 297 key_length_bytes); |
295 jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str)); | 298 jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str)); |
296 } | 299 } |
297 | 300 |
| 301 // Writes an RSA public key to a JWK dictionary |
| 302 void WriteRsaPublicKey(const std::vector<uint8>& modulus, |
| 303 const std::vector<uint8>& public_exponent, |
| 304 base::DictionaryValue* jwk_dict) { |
| 305 DCHECK(jwk_dict); |
| 306 DCHECK(modulus.size()); |
| 307 DCHECK(public_exponent.size()); |
| 308 jwk_dict->SetString("kty", "RSA"); |
| 309 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus)); |
| 310 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent)); |
| 311 } |
| 312 |
298 // Writes a Web Crypto usage mask to a JWK dictionary. | 313 // Writes a Web Crypto usage mask to a JWK dictionary. |
299 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, | 314 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, |
300 base::DictionaryValue* jwk_dict) { | 315 base::DictionaryValue* jwk_dict) { |
301 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); | 316 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); |
302 } | 317 } |
303 | 318 |
304 // Writes a Web Crypto extractable value to a JWK dictionary. | 319 // Writes a Web Crypto extractable value to a JWK dictionary. |
305 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { | 320 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { |
306 jwk_dict->SetBoolean("ext", extractable); | 321 jwk_dict->SetBoolean("ext", extractable); |
307 } | 322 } |
308 | 323 |
309 // Writes a Web Crypto algorithm to a JWK dictionary. | 324 // Writes a Web Crypto algorithm to a JWK dictionary. |
310 Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm, | 325 Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm, |
311 unsigned int raw_key_length_bytes, | |
312 base::DictionaryValue* jwk_dict) { | 326 base::DictionaryValue* jwk_dict) { |
313 switch (algorithm.paramsType()) { | 327 switch (algorithm.paramsType()) { |
314 case blink::WebCryptoKeyAlgorithmParamsTypeAes: { | 328 case blink::WebCryptoKeyAlgorithmParamsTypeAes: { |
| 329 DCHECK(algorithm.aesParams()); |
315 const char* aes_prefix = ""; | 330 const char* aes_prefix = ""; |
316 switch (raw_key_length_bytes) { | 331 switch (algorithm.aesParams()->lengthBits()) { |
317 case 16: | 332 case 128: |
318 aes_prefix = "A128"; | 333 aes_prefix = "A128"; |
319 break; | 334 break; |
320 case 24: | 335 case 192: |
321 aes_prefix = "A192"; | 336 aes_prefix = "A192"; |
322 break; | 337 break; |
323 case 32: | 338 case 256: |
324 aes_prefix = "A256"; | 339 aes_prefix = "A256"; |
325 break; | 340 break; |
326 default: | 341 default: |
327 NOTREACHED(); // bad key length means algorithm was built improperly | 342 NOTREACHED(); // bad key length means algorithm was built improperly |
328 return Status::ErrorUnexpected(); | 343 return Status::ErrorUnexpected(); |
329 } | 344 } |
330 const char* aes_suffix = ""; | 345 const char* aes_suffix = ""; |
331 switch (algorithm.id()) { | 346 switch (algorithm.id()) { |
332 case blink::WebCryptoAlgorithmIdAesCbc: | 347 case blink::WebCryptoAlgorithmIdAesCbc: |
333 aes_suffix = "CBC"; | 348 aes_suffix = "CBC"; |
(...skipping 29 matching lines...) Expand all Loading... |
363 case blink::WebCryptoAlgorithmIdSha512: | 378 case blink::WebCryptoAlgorithmIdSha512: |
364 jwk_dict->SetString("alg", "HS512"); | 379 jwk_dict->SetString("alg", "HS512"); |
365 break; | 380 break; |
366 default: | 381 default: |
367 NOTREACHED(); | 382 NOTREACHED(); |
368 return Status::ErrorUnexpected(); | 383 return Status::ErrorUnexpected(); |
369 } | 384 } |
370 break; | 385 break; |
371 } | 386 } |
372 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: | 387 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
| 388 switch (algorithm.id()) { |
| 389 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| 390 jwk_dict->SetString("alg", "RSA1_5"); |
| 391 break; |
| 392 default: |
| 393 NOTREACHED(); |
| 394 return Status::ErrorUnexpected(); |
| 395 } |
| 396 break; |
373 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: | 397 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
374 // TODO(padolph): Handle RSA key | 398 switch (algorithm.rsaHashedParams()->hash().id()) { |
375 return Status::ErrorUnsupported(); | 399 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 400 jwk_dict->SetString("alg", "RSA-OAEP"); |
| 401 break; |
| 402 case blink::WebCryptoAlgorithmIdSha1: |
| 403 jwk_dict->SetString("alg", "RS1"); |
| 404 break; |
| 405 case blink::WebCryptoAlgorithmIdSha256: |
| 406 jwk_dict->SetString("alg", "RS256"); |
| 407 break; |
| 408 case blink::WebCryptoAlgorithmIdSha384: |
| 409 jwk_dict->SetString("alg", "RS384"); |
| 410 break; |
| 411 case blink::WebCryptoAlgorithmIdSha512: |
| 412 jwk_dict->SetString("alg", "RS512"); |
| 413 break; |
| 414 default: |
| 415 NOTREACHED(); |
| 416 return Status::ErrorUnexpected(); |
| 417 } |
| 418 break; |
376 default: | 419 default: |
377 return Status::ErrorUnsupported(); | 420 return Status::ErrorUnsupported(); |
378 } | 421 } |
379 return Status::Success(); | 422 return Status::Success(); |
380 } | 423 } |
381 | 424 |
| 425 bool IsRsaPublicKey(const blink::WebCryptoKey& key) { |
| 426 if (key.type() != blink::WebCryptoKeyTypePublic) |
| 427 return false; |
| 428 const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id(); |
| 429 return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
| 430 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
| 431 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep; |
| 432 } |
| 433 |
| 434 // TODO(padolph): This function is duplicated in shared_crypto.cc |
| 435 Status ToPlatformPublicKey(const blink::WebCryptoKey& key, |
| 436 platform::PublicKey** out) { |
| 437 *out = static_cast<platform::Key*>(key.handle())->AsPublicKey(); |
| 438 if (!*out) |
| 439 return Status::ErrorUnexpectedKeyType(); |
| 440 return Status::Success(); |
| 441 } |
| 442 |
382 } // namespace | 443 } // namespace |
383 | 444 |
384 Status ImportKeyJwk(const CryptoData& key_data, | 445 Status ImportKeyJwk(const CryptoData& key_data, |
385 const blink::WebCryptoAlgorithm& algorithm, | 446 const blink::WebCryptoAlgorithm& algorithm, |
386 bool extractable, | 447 bool extractable, |
387 blink::WebCryptoKeyUsageMask usage_mask, | 448 blink::WebCryptoKeyUsageMask usage_mask, |
388 blink::WebCryptoKey* key) { | 449 blink::WebCryptoKey* key) { |
389 // TODO(padolph): Generalize this comment to include export, and move to top | 450 // TODO(padolph): Generalize this comment to include export, and move to top |
390 // of file. | 451 // of file. |
391 | 452 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 // | 532 // |
472 // - alg (Algorithm) | 533 // - alg (Algorithm) |
473 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 | 534 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 |
474 // +--------------+-------------------------------------------------------+ | 535 // +--------------+-------------------------------------------------------+ |
475 // | Digital Signature or MAC Algorithm | | 536 // | Digital Signature or MAC Algorithm | |
476 // +--------------+-------------------------------------------------------+ | 537 // +--------------+-------------------------------------------------------+ |
477 // | "HS1" | HMAC using SHA-1 hash algorithm | | 538 // | "HS1" | HMAC using SHA-1 hash algorithm | |
478 // | "HS256" | HMAC using SHA-256 hash algorithm | | 539 // | "HS256" | HMAC using SHA-256 hash algorithm | |
479 // | "HS384" | HMAC using SHA-384 hash algorithm | | 540 // | "HS384" | HMAC using SHA-384 hash algorithm | |
480 // | "HS512" | HMAC using SHA-512 hash algorithm | | 541 // | "HS512" | HMAC using SHA-512 hash algorithm | |
| 542 // | "RS1" | RSASSA using SHA-1 hash algorithm |
481 // | "RS256" | RSASSA using SHA-256 hash algorithm | | 543 // | "RS256" | RSASSA using SHA-256 hash algorithm | |
482 // | "RS384" | RSASSA using SHA-384 hash algorithm | | 544 // | "RS384" | RSASSA using SHA-384 hash algorithm | |
483 // | "RS512" | RSASSA using SHA-512 hash algorithm | | 545 // | "RS512" | RSASSA using SHA-512 hash algorithm | |
484 // +--------------+-------------------------------------------------------| | 546 // +--------------+-------------------------------------------------------| |
485 // | Key Management Algorithm | | 547 // | Key Management Algorithm | |
486 // +--------------+-------------------------------------------------------+ | 548 // +--------------+-------------------------------------------------------+ |
487 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | | 549 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | |
488 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | | 550 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | |
489 // | | (OAEP) [RFC3447], with the default parameters | | 551 // | | (OAEP) [RFC3447], with the default parameters | |
490 // | | specified by RFC3447 in Section A.2.1 | | 552 // | | specified by RFC3447 in Section A.2.1 | |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 CryptoData(jwk_e_value), | 769 CryptoData(jwk_e_value), |
708 key); | 770 key); |
709 | 771 |
710 } | 772 } |
711 | 773 |
712 return Status::ErrorJwkUnrecognizedKty(); | 774 return Status::ErrorJwkUnrecognizedKty(); |
713 } | 775 } |
714 | 776 |
715 Status ExportKeyJwk(const blink::WebCryptoKey& key, | 777 Status ExportKeyJwk(const blink::WebCryptoKey& key, |
716 blink::WebArrayBuffer* buffer) { | 778 blink::WebArrayBuffer* buffer) { |
| 779 DCHECK(key.extractable()); |
717 base::DictionaryValue jwk_dict; | 780 base::DictionaryValue jwk_dict; |
718 Status status = Status::Error(); | 781 Status status = Status::Error(); |
719 blink::WebArrayBuffer exported_key; | |
720 | 782 |
721 if (key.type() == blink::WebCryptoKeyTypeSecret) { | 783 switch (key.type()) { |
722 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); | 784 case blink::WebCryptoKeyTypeSecret: { |
723 if (status.IsError()) | 785 blink::WebArrayBuffer exported_key; |
724 return status; | 786 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); |
725 WriteSecretKey(exported_key, &jwk_dict); | 787 if (status.IsError()) |
726 } else { | 788 return status; |
727 // TODO(padolph): Handle asymmetric keys, at least the public key. | 789 WriteSecretKey(exported_key, &jwk_dict); |
728 return Status::ErrorUnsupported(); | 790 break; |
| 791 } |
| 792 case blink::WebCryptoKeyTypePublic: { |
| 793 // Currently only RSA public key export is supported. |
| 794 if (!IsRsaPublicKey(key)) |
| 795 return Status::ErrorUnsupported(); |
| 796 platform::PublicKey* public_key; |
| 797 status = ToPlatformPublicKey(key, &public_key); |
| 798 if (status.IsError()) |
| 799 return status; |
| 800 std::vector<uint8> modulus; |
| 801 std::vector<uint8> public_exponent; |
| 802 status = |
| 803 platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent); |
| 804 if (status.IsError()) |
| 805 return status; |
| 806 WriteRsaPublicKey(modulus, public_exponent, &jwk_dict); |
| 807 break; |
| 808 } |
| 809 case blink::WebCryptoKeyTypePrivate: // TODO(padolph) |
| 810 default: |
| 811 return Status::ErrorUnsupported(); |
729 } | 812 } |
730 | 813 |
731 WriteKeyOps(key.usages(), &jwk_dict); | 814 WriteKeyOps(key.usages(), &jwk_dict); |
732 WriteExt(key.extractable(), &jwk_dict); | 815 WriteExt(key.extractable(), &jwk_dict); |
733 status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict); | 816 status = WriteAlg(key.algorithm(), &jwk_dict); |
734 if (status.IsError()) | 817 if (status.IsError()) |
735 return status; | 818 return status; |
736 | 819 |
737 std::string json; | 820 std::string json; |
738 base::JSONWriter::Write(&jwk_dict, &json); | 821 base::JSONWriter::Write(&jwk_dict, &json); |
739 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), | 822 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), |
740 json.size()); | 823 json.size()); |
741 return Status::Success(); | 824 return Status::Success(); |
742 } | 825 } |
743 | 826 |
744 } // namespace webcrypto | 827 } // namespace webcrypto |
745 | 828 |
746 } // namespace content | 829 } // namespace content |
OLD | NEW |