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