| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/stl_util.h" | |
| 6 #include "components/webcrypto/algorithm_dispatch.h" | |
| 7 #include "components/webcrypto/crypto_data.h" | |
| 8 #include "components/webcrypto/status.h" | |
| 9 #include "components/webcrypto/test/test_helpers.h" | |
| 10 #include "components/webcrypto/webcrypto_util.h" | |
| 11 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
| 12 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | |
| 13 | |
| 14 namespace webcrypto { | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm( | |
| 19 unsigned short key_length_bits) { | |
| 20 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw, | |
| 21 key_length_bits); | |
| 22 } | |
| 23 | |
| 24 class WebCryptoAesKwTest : public WebCryptoTestBase {}; | |
| 25 | |
| 26 TEST_F(WebCryptoAesKwTest, GenerateKeyBadLength) { | |
| 27 const unsigned short kKeyLen[] = {0, 127, 257}; | |
| 28 blink::WebCryptoKey key; | |
| 29 for (size_t i = 0; i < arraysize(kKeyLen); ++i) { | |
| 30 SCOPED_TRACE(i); | |
| 31 EXPECT_EQ(Status::ErrorGenerateAesKeyLength(), | |
| 32 GenerateSecretKey(CreateAesKwKeyGenAlgorithm(kKeyLen[i]), true, | |
| 33 blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 34 } | |
| 35 } | |
| 36 | |
| 37 TEST_F(WebCryptoAesKwTest, GenerateKeyEmptyUsage) { | |
| 38 blink::WebCryptoKey key; | |
| 39 EXPECT_EQ(Status::ErrorCreateKeyEmptyUsages(), | |
| 40 GenerateSecretKey(CreateAesKwKeyGenAlgorithm(256), true, 0, &key)); | |
| 41 } | |
| 42 | |
| 43 TEST_F(WebCryptoAesKwTest, ImportKeyEmptyUsage) { | |
| 44 blink::WebCryptoKey key; | |
| 45 EXPECT_EQ(Status::ErrorCreateKeyEmptyUsages(), | |
| 46 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 47 CryptoData(std::vector<uint8_t>(16)), | |
| 48 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), true, | |
| 49 0, &key)); | |
| 50 } | |
| 51 | |
| 52 TEST_F(WebCryptoAesKwTest, ImportKeyJwkKeyOpsWrapUnwrap) { | |
| 53 blink::WebCryptoKey key; | |
| 54 base::DictionaryValue dict; | |
| 55 dict.SetString("kty", "oct"); | |
| 56 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg"); | |
| 57 base::ListValue* key_ops = new base::ListValue; | |
| 58 dict.Set("key_ops", key_ops); // Takes ownership. | |
| 59 | |
| 60 key_ops->AppendString("wrapKey"); | |
| 61 | |
| 62 EXPECT_EQ(Status::Success(), | |
| 63 ImportKeyJwkFromDict( | |
| 64 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), false, | |
| 65 blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 66 | |
| 67 EXPECT_EQ(blink::WebCryptoKeyUsageWrapKey, key.usages()); | |
| 68 | |
| 69 key_ops->AppendString("unwrapKey"); | |
| 70 | |
| 71 EXPECT_EQ(Status::Success(), | |
| 72 ImportKeyJwkFromDict( | |
| 73 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), false, | |
| 74 blink::WebCryptoKeyUsageUnwrapKey, &key)); | |
| 75 | |
| 76 EXPECT_EQ(blink::WebCryptoKeyUsageUnwrapKey, key.usages()); | |
| 77 } | |
| 78 | |
| 79 TEST_F(WebCryptoAesKwTest, ImportExportJwk) { | |
| 80 const blink::WebCryptoAlgorithm algorithm = | |
| 81 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 82 | |
| 83 // AES-KW 128 | |
| 84 ImportExportJwkSymmetricKey( | |
| 85 128, algorithm, | |
| 86 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, | |
| 87 "A128KW"); | |
| 88 | |
| 89 // AES-KW 256 | |
| 90 ImportExportJwkSymmetricKey( | |
| 91 256, algorithm, | |
| 92 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, | |
| 93 "A256KW"); | |
| 94 } | |
| 95 | |
| 96 TEST_F(WebCryptoAesKwTest, AesKwKeyImport) { | |
| 97 blink::WebCryptoKey key; | |
| 98 blink::WebCryptoAlgorithm algorithm = | |
| 99 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 100 | |
| 101 // Import a 128-bit Key Encryption Key (KEK) | |
| 102 std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939"; | |
| 103 ASSERT_EQ(Status::Success(), | |
| 104 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 105 CryptoData(HexStringToBytes(key_raw_hex_in)), algorithm, | |
| 106 true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 107 std::vector<uint8_t> key_raw_out; | |
| 108 EXPECT_EQ(Status::Success(), | |
| 109 ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out)); | |
| 110 EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out); | |
| 111 | |
| 112 // Import a 192-bit KEK | |
| 113 key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103"; | |
| 114 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), | |
| 115 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 116 CryptoData(HexStringToBytes(key_raw_hex_in)), algorithm, | |
| 117 true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 118 | |
| 119 // Import a 256-bit Key Encryption Key (KEK) | |
| 120 key_raw_hex_in = | |
| 121 "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f"; | |
| 122 ASSERT_EQ(Status::Success(), | |
| 123 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 124 CryptoData(HexStringToBytes(key_raw_hex_in)), algorithm, | |
| 125 true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 126 EXPECT_EQ(Status::Success(), | |
| 127 ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out)); | |
| 128 EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out); | |
| 129 | |
| 130 // Fail import of 0 length key | |
| 131 EXPECT_EQ( | |
| 132 Status::ErrorImportAesKeyLength(), | |
| 133 ImportKey(blink::WebCryptoKeyFormatRaw, CryptoData(HexStringToBytes("")), | |
| 134 algorithm, true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 135 | |
| 136 // Fail import of 124-bit KEK | |
| 137 key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb"; | |
| 138 EXPECT_EQ(Status::ErrorImportAesKeyLength(), | |
| 139 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 140 CryptoData(HexStringToBytes(key_raw_hex_in)), algorithm, | |
| 141 true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 142 | |
| 143 // Fail import of 200-bit KEK | |
| 144 key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e"; | |
| 145 EXPECT_EQ(Status::ErrorImportAesKeyLength(), | |
| 146 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 147 CryptoData(HexStringToBytes(key_raw_hex_in)), algorithm, | |
| 148 true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 149 | |
| 150 // Fail import of 260-bit KEK | |
| 151 key_raw_hex_in = | |
| 152 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a"; | |
| 153 EXPECT_EQ(Status::ErrorImportAesKeyLength(), | |
| 154 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 155 CryptoData(HexStringToBytes(key_raw_hex_in)), algorithm, | |
| 156 true, blink::WebCryptoKeyUsageWrapKey, &key)); | |
| 157 } | |
| 158 | |
| 159 TEST_F(WebCryptoAesKwTest, UnwrapFailures) { | |
| 160 // This test exercises the code path common to all unwrap operations. | |
| 161 scoped_ptr<base::ListValue> tests; | |
| 162 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); | |
| 163 base::DictionaryValue* test; | |
| 164 ASSERT_TRUE(tests->GetDictionary(0, &test)); | |
| 165 const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); | |
| 166 const std::vector<uint8_t> test_ciphertext = | |
| 167 GetBytesFromHexString(test, "ciphertext"); | |
| 168 | |
| 169 blink::WebCryptoKey unwrapped_key; | |
| 170 | |
| 171 // Using a wrapping algorithm that does not match the wrapping key algorithm | |
| 172 // should fail. | |
| 173 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
| 174 test_kek, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), | |
| 175 blink::WebCryptoKeyUsageUnwrapKey); | |
| 176 EXPECT_EQ(Status::ErrorUnexpected(), | |
| 177 UnwrapKey(blink::WebCryptoKeyFormatRaw, CryptoData(test_ciphertext), | |
| 178 wrapping_key, | |
| 179 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | |
| 180 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true, | |
| 181 blink::WebCryptoKeyUsageEncrypt, &unwrapped_key)); | |
| 182 } | |
| 183 | |
| 184 TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapKnownAnswer) { | |
| 185 scoped_ptr<base::ListValue> tests; | |
| 186 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); | |
| 187 | |
| 188 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { | |
| 189 SCOPED_TRACE(test_index); | |
| 190 base::DictionaryValue* test; | |
| 191 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); | |
| 192 const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); | |
| 193 const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); | |
| 194 const std::vector<uint8_t> test_ciphertext = | |
| 195 GetBytesFromHexString(test, "ciphertext"); | |
| 196 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
| 197 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 198 | |
| 199 // Import the wrapping key. | |
| 200 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
| 201 test_kek, wrapping_algorithm, | |
| 202 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey); | |
| 203 | |
| 204 // Import the key to be wrapped. | |
| 205 blink::WebCryptoKey key = ImportSecretKeyFromRaw( | |
| 206 test_key, | |
| 207 CreateHmacImportAlgorithmNoLength(blink::WebCryptoAlgorithmIdSha1), | |
| 208 blink::WebCryptoKeyUsageSign); | |
| 209 | |
| 210 // Wrap the key and verify the ciphertext result against the known answer. | |
| 211 std::vector<uint8_t> wrapped_key; | |
| 212 ASSERT_EQ(Status::Success(), | |
| 213 WrapKey(blink::WebCryptoKeyFormatRaw, key, wrapping_key, | |
| 214 wrapping_algorithm, &wrapped_key)); | |
| 215 EXPECT_BYTES_EQ(test_ciphertext, wrapped_key); | |
| 216 | |
| 217 // Unwrap the known ciphertext to get a new test_key. | |
| 218 blink::WebCryptoKey unwrapped_key; | |
| 219 ASSERT_EQ( | |
| 220 Status::Success(), | |
| 221 UnwrapKey( | |
| 222 blink::WebCryptoKeyFormatRaw, CryptoData(test_ciphertext), | |
| 223 wrapping_key, wrapping_algorithm, | |
| 224 CreateHmacImportAlgorithmNoLength(blink::WebCryptoAlgorithmIdSha1), | |
| 225 true, blink::WebCryptoKeyUsageSign, &unwrapped_key)); | |
| 226 EXPECT_FALSE(key.isNull()); | |
| 227 EXPECT_TRUE(key.handle()); | |
| 228 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | |
| 229 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); | |
| 230 EXPECT_EQ(true, key.extractable()); | |
| 231 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages()); | |
| 232 | |
| 233 // Export the new key and compare its raw bytes with the original known key. | |
| 234 std::vector<uint8_t> raw_key; | |
| 235 EXPECT_EQ(Status::Success(), | |
| 236 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); | |
| 237 EXPECT_BYTES_EQ(test_key, raw_key); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 // Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the | |
| 242 // unwrapped key | |
| 243 TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapSignVerifyHmac) { | |
| 244 scoped_ptr<base::ListValue> tests; | |
| 245 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); | |
| 246 | |
| 247 base::DictionaryValue* test; | |
| 248 ASSERT_TRUE(tests->GetDictionary(0, &test)); | |
| 249 const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); | |
| 250 const std::vector<uint8_t> test_ciphertext = | |
| 251 GetBytesFromHexString(test, "ciphertext"); | |
| 252 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
| 253 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 254 | |
| 255 // Import the wrapping key. | |
| 256 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
| 257 test_kek, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey); | |
| 258 | |
| 259 // Unwrap the known ciphertext. | |
| 260 blink::WebCryptoKey key; | |
| 261 ASSERT_EQ( | |
| 262 Status::Success(), | |
| 263 UnwrapKey( | |
| 264 blink::WebCryptoKeyFormatRaw, CryptoData(test_ciphertext), | |
| 265 wrapping_key, wrapping_algorithm, | |
| 266 CreateHmacImportAlgorithmNoLength(blink::WebCryptoAlgorithmIdSha1), | |
| 267 false, blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, | |
| 268 &key)); | |
| 269 | |
| 270 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | |
| 271 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); | |
| 272 EXPECT_FALSE(key.extractable()); | |
| 273 EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, | |
| 274 key.usages()); | |
| 275 | |
| 276 // Sign an empty message and ensure it is verified. | |
| 277 std::vector<uint8_t> test_message; | |
| 278 std::vector<uint8_t> signature; | |
| 279 | |
| 280 ASSERT_EQ(Status::Success(), | |
| 281 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac), key, | |
| 282 CryptoData(test_message), &signature)); | |
| 283 | |
| 284 EXPECT_GT(signature.size(), 0u); | |
| 285 | |
| 286 bool verify_result; | |
| 287 ASSERT_EQ( | |
| 288 Status::Success(), | |
| 289 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac), key, | |
| 290 CryptoData(signature), CryptoData(test_message), &verify_result)); | |
| 291 } | |
| 292 | |
| 293 TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapErrors) { | |
| 294 scoped_ptr<base::ListValue> tests; | |
| 295 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); | |
| 296 base::DictionaryValue* test; | |
| 297 // Use 256 bits of data with a 256-bit KEK | |
| 298 ASSERT_TRUE(tests->GetDictionary(3, &test)); | |
| 299 const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); | |
| 300 const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); | |
| 301 const std::vector<uint8_t> test_ciphertext = | |
| 302 GetBytesFromHexString(test, "ciphertext"); | |
| 303 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
| 304 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 305 const blink::WebCryptoAlgorithm key_algorithm = | |
| 306 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); | |
| 307 // Import the wrapping key. | |
| 308 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
| 309 test_kek, wrapping_algorithm, | |
| 310 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey); | |
| 311 // Import the key to be wrapped. | |
| 312 blink::WebCryptoKey key = ImportSecretKeyFromRaw( | |
| 313 test_key, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | |
| 314 blink::WebCryptoKeyUsageEncrypt); | |
| 315 | |
| 316 // Unwrap with wrapped data too small must fail. | |
| 317 const std::vector<uint8_t> small_data(test_ciphertext.begin(), | |
| 318 test_ciphertext.begin() + 23); | |
| 319 blink::WebCryptoKey unwrapped_key; | |
| 320 EXPECT_EQ(Status::ErrorDataTooSmall(), | |
| 321 UnwrapKey(blink::WebCryptoKeyFormatRaw, CryptoData(small_data), | |
| 322 wrapping_key, wrapping_algorithm, key_algorithm, true, | |
| 323 blink::WebCryptoKeyUsageEncrypt, &unwrapped_key)); | |
| 324 | |
| 325 // Unwrap with wrapped data size not a multiple of 8 bytes must fail. | |
| 326 const std::vector<uint8_t> unaligned_data(test_ciphertext.begin(), | |
| 327 test_ciphertext.end() - 2); | |
| 328 EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(), | |
| 329 UnwrapKey(blink::WebCryptoKeyFormatRaw, CryptoData(unaligned_data), | |
| 330 wrapping_key, wrapping_algorithm, key_algorithm, true, | |
| 331 blink::WebCryptoKeyUsageEncrypt, &unwrapped_key)); | |
| 332 } | |
| 333 | |
| 334 TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapCorruptData) { | |
| 335 scoped_ptr<base::ListValue> tests; | |
| 336 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); | |
| 337 base::DictionaryValue* test; | |
| 338 // Use 256 bits of data with a 256-bit KEK | |
| 339 ASSERT_TRUE(tests->GetDictionary(3, &test)); | |
| 340 const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); | |
| 341 const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); | |
| 342 const std::vector<uint8_t> test_ciphertext = | |
| 343 GetBytesFromHexString(test, "ciphertext"); | |
| 344 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
| 345 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 346 | |
| 347 // Import the wrapping key. | |
| 348 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
| 349 test_kek, wrapping_algorithm, | |
| 350 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey); | |
| 351 | |
| 352 // Unwrap of a corrupted version of the known ciphertext should fail, due to | |
| 353 // AES-KW's built-in integrity check. | |
| 354 blink::WebCryptoKey unwrapped_key; | |
| 355 EXPECT_EQ(Status::OperationError(), | |
| 356 UnwrapKey(blink::WebCryptoKeyFormatRaw, | |
| 357 CryptoData(Corrupted(test_ciphertext)), wrapping_key, | |
| 358 wrapping_algorithm, | |
| 359 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), true, | |
| 360 blink::WebCryptoKeyUsageEncrypt, &unwrapped_key)); | |
| 361 } | |
| 362 | |
| 363 TEST_F(WebCryptoAesKwTest, AesKwJwkSymkeyUnwrapKnownData) { | |
| 364 // The following data lists a known HMAC SHA-256 key, then a JWK | |
| 365 // representation of this key which was encrypted ("wrapped") using AES-KW and | |
| 366 // the following wrapping key. | |
| 367 // For reference, the intermediate clear JWK is | |
| 368 // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"} | |
| 369 // (Not shown is space padding to ensure the cleartext meets the size | |
| 370 // requirements of the AES-KW algorithm.) | |
| 371 const std::vector<uint8_t> key_data = HexStringToBytes( | |
| 372 "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"); | |
| 373 const std::vector<uint8_t> wrapped_key_data = HexStringToBytes( | |
| 374 "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0" | |
| 375 "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5" | |
| 376 "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158" | |
| 377 "97938C5CFE5B10B4254D0C399F39D0"); | |
| 378 const std::vector<uint8_t> wrapping_key_data = | |
| 379 HexStringToBytes("000102030405060708090A0B0C0D0E0F"); | |
| 380 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
| 381 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 382 | |
| 383 // Import the wrapping key. | |
| 384 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
| 385 wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey); | |
| 386 | |
| 387 // Unwrap the known wrapped key data to produce a new key | |
| 388 blink::WebCryptoKey unwrapped_key; | |
| 389 ASSERT_EQ( | |
| 390 Status::Success(), | |
| 391 UnwrapKey( | |
| 392 blink::WebCryptoKeyFormatJwk, CryptoData(wrapped_key_data), | |
| 393 wrapping_key, wrapping_algorithm, | |
| 394 CreateHmacImportAlgorithmNoLength(blink::WebCryptoAlgorithmIdSha256), | |
| 395 true, blink::WebCryptoKeyUsageVerify, &unwrapped_key)); | |
| 396 | |
| 397 // Validate the new key's attributes. | |
| 398 EXPECT_FALSE(unwrapped_key.isNull()); | |
| 399 EXPECT_TRUE(unwrapped_key.handle()); | |
| 400 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type()); | |
| 401 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id()); | |
| 402 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, | |
| 403 unwrapped_key.algorithm().hmacParams()->hash().id()); | |
| 404 EXPECT_EQ(256u, unwrapped_key.algorithm().hmacParams()->lengthBits()); | |
| 405 EXPECT_EQ(true, unwrapped_key.extractable()); | |
| 406 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages()); | |
| 407 | |
| 408 // Export the new key's raw data and compare to the known original. | |
| 409 std::vector<uint8_t> raw_key; | |
| 410 EXPECT_EQ(Status::Success(), | |
| 411 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); | |
| 412 EXPECT_BYTES_EQ(key_data, raw_key); | |
| 413 } | |
| 414 | |
| 415 // Try importing an AES-KW key with unsupported key usages using raw | |
| 416 // format. AES-KW keys support the following usages: | |
| 417 // 'wrapKey', 'unwrapKey' | |
| 418 TEST_F(WebCryptoAesKwTest, ImportKeyBadUsage_Raw) { | |
| 419 const blink::WebCryptoAlgorithm algorithm = | |
| 420 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 421 | |
| 422 blink::WebCryptoKeyUsageMask bad_usages[] = { | |
| 423 blink::WebCryptoKeyUsageEncrypt, | |
| 424 blink::WebCryptoKeyUsageDecrypt, | |
| 425 blink::WebCryptoKeyUsageSign, | |
| 426 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageUnwrapKey, | |
| 427 blink::WebCryptoKeyUsageDeriveBits, | |
| 428 blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify, | |
| 429 }; | |
| 430 | |
| 431 std::vector<uint8_t> key_bytes(16); | |
| 432 | |
| 433 for (size_t i = 0; i < arraysize(bad_usages); ++i) { | |
| 434 SCOPED_TRACE(i); | |
| 435 | |
| 436 blink::WebCryptoKey key; | |
| 437 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), | |
| 438 ImportKey(blink::WebCryptoKeyFormatRaw, CryptoData(key_bytes), | |
| 439 algorithm, true, bad_usages[i], &key)); | |
| 440 } | |
| 441 } | |
| 442 | |
| 443 // Try unwrapping an HMAC key with unsupported usages using JWK format and | |
| 444 // AES-KW. HMAC keys support the following usages: | |
| 445 // 'sign', 'verify' | |
| 446 TEST_F(WebCryptoAesKwTest, UnwrapHmacKeyBadUsage_JWK) { | |
| 447 const blink::WebCryptoAlgorithm unwrap_algorithm = | |
| 448 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 449 | |
| 450 blink::WebCryptoKeyUsageMask bad_usages[] = { | |
| 451 blink::WebCryptoKeyUsageEncrypt, | |
| 452 blink::WebCryptoKeyUsageDecrypt, | |
| 453 blink::WebCryptoKeyUsageWrapKey, | |
| 454 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey, | |
| 455 blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDeriveKey, | |
| 456 }; | |
| 457 | |
| 458 // Import the wrapping key. | |
| 459 blink::WebCryptoKey wrapping_key; | |
| 460 ASSERT_EQ(Status::Success(), | |
| 461 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 462 CryptoData(std::vector<uint8_t>(16)), unwrap_algorithm, | |
| 463 true, blink::WebCryptoKeyUsageUnwrapKey, &wrapping_key)); | |
| 464 | |
| 465 // The JWK plain text is: | |
| 466 // {"kty":"oct","alg":"HS256","k":"GADWrMRHwQfoNaXU5fZvTg"} | |
| 467 const char* kWrappedJwk = | |
| 468 "C2B7F19A32EE31372CD40C9C969B8CD67553E5AEA7FD1144874584E46ABCD79FDC308848" | |
| 469 "B2DD8BD36A2D61062B9C5B8B499B8D6EF8EB320D87A614952B4EE771"; | |
| 470 | |
| 471 for (size_t i = 0; i < arraysize(bad_usages); ++i) { | |
| 472 SCOPED_TRACE(i); | |
| 473 | |
| 474 blink::WebCryptoKey key; | |
| 475 | |
| 476 ASSERT_EQ( | |
| 477 Status::ErrorCreateKeyBadUsages(), | |
| 478 UnwrapKey(blink::WebCryptoKeyFormatJwk, | |
| 479 CryptoData(HexStringToBytes(kWrappedJwk)), wrapping_key, | |
| 480 unwrap_algorithm, CreateHmacImportAlgorithmNoLength( | |
| 481 blink::WebCryptoAlgorithmIdSha256), | |
| 482 true, bad_usages[i], &key)); | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 // Try unwrapping an RSA-SSA public key with unsupported usages using JWK format | |
| 487 // and AES-KW. RSA-SSA public keys support the following usages: | |
| 488 // 'verify' | |
| 489 TEST_F(WebCryptoAesKwTest, UnwrapRsaSsaPublicKeyBadUsage_JWK) { | |
| 490 const blink::WebCryptoAlgorithm unwrap_algorithm = | |
| 491 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
| 492 | |
| 493 blink::WebCryptoKeyUsageMask bad_usages[] = { | |
| 494 blink::WebCryptoKeyUsageEncrypt, | |
| 495 blink::WebCryptoKeyUsageSign, | |
| 496 blink::WebCryptoKeyUsageDecrypt, | |
| 497 blink::WebCryptoKeyUsageWrapKey, | |
| 498 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey, | |
| 499 }; | |
| 500 | |
| 501 // Import the wrapping key. | |
| 502 blink::WebCryptoKey wrapping_key; | |
| 503 ASSERT_EQ(Status::Success(), | |
| 504 ImportKey(blink::WebCryptoKeyFormatRaw, | |
| 505 CryptoData(std::vector<uint8_t>(16)), unwrap_algorithm, | |
| 506 true, blink::WebCryptoKeyUsageUnwrapKey, &wrapping_key)); | |
| 507 | |
| 508 // The JWK plaintext is: | |
| 509 // { "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"} | |
| 510 | |
| 511 const char* kWrappedJwk = | |
| 512 "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152" | |
| 513 "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D" | |
| 514 "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D" | |
| 515 "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B" | |
| 516 "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2" | |
| 517 "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B" | |
| 518 "30F2EE83CEDFD51136852C8A5939B768"; | |
| 519 | |
| 520 for (size_t i = 0; i < arraysize(bad_usages); ++i) { | |
| 521 SCOPED_TRACE(i); | |
| 522 | |
| 523 blink::WebCryptoKey key; | |
| 524 | |
| 525 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), | |
| 526 UnwrapKey(blink::WebCryptoKeyFormatJwk, | |
| 527 CryptoData(HexStringToBytes(kWrappedJwk)), wrapping_key, | |
| 528 unwrap_algorithm, | |
| 529 CreateRsaHashedImportAlgorithm( | |
| 530 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
| 531 blink::WebCryptoAlgorithmIdSha256), | |
| 532 true, bad_usages[i], &key)); | |
| 533 } | |
| 534 } | |
| 535 | |
| 536 } // namespace | |
| 537 | |
| 538 } // namespace webcrypto | |
| OLD | NEW |