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

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_unittest.cc

Issue 25906002: [webcrypto] Add JWK import for HMAC and AES-CBC key. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed some DCHECK's and TODO's. Created 7 years, 2 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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 "webcrypto_impl.h" 5 #include "webcrypto_impl.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/json/json_writer.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
11 #include "content/public/renderer/content_renderer_client.h" 12 #include "content/public/renderer/content_renderer_client.h"
12 #include "content/renderer/renderer_webkitplatformsupport_impl.h" 13 #include "content/renderer/renderer_webkitplatformsupport_impl.h"
13 #include "content/renderer/webcrypto/webcrypto_impl.h" 14 #include "content/renderer/webcrypto/webcrypto_impl.h"
14 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" 16 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
16 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 return &data[0]; 53 return &data[0];
53 } 54 }
54 55
55 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm( 56 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm(
56 const std::vector<uint8>& iv) { 57 const std::vector<uint8>& iv) {
57 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( 58 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(
58 WebKit::WebCryptoAlgorithmIdAesCbc, 59 WebKit::WebCryptoAlgorithmIdAesCbc,
59 new WebKit::WebCryptoAesCbcParams(Start(iv), iv.size())); 60 new WebKit::WebCryptoAesCbcParams(Start(iv), iv.size()));
60 } 61 }
61 62
63 std::vector<unsigned char> MakeJsonVector(const std::string& json_string) {
64 return std::vector<unsigned char>(json_string.begin(), json_string.end());
65 }
66
67 std::vector<unsigned char> MakeJsonVector(const base::DictionaryValue& dict) {
68 std::string json;
69 base::JSONWriter::Write(&dict, &json);
70 return MakeJsonVector(json);
71 }
72
62 } // namespace 73 } // namespace
63 74
64 namespace content { 75 namespace content {
65 76
66 class WebCryptoImplTest : public testing::Test { 77 class WebCryptoImplTest : public testing::Test {
67 protected: 78 protected:
68 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( 79 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString(
69 const std::string& key_hex, 80 const std::string& key_hex,
70 const WebKit::WebCryptoAlgorithm& algorithm, 81 const WebKit::WebCryptoAlgorithm& algorithm,
71 WebKit::WebCryptoKeyUsageMask usage) { 82 WebKit::WebCryptoKeyUsageMask usage) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 180
170 bool DecryptInternal( 181 bool DecryptInternal(
171 const WebKit::WebCryptoAlgorithm& algorithm, 182 const WebKit::WebCryptoAlgorithm& algorithm,
172 const WebKit::WebCryptoKey& key, 183 const WebKit::WebCryptoKey& key,
173 const std::vector<uint8>& data, 184 const std::vector<uint8>& data,
174 WebKit::WebArrayBuffer* buffer) { 185 WebKit::WebArrayBuffer* buffer) {
175 return crypto_.DecryptInternal( 186 return crypto_.DecryptInternal(
176 algorithm, key, Start(data), data.size(), buffer); 187 algorithm, key, Start(data), data.size(), buffer);
177 } 188 }
178 189
190 bool ImportKeyJwk(
191 const unsigned char* key_data,
192 unsigned key_data_size,
193 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
194 WebKit::WebCryptoKeyType* type,
195 bool* extractable,
196 WebKit::WebCryptoAlgorithm* algorithm,
197 WebKit::WebCryptoKeyUsageMask* usage_mask) {
198 return crypto_.ImportKeyJwk(key_data,
199 key_data_size,
200 handle,
201 type,
202 extractable,
203 algorithm,
204 usage_mask);
205 }
206
179 private: 207 private:
180 WebCryptoImpl crypto_; 208 WebCryptoImpl crypto_;
181 }; 209 };
182 210
183 // TODO(padolph) Enable these tests for OpenSSL once matching impl is available 211 // TODO(padolph) Enable these tests for OpenSSL once matching impl is available
184 #if !defined(USE_OPENSSL) 212 #if !defined(USE_OPENSSL)
185 213
186 TEST_F(WebCryptoImplTest, DigestSampleSets) { 214 TEST_F(WebCryptoImplTest, DigestSampleSets) {
187 // The results are stored here in hex format for readability. 215 // The results are stored here in hex format for readability.
188 // 216 //
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 285
258 WebKit::WebCryptoAlgorithm algorithm = CreateAlgorithm(test.algorithm); 286 WebKit::WebCryptoAlgorithm algorithm = CreateAlgorithm(test.algorithm);
259 std::vector<uint8> input = HexStringToBytes(test.hex_input); 287 std::vector<uint8> input = HexStringToBytes(test.hex_input);
260 288
261 WebKit::WebArrayBuffer output; 289 WebKit::WebArrayBuffer output;
262 ASSERT_TRUE(DigestInternal(algorithm, input, &output)); 290 ASSERT_TRUE(DigestInternal(algorithm, input, &output));
263 ExpectArrayBufferMatchesHex(test.hex_result, output); 291 ExpectArrayBufferMatchesHex(test.hex_result, output);
264 } 292 }
265 } 293 }
266 294
267 #endif // #if !defined(USE_OPENSSL) 295 #endif // #if !defined(USE_OPENSSL)
268 296
269 TEST_F(WebCryptoImplTest, HMACSampleSets) { 297 TEST_F(WebCryptoImplTest, HMACSampleSets) {
270 struct TestCase { 298 struct TestCase {
271 WebKit::WebCryptoAlgorithmId algorithm; 299 WebKit::WebCryptoAlgorithmId algorithm;
272 const char* key; 300 const char* key;
273 const char* message; 301 const char* message;
274 const char* mac; 302 const char* mac;
275 }; 303 };
276 304
277 const TestCase kTests[] = { 305 const TestCase kTests[] = {
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 if (cipher_text.size() > 3) { 622 if (cipher_text.size() > 3) {
595 EXPECT_FALSE(DecryptInternal(CreateAesCbcAlgorithm(iv), 623 EXPECT_FALSE(DecryptInternal(CreateAesCbcAlgorithm(iv),
596 key, 624 key,
597 &cipher_text[0], 625 &cipher_text[0],
598 cipher_text.size() - 3, 626 cipher_text.size() - 3,
599 &output)); 627 &output));
600 } 628 }
601 } 629 }
602 } 630 }
603 631
604 #endif // !defined(USE_OPENSSL) 632 #endif // !defined(USE_OPENSSL)
633
634 TEST_F(WebCryptoImplTest, ImportJwkBadJwk) {
635
636 WebKit::WebCryptoKeyType type;
637 scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
638 std::vector<uint8> iv(16);
639 WebKit::WebCryptoAlgorithm algorithm = CreateAesCbcAlgorithm(iv);
640 bool extractable = false;
641 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign;
642
643 // Empty JSON
644 std::vector<unsigned char> json_vec = MakeJsonVector("");
645 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
646 json_vec.size(),
647 &handle,
648 &type,
649 &extractable,
650 &algorithm,
651 &usage_mask));
652
653 // Bad JSON
654 json_vec = MakeJsonVector(
655 "{"
656 "\"kty\" : \"oct\","
657 "\"alg\" : \"HS256\","
658 "\"use\" : "
659 );
660 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
661 json_vec.size(),
662 &handle,
663 &type,
664 &extractable,
665 &algorithm,
666 &usage_mask));
667
668 // Note, each subtest below resets the dictionary so there is less chance of
669 // failure if they happen to be reordered.
670
671 // Invalid kty
672 base::DictionaryValue dict;
673 dict.SetString("kty", "foo");
674 dict.SetString("alg", "HS256");
675 dict.SetString("use", "sig");
676 dict.SetBoolean("extractable", true);
677 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
678 json_vec = MakeJsonVector(dict);
679 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
680 json_vec.size(),
681 &handle,
682 &type,
683 &extractable,
684 &algorithm,
685 &usage_mask));
686 dict.SetString("kty", "oct");
687
688 // Missing kty
689 dict.Remove("kty", NULL);
690 json_vec = MakeJsonVector(dict);
691 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
692 json_vec.size(),
693 &handle,
694 &type,
695 &extractable,
696 &algorithm,
697 &usage_mask));
698 dict.SetString("kty", "oct");
699
700 // Invalid alg
701 dict.SetString("alg", "foo");
702 json_vec = MakeJsonVector(dict);
703 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
704 json_vec.size(),
705 &handle,
706 &type,
707 &extractable,
708 &algorithm,
709 &usage_mask));
710 dict.SetString("alg", "HS256");
711
712 // Invalid use
713 dict.SetString("use", "foo");
714 json_vec = MakeJsonVector(dict);
715 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
716 json_vec.size(),
717 &handle,
718 &type,
719 &extractable,
720 &algorithm,
721 &usage_mask));
722 dict.SetString("use", "sig");
723
724 // Missing k when kty = "oct"
725 dict.Remove("k", NULL);
726 json_vec = MakeJsonVector(dict);
727 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
728 json_vec.size(),
729 &handle,
730 &type,
731 &extractable,
732 &algorithm,
733 &usage_mask));
734 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
735
736 // Bad encoding for k
737 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3r #$% jhdY8vOkbIvh4lxTuMao9Y_--hdg");
738 json_vec = MakeJsonVector(dict);
739 EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
740 json_vec.size(),
741 &handle,
742 &type,
743 &extractable,
744 &algorithm,
745 &usage_mask));
746 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
747
748 // TODO(padolph) RSA public key bad data:
749 // Missing n or e when kty = "RSA"
750 // Bad encoding for n or e
751 // Size check on n??
752 // Value check on e??
753 }
754
755 TEST_F(WebCryptoImplTest, ImportJwkCollision) {
756
757 WebKit::WebCryptoKeyType type;
758 scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
759 std::vector<uint8> iv(16);
760 WebKit::WebCryptoAlgorithm algorithm = CreateAesCbcAlgorithm(iv);
761 bool extractable = false;
762 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign;
763
764 // Collision rules when JWK value exists:
765 // Input _type_ should be ignored.
766 // Input _algorithm_ should be overridden by the JWK value.
767 // Output _extractable_ should be AND of input and JWK value.
768 // Input _usage_mask_ should be overridden by the JWK value.
769 type = WebKit::WebCryptoKeyTypePublic;
770 algorithm = CreateAesCbcAlgorithm(iv);
771 extractable = true;
772 usage_mask = WebKit::WebCryptoKeyUsageWrapKey;
773
774 base::DictionaryValue dict;
775 dict.SetString("kty", "oct");
776 dict.SetString("alg", "HS256");
777 dict.SetString("use", "sig");
778 dict.SetBoolean("extractable", false);
779 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
780 std::vector<unsigned char> json_vec = MakeJsonVector(dict);
781
782 EXPECT_TRUE(ImportKeyJwk(Start(json_vec),
783 json_vec.size(),
784 &handle,
785 &type,
786 &extractable,
787 &algorithm,
788 &usage_mask));
789 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, type);
790 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id());
791 const WebKit::WebCryptoHmacParams* const hmac_params = algorithm.hmacParams();
792 ASSERT_TRUE(hmac_params != NULL);
793 EXPECT_EQ(hmac_params->hash().id(), WebKit::WebCryptoAlgorithmIdSha256);
794 EXPECT_FALSE(extractable);
795 EXPECT_EQ(WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify,
796 usage_mask);
797
798 // Collision rules when JWK value is not present:
799 // Inputs should be unmodified.
800 algorithm = CreateHmacAlgorithm(WebKit::WebCryptoAlgorithmIdSha256);
801 extractable = true;
802 usage_mask = WebKit::WebCryptoKeyUsageSign;
803
804 dict.Clear();
805 dict.SetString("kty", "oct");
806 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
807 json_vec = MakeJsonVector(dict);
808
809 EXPECT_TRUE(ImportKeyJwk(Start(json_vec),
810 json_vec.size(),
811 &handle,
812 &type,
813 &extractable,
814 &algorithm,
815 &usage_mask));
816 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id());
817 EXPECT_TRUE(extractable);
818 EXPECT_EQ(WebKit::WebCryptoKeyUsageSign, usage_mask);
819 }
820
821 TEST_F(WebCryptoImplTest, ImportJwkHappy) {
822
823 WebKit::WebCryptoKeyType type;
824 scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
825 std::vector<uint8> iv(16);
826 WebKit::WebCryptoAlgorithm algorithm = CreateAesCbcAlgorithm(iv);
827 bool extractable = false;
828 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign;
829
830 // Import a symmetric key JWK and HMAC-SHA256 sign()
831 // Uses the first SHA256 test vector from the HMAC sample set above.
832
833 base::DictionaryValue dict;
834 dict.SetString("kty", "oct");
835 dict.SetString("alg", "HS256");
836 dict.SetString("use", "sig");
837 dict.SetBoolean("extractable", true);
838 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
839 std::vector<unsigned char> json_vec = MakeJsonVector(dict);
840
841 EXPECT_TRUE(ImportKeyJwk(Start(json_vec),
842 json_vec.size(),
843 &handle,
844 &type,
845 &extractable,
846 &algorithm,
847 &usage_mask));
848
849 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::create(handle.release(),
850 type, extractable, algorithm, usage_mask);
851
852 const std::vector<uint8> message_raw = HexStringToBytes(
853 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
854 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
855 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
856 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
857
858 WebKit::WebArrayBuffer output;
859
860 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
861
862 const std::string mac_raw =
863 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
864
865 ExpectArrayBufferMatchesHex(mac_raw, output);
866
867 // TODO(padolph)
868 // Import an RSA public key JWK and use it
869 }
605 870
606 } // namespace content 871 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698