Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Side by Side Diff: content/child/webcrypto/jwk.cc

Issue 416993009: [webcrypto] JWK: Reject keys with non-minimal bigintegers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address sleevi comment Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | content/child/webcrypto/nss/rsa_key_nss.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "jwk.h" 5 #include "jwk.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <map> 9 #include <map>
10 10
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 Status status = GetJwkString(dict, path, &base64_string); 315 Status status = GetJwkString(dict, path, &base64_string);
316 if (status.IsError()) 316 if (status.IsError())
317 return status; 317 return status;
318 318
319 if (!Base64DecodeUrlSafe(base64_string, result)) 319 if (!Base64DecodeUrlSafe(base64_string, result))
320 return Status::ErrorJwkBase64Decode(path); 320 return Status::ErrorJwkBase64Decode(path);
321 321
322 return Status::Success(); 322 return Status::Success();
323 } 323 }
324 324
325 // Extracts the optional string property with key |path| from |dict| and saves 325 // Extracts the required base64url property, which is interpreted as being a
326 // the base64url-decoded bytes to |*result|. If the property exist and is not a 326 // big-endian unsigned integer.
327 // string, or could not be base64url-decoded, returns an error. In the case 327 Status GetJwkBigInteger(base::DictionaryValue* dict,
328 // where the property does not exist, |result| is guaranteed to be empty. 328 const std::string& path,
329 Status GetOptionalJwkBytes(base::DictionaryValue* dict, 329 std::string* result) {
330 const std::string& path, 330 Status status = GetJwkBytes(dict, path, result);
331 std::string* result,
332 bool* property_exists) {
333 std::string base64_string;
334 Status status =
335 GetOptionalJwkString(dict, path, &base64_string, property_exists);
336 if (status.IsError()) 331 if (status.IsError())
337 return status; 332 return status;
338 333
339 if (!*property_exists) { 334 if (result->empty())
340 result->clear(); 335 return Status::ErrorJwkEmptyBigInteger(path);
341 return Status::Success();
342 }
343 336
344 if (!Base64DecodeUrlSafe(base64_string, result)) 337 // The JWA spec says that "The octet sequence MUST utilize the minimum number
345 return Status::ErrorJwkBase64Decode(path); 338 // of octets to represent the value." This means there shouldn't be any
339 // leading zeros.
340 if (result->size() > 1 && (*result)[0] == 0)
341 return Status::ErrorJwkBigIntegerHasLeadingZero(path);
346 342
347 return Status::Success(); 343 return Status::Success();
348 } 344 }
349 345
350 // Extracts the optional boolean property with key |path| from |dict| and saves 346 // Extracts the optional boolean property with key |path| from |dict| and saves
351 // the result to |*result| if it was found. If the property exists and is not a 347 // the result to |*result| if it was found. If the property exists and is not a
352 // boolean, returns an error. Otherwise returns success, and sets 348 // boolean, returns an error. Otherwise returns success, and sets
353 // |*property_exists| if it was found. 349 // |*property_exists| if it was found.
354 Status GetOptionalJwkBool(base::DictionaryValue* dict, 350 Status GetOptionalJwkBool(base::DictionaryValue* dict,
355 const std::string& path, 351 const std::string& path,
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 return status; 639 return status;
644 640
645 if (kty != "RSA") 641 if (kty != "RSA")
646 return Status::ErrorJwkUnexpectedKty("RSA"); 642 return Status::ErrorJwkUnexpectedKty("RSA");
647 643
648 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry 644 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
649 // in the JWK, while an RSA private key must have those, plus at least a "d" 645 // in the JWK, while an RSA private key must have those, plus at least a "d"
650 // (private exponent) entry. 646 // (private exponent) entry.
651 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, 647 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
652 // section 6.3. 648 // section 6.3.
653 status = GetJwkBytes(dict.get(), "n", &result->n); 649 status = GetJwkBigInteger(dict.get(), "n", &result->n);
654 if (status.IsError()) 650 if (status.IsError())
655 return status; 651 return status;
656 status = GetJwkBytes(dict.get(), "e", &result->e); 652 status = GetJwkBigInteger(dict.get(), "e", &result->e);
657 if (status.IsError()) 653 if (status.IsError())
658 return status; 654 return status;
659 655
660 result->is_private_key = dict->HasKey("d"); 656 result->is_private_key = dict->HasKey("d");
661 if (!result->is_private_key) 657 if (!result->is_private_key)
662 return Status::Success(); 658 return Status::Success();
663 659
664 status = GetJwkBytes(dict.get(), "d", &result->d); 660 status = GetJwkBigInteger(dict.get(), "d", &result->d);
665 if (status.IsError()) 661 if (status.IsError())
666 return status; 662 return status;
667 663
668 // The "p", "q", "dp", "dq", and "qi" properties are optional. Treat these 664 // The "p", "q", "dp", "dq", and "qi" properties are optional in the JWA
669 // properties the same if they are unspecified, as if they were specified-but 665 // spec. However they are required by Chromium's WebCrypto implementation.
670 // empty, since ImportRsaPrivateKey() doesn't do validation checks anyway.
671 666
672 bool has_p; 667 status = GetJwkBigInteger(dict.get(), "p", &result->p);
673 status = GetOptionalJwkBytes(dict.get(), "p", &result->p, &has_p);
674 if (status.IsError()) 668 if (status.IsError())
675 return status; 669 return status;
676 670
677 bool has_q; 671 status = GetJwkBigInteger(dict.get(), "q", &result->q);
678 status = GetOptionalJwkBytes(dict.get(), "q", &result->q, &has_q);
679 if (status.IsError()) 672 if (status.IsError())
680 return status; 673 return status;
681 674
682 bool has_dp; 675 status = GetJwkBigInteger(dict.get(), "dp", &result->dp);
683 status = GetOptionalJwkBytes(dict.get(), "dp", &result->dp, &has_dp);
684 if (status.IsError()) 676 if (status.IsError())
685 return status; 677 return status;
686 678
687 bool has_dq; 679 status = GetJwkBigInteger(dict.get(), "dq", &result->dq);
688 status = GetOptionalJwkBytes(dict.get(), "dq", &result->dq, &has_dq);
689 if (status.IsError()) 680 if (status.IsError())
690 return status; 681 return status;
691 682
692 bool has_qi; 683 status = GetJwkBigInteger(dict.get(), "qi", &result->qi);
693 status = GetOptionalJwkBytes(dict.get(), "qi", &result->qi, &has_qi);
694 if (status.IsError()) 684 if (status.IsError())
695 return status; 685 return status;
696 686
697 int num_optional_properties = has_p + has_q + has_dp + has_dq + has_qi;
698 if (num_optional_properties != 0 && num_optional_properties != 5)
699 return Status::ErrorJwkIncompleteOptionalRsaPrivateKey();
700
701 return Status::Success(); 687 return Status::Success();
702 } 688 }
703 689
704 const char* GetJwkHmacAlgorithmName(blink::WebCryptoAlgorithmId hash) { 690 const char* GetJwkHmacAlgorithmName(blink::WebCryptoAlgorithmId hash) {
705 switch (hash) { 691 switch (hash) {
706 case blink::WebCryptoAlgorithmIdSha1: 692 case blink::WebCryptoAlgorithmIdSha1:
707 return "HS1"; 693 return "HS1";
708 case blink::WebCryptoAlgorithmIdSha256: 694 case blink::WebCryptoAlgorithmIdSha256:
709 return "HS256"; 695 return "HS256";
710 case blink::WebCryptoAlgorithmIdSha384: 696 case blink::WebCryptoAlgorithmIdSha384:
711 return "HS384"; 697 return "HS384";
712 case blink::WebCryptoAlgorithmIdSha512: 698 case blink::WebCryptoAlgorithmIdSha512:
713 return "HS512"; 699 return "HS512";
714 default: 700 default:
715 return NULL; 701 return NULL;
716 } 702 }
717 } 703 }
718 704
719 } // namespace webcrypto 705 } // namespace webcrypto
720 706
721 } // namespace content 707 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/child/webcrypto/nss/rsa_key_nss.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698