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 3 // found in the LICENSE file. 4 5 #include "content/renderer/webcrypto/webcrypto_impl.h" 6 7 #include <algorithm> 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/json/json_writer.h" 13 #include "base/logging.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/strings/string_number_conversions.h" 16 #include "content/public/renderer/content_renderer_client.h" 17 #include "content/renderer/renderer_webkitplatformsupport_impl.h" 18 #include "content/renderer/webcrypto/webcrypto_util.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" 21 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 23 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 24 25 namespace content { 26 27 namespace { 28 29 std::vector<uint8> HexStringToBytes(const std::string& hex) { 30 std::vector<uint8> bytes; 31 base::HexStringToBytes(hex, &bytes); 32 return bytes; 33 } 34 35 void ExpectArrayBufferMatchesHex(const std::string& expected_hex, 36 const blink::WebArrayBuffer& array_buffer) { 37 EXPECT_STRCASEEQ( 38 expected_hex.c_str(), 39 base::HexEncode(array_buffer.data(), array_buffer.byteLength()).c_str()); 40 } 41 42 std::vector<uint8> MakeJsonVector(const std::string& json_string) { 43 return std::vector<uint8>(json_string.begin(), json_string.end()); 44 } 45 46 std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) { 47 std::string json; 48 base::JSONWriter::Write(&dict, &json); 49 return MakeJsonVector(json); 50 } 51 52 // Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON 53 // dictionary to a good state 54 void RestoreJwkOctDictionary(base::DictionaryValue* dict) { 55 dict->Clear(); 56 dict->SetString("kty", "oct"); 57 dict->SetString("alg", "A128CBC"); 58 dict->SetString("use", "enc"); 59 dict->SetBoolean("extractable", false); 60 dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg=="); 61 } 62 63 #if !defined(USE_OPENSSL) 64 65 // Helper for ImportJwkRsaFailures. Restores the JWK JSON 66 // dictionary to a good state 67 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) { 68 dict->Clear(); 69 dict->SetString("kty", "RSA"); 70 dict->SetString("alg", "RSA1_5"); 71 dict->SetString("use", "enc"); 72 dict->SetBoolean("extractable", false); 73 dict->SetString("n", 74 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk" 75 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm" 76 "e7PUJHYW1PW6ENTP0ibeiNOfFvs"); 77 dict->SetString("e", "AQAB"); 78 } 79 80 blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( 81 blink::WebCryptoAlgorithmId algorithm_id, 82 unsigned modulus_length, 83 const std::vector<uint8>& public_exponent) { 84 DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || 85 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || 86 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); 87 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 88 algorithm_id, 89 new blink::WebCryptoRsaKeyGenParams( 90 modulus_length, 91 webcrypto::Uint8VectorStart(public_exponent), 92 public_exponent.size())); 93 } 94 95 // Determines if two ArrayBuffers have identical content. 96 bool ArrayBuffersEqual( 97 const blink::WebArrayBuffer& a, 98 const blink::WebArrayBuffer& b) { 99 return a.byteLength() == b.byteLength() && 100 memcmp(a.data(), b.data(), a.byteLength()) == 0; 101 } 102 103 // Given a vector of WebArrayBuffers, determines if there are any copies. 104 bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) { 105 for (size_t i = 0; i < bufs.size(); ++i) { 106 for (size_t j = i + 1; j < bufs.size(); ++j) { 107 if (ArrayBuffersEqual(bufs[i], bufs[j])) 108 return true; 109 } 110 } 111 return false; 112 } 113 114 #endif // #if !defined(USE_OPENSSL) 115 116 } // namespace 117 118 class WebCryptoImplTest : public testing::Test { 119 protected: 120 blink::WebCryptoKey ImportSecretKeyFromRawHexString( 121 const std::string& key_hex, 122 const blink::WebCryptoAlgorithm& algorithm, 123 blink::WebCryptoKeyUsageMask usage) { 124 std::vector<uint8> key_raw = HexStringToBytes(key_hex); 125 126 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 127 bool extractable = true; 128 EXPECT_TRUE(crypto_.ImportKeyInternal(blink::WebCryptoKeyFormatRaw, 129 webcrypto::Uint8VectorStart(key_raw), 130 key_raw.size(), 131 algorithm, 132 extractable, 133 usage, 134 &key)); 135 136 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 137 EXPECT_FALSE(key.isNull()); 138 EXPECT_TRUE(key.handle()); 139 return key; 140 } 141 142 // Forwarding methods to gain access to protected methods of 143 // WebCryptoImpl. 144 145 bool DigestInternal( 146 const blink::WebCryptoAlgorithm& algorithm, 147 const std::vector<uint8>& data, 148 blink::WebArrayBuffer* buffer) { 149 return crypto_.DigestInternal( 150 algorithm, webcrypto::Uint8VectorStart(data), data.size(), buffer); 151 } 152 153 bool GenerateKeyInternal( 154 const blink::WebCryptoAlgorithm& algorithm, 155 blink::WebCryptoKey* key) { 156 bool extractable = true; 157 blink::WebCryptoKeyUsageMask usage_mask = 0; 158 return crypto_.GenerateKeyInternal(algorithm, extractable, usage_mask, key); 159 } 160 161 bool GenerateKeyPairInternal( 162 const blink::WebCryptoAlgorithm& algorithm, 163 bool extractable, 164 blink::WebCryptoKeyUsageMask usage_mask, 165 blink::WebCryptoKey* public_key, 166 blink::WebCryptoKey* private_key) { 167 return crypto_.GenerateKeyPairInternal( 168 algorithm, extractable, usage_mask, public_key, private_key); 169 } 170 171 bool ImportKeyInternal( 172 blink::WebCryptoKeyFormat format, 173 const std::vector<uint8>& key_data, 174 const blink::WebCryptoAlgorithm& algorithm, 175 bool extractable, 176 blink::WebCryptoKeyUsageMask usage_mask, 177 blink::WebCryptoKey* key) { 178 return crypto_.ImportKeyInternal(format, 179 webcrypto::Uint8VectorStart(key_data), 180 key_data.size(), 181 algorithm, 182 extractable, 183 usage_mask, 184 key); 185 } 186 187 bool ExportKeyInternal( 188 blink::WebCryptoKeyFormat format, 189 const blink::WebCryptoKey& key, 190 blink::WebArrayBuffer* buffer) { 191 return crypto_.ExportKeyInternal(format, key, buffer); 192 } 193 194 bool SignInternal( 195 const blink::WebCryptoAlgorithm& algorithm, 196 const blink::WebCryptoKey& key, 197 const std::vector<uint8>& data, 198 blink::WebArrayBuffer* buffer) { 199 return crypto_.SignInternal( 200 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer); 201 } 202 203 bool VerifySignatureInternal( 204 const blink::WebCryptoAlgorithm& algorithm, 205 const blink::WebCryptoKey& key, 206 const unsigned char* signature, 207 unsigned signature_size, 208 const std::vector<uint8>& data, 209 bool* signature_match) { 210 return crypto_.VerifySignatureInternal(algorithm, 211 key, 212 signature, 213 signature_size, 214 webcrypto::Uint8VectorStart(data), 215 data.size(), 216 signature_match); 217 } 218 219 bool EncryptInternal( 220 const blink::WebCryptoAlgorithm& algorithm, 221 const blink::WebCryptoKey& key, 222 const unsigned char* data, 223 unsigned data_size, 224 blink::WebArrayBuffer* buffer) { 225 return crypto_.EncryptInternal(algorithm, key, data, data_size, buffer); 226 } 227 228 bool EncryptInternal( 229 const blink::WebCryptoAlgorithm& algorithm, 230 const blink::WebCryptoKey& key, 231 const std::vector<uint8>& data, 232 blink::WebArrayBuffer* buffer) { 233 return crypto_.EncryptInternal( 234 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer); 235 } 236 237 bool DecryptInternal( 238 const blink::WebCryptoAlgorithm& algorithm, 239 const blink::WebCryptoKey& key, 240 const unsigned char* data, 241 unsigned data_size, 242 blink::WebArrayBuffer* buffer) { 243 return crypto_.DecryptInternal(algorithm, key, data, data_size, buffer); 244 } 245 246 bool DecryptInternal( 247 const blink::WebCryptoAlgorithm& algorithm, 248 const blink::WebCryptoKey& key, 249 const std::vector<uint8>& data, 250 blink::WebArrayBuffer* buffer) { 251 return crypto_.DecryptInternal( 252 algorithm, key, webcrypto::Uint8VectorStart(data), data.size(), buffer); 253 } 254 255 bool ImportKeyJwk( 256 const std::vector<uint8>& key_data, 257 const blink::WebCryptoAlgorithm& algorithm, 258 bool extractable, 259 blink::WebCryptoKeyUsageMask usage_mask, 260 blink::WebCryptoKey* key) { 261 return crypto_.ImportKeyJwk(webcrypto::Uint8VectorStart(key_data), 262 key_data.size(), 263 algorithm, 264 extractable, 265 usage_mask, 266 key); 267 } 268 269 private: 270 WebCryptoImpl crypto_; 271 }; 272 273 TEST_F(WebCryptoImplTest, DigestSampleSets) { 274 // The results are stored here in hex format for readability. 275 // 276 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced 277 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 278 // 279 // Results were generated using the command sha{1,224,256,384,512}sum. 280 struct TestCase { 281 blink::WebCryptoAlgorithmId algorithm; 282 const std::string hex_input; 283 const char* hex_result; 284 }; 285 286 const TestCase kTests[] = { 287 { blink::WebCryptoAlgorithmIdSha1, "", 288 "da39a3ee5e6b4b0d3255bfef95601890afd80709" 289 }, 290 { blink::WebCryptoAlgorithmIdSha224, "", 291 "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" 292 }, 293 { blink::WebCryptoAlgorithmIdSha256, "", 294 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 295 }, 296 { blink::WebCryptoAlgorithmIdSha384, "", 297 "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274e" 298 "debfe76f65fbd51ad2f14898b95b" 299 }, 300 { blink::WebCryptoAlgorithmIdSha512, "", 301 "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0" 302 "d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", 303 }, 304 { blink::WebCryptoAlgorithmIdSha1, "00", 305 "5ba93c9db0cff93f52b521d7420e43f6eda2784f", 306 }, 307 { blink::WebCryptoAlgorithmIdSha224, "00", 308 "fff9292b4201617bdc4d3053fce02734166a683d7d858a7f5f59b073", 309 }, 310 { blink::WebCryptoAlgorithmIdSha256, "00", 311 "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 312 }, 313 { blink::WebCryptoAlgorithmIdSha384, "00", 314 "bec021b4f368e3069134e012c2b4307083d3a9bdd206e24e5f0d86e13d6636655933" 315 "ec2b413465966817a9c208a11717", 316 }, 317 { blink::WebCryptoAlgorithmIdSha512, "00", 318 "b8244d028981d693af7b456af8efa4cad63d282e19ff14942c246e50d9351d22704a" 319 "802a71c3580b6370de4ceb293c324a8423342557d4e5c38438f0e36910ee", 320 }, 321 { blink::WebCryptoAlgorithmIdSha1, "000102030405", 322 "868460d98d09d8bbb93d7b6cdd15cc7fbec676b9", 323 }, 324 { blink::WebCryptoAlgorithmIdSha224, "000102030405", 325 "7d92e7f1cad1818ed1d13ab41f04ebabfe1fef6bb4cbeebac34c29bc", 326 }, 327 { blink::WebCryptoAlgorithmIdSha256, "000102030405", 328 "17e88db187afd62c16e5debf3e6527cd006bc012bc90b51a810cd80c2d511f43", 329 }, 330 { blink::WebCryptoAlgorithmIdSha384, "000102030405", 331 "79f4738706fce9650ac60266675c3cd07298b09923850d525604d040e6e448adc7dc" 332 "22780d7e1b95bfeaa86a678e4552", 333 }, 334 { blink::WebCryptoAlgorithmIdSha512, "000102030405", 335 "2f3831bccc94cf061bcfa5f8c23c1429d26e3bc6b76edad93d9025cb91c903af6cf9" 336 "c935dc37193c04c2c66e7d9de17c358284418218afea2160147aaa912f4c", 337 }, 338 }; 339 340 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); 341 ++test_index) { 342 SCOPED_TRACE(test_index); 343 const TestCase& test = kTests[test_index]; 344 345 blink::WebCryptoAlgorithm algorithm = 346 webcrypto::CreateAlgorithm(test.algorithm); 347 std::vector<uint8> input = HexStringToBytes(test.hex_input); 348 349 blink::WebArrayBuffer output; 350 ASSERT_TRUE(DigestInternal(algorithm, input, &output)); 351 ExpectArrayBufferMatchesHex(test.hex_result, output); 352 } 353 } 354 355 TEST_F(WebCryptoImplTest, HMACSampleSets) { 356 struct TestCase { 357 blink::WebCryptoAlgorithmId algorithm; 358 const char* key; 359 const char* message; 360 const char* mac; 361 }; 362 363 const TestCase kTests[] = { 364 // Empty sets. Result generated via OpenSSL commandline tool. These 365 // particular results are also posted on the Wikipedia page examples: 366 // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code 367 { 368 blink::WebCryptoAlgorithmIdSha1, 369 "", 370 "", 371 // openssl dgst -sha1 -hmac "" < /dev/null 372 "fbdb1d1b18aa6c08324b7d64b71fb76370690e1d", 373 }, 374 { 375 blink::WebCryptoAlgorithmIdSha256, 376 "", 377 "", 378 // openssl dgst -sha256 -hmac "" < /dev/null 379 "b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", 380 }, 381 // For this data, see http://csrc.nist.gov/groups/STM/cavp/index.html#07 382 // Download: 383 // http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip 384 // L=20 set 45 385 { 386 blink::WebCryptoAlgorithmIdSha1, 387 // key 388 "59785928d72516e31272", 389 // message 390 "a3ce8899df1022e8d2d539b47bf0e309c66f84095e21438ec355bf119ce5fdcb4e73a6" 391 "19cdf36f25b369d8c38ff419997f0c59830108223606e31223483fd39edeaa4d3f0d21" 392 "198862d239c9fd26074130ff6c86493f5227ab895c8f244bd42c7afce5d147a20a5907" 393 "98c68e708e964902d124dadecdbda9dbd0051ed710e9bf", 394 // mac 395 "3c8162589aafaee024fc9a5ca50dd2336fe3eb28", 396 }, 397 // L=20 set 299 398 { 399 blink::WebCryptoAlgorithmIdSha1, 400 // key 401 "ceb9aedf8d6efcf0ae52bea0fa99a9e26ae81bacea0cff4d5eecf201e3bca3c3577480" 402 "621b818fd717ba99d6ff958ea3d59b2527b019c343bb199e648090225867d994607962" 403 "f5866aa62930d75b58f6", 404 // message 405 "99958aa459604657c7bf6e4cdfcc8785f0abf06ffe636b5b64ecd931bd8a4563055924" 406 "21fc28dbcccb8a82acea2be8e54161d7a78e0399a6067ebaca3f2510274dc9f92f2c8a" 407 "e4265eec13d7d42e9f8612d7bc258f913ecb5a3a5c610339b49fb90e9037b02d684fc6" 408 "0da835657cb24eab352750c8b463b1a8494660d36c3ab2", 409 // mac 410 "4ac41ab89f625c60125ed65ffa958c6b490ea670", 411 }, 412 // L=32, set 30 413 { 414 blink::WebCryptoAlgorithmIdSha256, 415 // key 416 "9779d9120642797f1747025d5b22b7ac607cab08e1758f2f3a46c8be1e25c53b8c6a8f" 417 "58ffefa176", 418 // message 419 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" 420 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" 421 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" 422 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e", 423 // mac 424 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b", 425 }, 426 // L=32, set 224 427 { 428 blink::WebCryptoAlgorithmIdSha256, 429 // key 430 "4b7ab133efe99e02fc89a28409ee187d579e774f4cba6fc223e13504e3511bef8d4f63" 431 "8b9aca55d4a43b8fbd64cf9d74dcc8c9e8d52034898c70264ea911a3fd70813fa73b08" 432 "3371289b", 433 // message 434 "138efc832c64513d11b9873c6fd4d8a65dbf367092a826ddd587d141b401580b798c69" 435 "025ad510cff05fcfbceb6cf0bb03201aaa32e423d5200925bddfadd418d8e30e18050e" 436 "b4f0618eb9959d9f78c1157d4b3e02cd5961f138afd57459939917d9144c95d8e6a94c" 437 "8f6d4eef3418c17b1ef0b46c2a7188305d9811dccb3d99", 438 // mac 439 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", 440 }, 441 }; 442 443 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); 444 ++test_index) { 445 SCOPED_TRACE(test_index); 446 const TestCase& test = kTests[test_index]; 447 448 blink::WebCryptoAlgorithm algorithm = 449 webcrypto::CreateHmacAlgorithmByHashId(test.algorithm); 450 451 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 452 test.key, algorithm, blink::WebCryptoKeyUsageSign); 453 454 // Verify exported raw key is identical to the imported data 455 blink::WebArrayBuffer raw_key; 456 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); 457 ExpectArrayBufferMatchesHex(test.key, raw_key); 458 459 std::vector<uint8> message_raw = HexStringToBytes(test.message); 460 461 blink::WebArrayBuffer output; 462 463 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); 464 465 ExpectArrayBufferMatchesHex(test.mac, output); 466 467 bool signature_match = false; 468 EXPECT_TRUE(VerifySignatureInternal( 469 algorithm, 470 key, 471 static_cast<const unsigned char*>(output.data()), 472 output.byteLength(), 473 message_raw, 474 &signature_match)); 475 EXPECT_TRUE(signature_match); 476 477 // Ensure truncated signature does not verify by passing one less byte. 478 EXPECT_TRUE(VerifySignatureInternal( 479 algorithm, 480 key, 481 static_cast<const unsigned char*>(output.data()), 482 output.byteLength() - 1, 483 message_raw, 484 &signature_match)); 485 EXPECT_FALSE(signature_match); 486 487 // Ensure extra long signature does not cause issues and fails. 488 const unsigned char kLongSignature[1024] = { 0 }; 489 EXPECT_TRUE(VerifySignatureInternal( 490 algorithm, 491 key, 492 kLongSignature, 493 sizeof(kLongSignature), 494 message_raw, 495 &signature_match)); 496 EXPECT_FALSE(signature_match); 497 } 498 } 499 500 #if !defined(USE_OPENSSL) 501 502 TEST_F(WebCryptoImplTest, AesCbcFailures) { 503 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c"; 504 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 505 key_hex, 506 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 507 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); 508 509 // Verify exported raw key is identical to the imported data 510 blink::WebArrayBuffer raw_key; 511 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); 512 ExpectArrayBufferMatchesHex(key_hex, raw_key); 513 514 blink::WebArrayBuffer output; 515 516 // Use an invalid |iv| (fewer than 16 bytes) 517 { 518 std::vector<uint8> input(32); 519 std::vector<uint8> iv; 520 EXPECT_FALSE(EncryptInternal( 521 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); 522 EXPECT_FALSE(DecryptInternal( 523 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); 524 } 525 526 // Use an invalid |iv| (more than 16 bytes) 527 { 528 std::vector<uint8> input(32); 529 std::vector<uint8> iv(17); 530 EXPECT_FALSE(EncryptInternal( 531 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); 532 EXPECT_FALSE(DecryptInternal( 533 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); 534 } 535 536 // Give an input that is too large (would cause integer overflow when 537 // narrowing to an int). 538 { 539 std::vector<uint8> iv(16); 540 541 // Pretend the input is large. Don't pass data pointer as NULL in case that 542 // is special cased; the implementation shouldn't actually dereference the 543 // data. 544 const unsigned char* input = &iv[0]; 545 unsigned input_len = INT_MAX - 3; 546 547 EXPECT_FALSE(EncryptInternal( 548 webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); 549 EXPECT_FALSE(DecryptInternal( 550 webcrypto::CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); 551 } 552 553 // Fail importing the key (too few bytes specified) 554 { 555 std::vector<uint8> key_raw(1); 556 std::vector<uint8> iv(16); 557 558 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 559 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw, 560 key_raw, 561 webcrypto::CreateAesCbcAlgorithm(iv), 562 true, 563 blink::WebCryptoKeyUsageEncrypt, 564 &key)); 565 } 566 567 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret 568 // keys). 569 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 570 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output)); 571 } 572 573 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { 574 struct TestCase { 575 const char* key; 576 const char* iv; 577 const char* plain_text; 578 const char* cipher_text; 579 }; 580 581 TestCase kTests[] = { 582 // F.2.1 (CBC-AES128.Encrypt) 583 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf 584 { 585 // key 586 "2b7e151628aed2a6abf7158809cf4f3c", 587 588 // iv 589 "000102030405060708090a0b0c0d0e0f", 590 591 // plain_text 592 "6bc1bee22e409f96e93d7e117393172a" 593 "ae2d8a571e03ac9c9eb76fac45af8e51" 594 "30c81c46a35ce411e5fbc1191a0a52ef" 595 "f69f2445df4f9b17ad2b417be66c3710", 596 597 // cipher_text 598 "7649abac8119b246cee98e9b12e9197d" 599 "5086cb9b507219ee95db113a917678b2" 600 "73bed6b8e3c1743b7116e69e22229516" 601 "3ff1caa1681fac09120eca307586e1a7" 602 // Padding block: encryption of {0x10, 0x10, ... 0x10}) (not given by the 603 // NIST test vector) 604 "8cb82807230e1321d3fae00d18cc2012" 605 }, 606 607 // F.2.6 CBC-AES256.Decrypt [*] 608 // http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf 609 // 610 // [*] Truncated 3 bytes off the plain text, so block 4 differs from the 611 // NIST vector. 612 { 613 // key 614 "603deb1015ca71be2b73aef0857d7781" 615 "1f352c073b6108d72d9810a30914dff4", 616 617 // iv 618 "000102030405060708090a0b0c0d0e0f", 619 620 // plain_text 621 "6bc1bee22e409f96e93d7e117393172a" 622 "ae2d8a571e03ac9c9eb76fac45af8e51" 623 "30c81c46a35ce411e5fbc1191a0a52ef" 624 // Truncated this last block to make it more interesting. 625 "f69f2445df4f9b17ad2b417be6", 626 627 // cipher_text 628 "f58c4c04d6e5f1ba779eabfb5f7bfbd6" 629 "9cfc4e967edb808d679f777bc6702c7d" 630 "39f23369a9d9bacfa530e26304231461" 631 // This block differs from source vector (due to truncation) 632 "c9aaf02a6a54e9e242ccbf48c59daca6" 633 }, 634 635 // Taken from encryptor_unittest.cc (EncryptorTest.EmptyEncrypt()) 636 { 637 // key 638 "3132383d5369787465656e4279746573", 639 640 // iv 641 "5377656574205369787465656e204956", 642 643 // plain_text 644 "", 645 646 // cipher_text 647 "8518b8878d34e7185e300d0fcc426396" 648 }, 649 }; 650 651 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) { 652 SCOPED_TRACE(index); 653 const TestCase& test = kTests[index]; 654 655 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 656 test.key, 657 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 658 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); 659 660 // Verify exported raw key is identical to the imported data 661 blink::WebArrayBuffer raw_key; 662 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); 663 ExpectArrayBufferMatchesHex(test.key, raw_key); 664 665 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); 666 std::vector<uint8> iv = HexStringToBytes(test.iv); 667 668 blink::WebArrayBuffer output; 669 670 // Test encryption. 671 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), 672 key, 673 plain_text, 674 &output)); 675 ExpectArrayBufferMatchesHex(test.cipher_text, output); 676 677 // Test decryption. 678 std::vector<uint8> cipher_text = HexStringToBytes(test.cipher_text); 679 EXPECT_TRUE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), 680 key, 681 cipher_text, 682 &output)); 683 ExpectArrayBufferMatchesHex(test.plain_text, output); 684 685 const unsigned kAesCbcBlockSize = 16; 686 687 // Decrypt with a padding error by stripping the last block. This also ends 688 // up testing decryption over empty cipher text. 689 if (cipher_text.size() >= kAesCbcBlockSize) { 690 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), 691 key, 692 &cipher_text[0], 693 cipher_text.size() - kAesCbcBlockSize, 694 &output)); 695 } 696 697 // Decrypt cipher text which is not a multiple of block size by stripping 698 // a few bytes off the cipher text. 699 if (cipher_text.size() > 3) { 700 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), 701 key, 702 &cipher_text[0], 703 cipher_text.size() - 3, 704 &output)); 705 } 706 } 707 } 708 709 TEST_F(WebCryptoImplTest, GenerateKeyAes) { 710 // Generate a small sample of AES keys. 711 std::vector<blink::WebArrayBuffer> keys; 712 blink::WebArrayBuffer key_bytes; 713 for (int i = 0; i < 16; ++i) { 714 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 715 ASSERT_TRUE( 716 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); 717 EXPECT_TRUE(key.handle()); 718 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 719 ASSERT_TRUE( 720 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes)); 721 keys.push_back(key_bytes); 722 } 723 // Ensure all entries in the key sample set are unique. This is a simplistic 724 // estimate of whether the generated keys appear random. 725 EXPECT_FALSE(CopiesExist(keys)); 726 } 727 728 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { 729 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 730 EXPECT_FALSE( 731 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); 732 EXPECT_FALSE( 733 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); 734 EXPECT_FALSE( 735 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key)); 736 } 737 738 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { 739 // Generate a small sample of HMAC keys. 740 std::vector<blink::WebArrayBuffer> keys; 741 for (int i = 0; i < 16; ++i) { 742 blink::WebArrayBuffer key_bytes; 743 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 744 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( 745 blink::WebCryptoAlgorithmIdSha1, 128); 746 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); 747 EXPECT_FALSE(key.isNull()); 748 EXPECT_TRUE(key.handle()); 749 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 750 } 751 // Ensure all entries in the key sample set are unique. This is a simplistic 752 // estimate of whether the generated keys appear random. 753 EXPECT_FALSE(CopiesExist(keys)); 754 } 755 756 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { 757 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 758 blink::WebCryptoAlgorithm algorithm = 759 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); 760 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); 761 EXPECT_TRUE(key.handle()); 762 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 763 } 764 765 TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) { 766 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 767 768 // This fails because the algorithm is null. 769 EXPECT_FALSE(ImportKeyInternal( 770 blink::WebCryptoKeyFormatRaw, 771 HexStringToBytes("00000000000000000000"), 772 blink::WebCryptoAlgorithm::createNull(), 773 true, 774 blink::WebCryptoKeyUsageEncrypt, 775 &key)); 776 } 777 778 #endif //#if !defined(USE_OPENSSL) 779 780 TEST_F(WebCryptoImplTest, ImportJwkFailures) { 781 782 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 783 blink::WebCryptoAlgorithm algorithm = 784 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); 785 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt; 786 787 // Baseline pass: each test below breaks a single item, so we start with a 788 // passing case to make sure each failure is caused by the isolated break. 789 // Each breaking subtest below resets the dictionary to this passing case when 790 // complete. 791 base::DictionaryValue dict; 792 RestoreJwkOctDictionary(&dict); 793 EXPECT_TRUE(ImportKeyJwk( 794 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 795 796 // Fail on empty JSON. 797 EXPECT_FALSE(ImportKeyJwk( 798 MakeJsonVector(""), algorithm, false, usage_mask, &key)); 799 800 // Fail on invalid JSON. 801 const std::vector<uint8> bad_json_vec = MakeJsonVector( 802 "{" 803 "\"kty\" : \"oct\"," 804 "\"alg\" : \"HS256\"," 805 "\"use\" : " 806 ); 807 EXPECT_FALSE(ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key)); 808 809 // Fail on JWK alg present but unrecognized. 810 dict.SetString("alg", "A127CBC"); 811 EXPECT_FALSE(ImportKeyJwk( 812 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 813 RestoreJwkOctDictionary(&dict); 814 815 // Fail on both JWK and input algorithm missing. 816 dict.Remove("alg", NULL); 817 EXPECT_FALSE(ImportKeyJwk(MakeJsonVector(dict), 818 blink::WebCryptoAlgorithm::createNull(), 819 false, 820 usage_mask, 821 &key)); 822 RestoreJwkOctDictionary(&dict); 823 824 // Fail on invalid kty. 825 dict.SetString("kty", "foo"); 826 EXPECT_FALSE(ImportKeyJwk( 827 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 828 RestoreJwkOctDictionary(&dict); 829 830 // Fail on missing kty. 831 dict.Remove("kty", NULL); 832 EXPECT_FALSE(ImportKeyJwk( 833 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 834 RestoreJwkOctDictionary(&dict); 835 836 // Fail on invalid use. 837 dict.SetString("use", "foo"); 838 EXPECT_FALSE(ImportKeyJwk( 839 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 840 RestoreJwkOctDictionary(&dict); 841 } 842 843 TEST_F(WebCryptoImplTest, ImportJwkOctFailures) { 844 845 base::DictionaryValue dict; 846 RestoreJwkOctDictionary(&dict); 847 blink::WebCryptoAlgorithm algorithm = 848 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); 849 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt; 850 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 851 852 // Baseline pass. 853 EXPECT_TRUE(ImportKeyJwk( 854 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 855 EXPECT_EQ(algorithm.id(), key.algorithm().id()); 856 EXPECT_FALSE(key.extractable()); 857 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); 858 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 859 860 // The following are specific failure cases for when kty = "oct". 861 862 // Fail on missing k. 863 dict.Remove("k", NULL); 864 EXPECT_FALSE(ImportKeyJwk( 865 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 866 RestoreJwkOctDictionary(&dict); 867 868 // Fail on bad b64 encoding for k. 869 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI="); 870 EXPECT_FALSE(ImportKeyJwk( 871 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 872 RestoreJwkOctDictionary(&dict); 873 874 // Fail on empty k. 875 dict.SetString("k", ""); 876 EXPECT_FALSE(ImportKeyJwk( 877 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 878 RestoreJwkOctDictionary(&dict); 879 880 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg 881 // value (128) for an AES key. 882 dict.SetString("k", "AVj42h0Y5aqGtE3yluKL"); 883 EXPECT_FALSE(ImportKeyJwk( 884 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 885 RestoreJwkOctDictionary(&dict); 886 } 887 888 #if !defined(USE_OPENSSL) 889 890 TEST_F(WebCryptoImplTest, ImportJwkRsaFailures) { 891 892 base::DictionaryValue dict; 893 RestoreJwkRsaDictionary(&dict); 894 blink::WebCryptoAlgorithm algorithm = 895 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); 896 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt; 897 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 898 899 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent) 900 // entry, while an RSA private key must have those plus at least a "d" 901 // (private exponent) entry. 902 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, 903 // section 6.3. 904 905 // Baseline pass. 906 EXPECT_TRUE(ImportKeyJwk( 907 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 908 EXPECT_EQ(algorithm.id(), key.algorithm().id()); 909 EXPECT_FALSE(key.extractable()); 910 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); 911 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type()); 912 913 // The following are specific failure cases for when kty = "RSA". 914 915 // Fail if either "n" or "e" is not present or malformed. 916 const std::string kKtyParmName[] = {"n", "e"}; 917 for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) { 918 919 // Fail on missing parameter. 920 dict.Remove(kKtyParmName[idx], NULL); 921 EXPECT_FALSE(ImportKeyJwk( 922 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 923 RestoreJwkRsaDictionary(&dict); 924 925 // Fail on bad b64 parameter encoding. 926 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0"); 927 EXPECT_FALSE(ImportKeyJwk( 928 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 929 RestoreJwkRsaDictionary(&dict); 930 931 // Fail on empty parameter. 932 dict.SetString(kKtyParmName[idx], ""); 933 EXPECT_FALSE(ImportKeyJwk( 934 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 935 RestoreJwkRsaDictionary(&dict); 936 } 937 938 // Fail if "d" parameter is present, implying the JWK is a private key, which 939 // is not supported. 940 dict.SetString("d", "Qk3f0Dsyt"); 941 EXPECT_FALSE(ImportKeyJwk( 942 MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 943 RestoreJwkRsaDictionary(&dict); 944 } 945 946 #endif // #if !defined(USE_OPENSSL) 947 948 TEST_F(WebCryptoImplTest, ImportJwkInputConsistency) { 949 // The Web Crypto spec says that if a JWK value is present, but is 950 // inconsistent with the input value, the operation must fail. 951 952 // Consistency rules when JWK value is not present: Inputs should be used. 953 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 954 bool extractable = false; 955 blink::WebCryptoAlgorithm algorithm = 956 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256); 957 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify; 958 base::DictionaryValue dict; 959 dict.SetString("kty", "oct"); 960 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); 961 std::vector<uint8> json_vec = MakeJsonVector(dict); 962 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); 963 EXPECT_TRUE(key.handle()); 964 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 965 EXPECT_EQ(extractable, key.extractable()); 966 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); 967 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, 968 key.algorithm().hmacParams()->hash().id()); 969 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages()); 970 key = blink::WebCryptoKey::createNull(); 971 972 // Consistency rules when JWK value exists: Fail if inconsistency is found. 973 974 // Pass: All input values are consistent with the JWK values. 975 dict.Clear(); 976 dict.SetString("kty", "oct"); 977 dict.SetString("alg", "HS256"); 978 dict.SetString("use", "sig"); 979 dict.SetBoolean("extractable", false); 980 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); 981 json_vec = MakeJsonVector(dict); 982 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); 983 984 // Extractable cases: 985 // 1. input=T, JWK=F ==> fail (inconsistent) 986 // 4. input=F, JWK=F ==> pass, result extractable is F 987 // 2. input=T, JWK=T ==> pass, result extractable is T 988 // 3. input=F, JWK=T ==> pass, result extractable is F 989 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, true, usage_mask, &key)); 990 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); 991 EXPECT_FALSE(key.extractable()); 992 dict.SetBoolean("extractable", true); 993 EXPECT_TRUE( 994 ImportKeyJwk(MakeJsonVector(dict), algorithm, true, usage_mask, &key)); 995 EXPECT_TRUE(key.extractable()); 996 EXPECT_TRUE( 997 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key)); 998 EXPECT_FALSE(key.extractable()); 999 dict.SetBoolean("extractable", true); // restore previous value 1000 1001 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value 1002 // (HMAC SHA256). 1003 EXPECT_FALSE(ImportKeyJwk( 1004 json_vec, 1005 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 1006 extractable, 1007 usage_mask, 1008 &key)); 1009 1010 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value 1011 // (HMAC SHA256). 1012 EXPECT_FALSE(ImportKeyJwk( 1013 json_vec, 1014 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha1), 1015 extractable, 1016 usage_mask, 1017 &key)); 1018 1019 // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value. 1020 EXPECT_TRUE(ImportKeyJwk(json_vec, 1021 blink::WebCryptoAlgorithm::createNull(), 1022 extractable, 1023 usage_mask, 1024 &key)); 1025 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); 1026 1027 // Pass: JWK alg missing but input algorithm specified: use input value 1028 dict.Remove("alg", NULL); 1029 EXPECT_TRUE(ImportKeyJwk( 1030 MakeJsonVector(dict), 1031 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256), 1032 extractable, 1033 usage_mask, 1034 &key)); 1035 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); 1036 dict.SetString("alg", "HS256"); 1037 1038 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value 1039 // (sign|verify) 1040 EXPECT_FALSE(ImportKeyJwk( 1041 json_vec, algorithm, extractable, blink::WebCryptoKeyUsageEncrypt, &key)); 1042 1043 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK 1044 // value (sign|verify) 1045 usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign | 1046 blink::WebCryptoKeyUsageVerify; 1047 EXPECT_FALSE( 1048 ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); 1049 usage_mask = blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; 1050 1051 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value, 1052 // only certain alg values are permitted. For example, when kty = "RSA" alg 1053 // must be of the RSA family, or when kty = "oct" alg must be symmetric 1054 // algorithm. 1055 } 1056 1057 TEST_F(WebCryptoImplTest, ImportJwkHappy) { 1058 1059 // This test verifies the happy path of JWK import, including the application 1060 // of the imported key material. 1061 1062 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 1063 bool extractable = false; 1064 blink::WebCryptoAlgorithm algorithm = 1065 webcrypto::CreateHmacAlgorithmByHashId(blink::WebCryptoAlgorithmIdSha256); 1066 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign; 1067 1068 // Import a symmetric key JWK and HMAC-SHA256 sign() 1069 // Uses the first SHA256 test vector from the HMAC sample set above. 1070 1071 base::DictionaryValue dict; 1072 dict.SetString("kty", "oct"); 1073 dict.SetString("alg", "HS256"); 1074 dict.SetString("use", "sig"); 1075 dict.SetBoolean("extractable", false); 1076 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); 1077 std::vector<uint8> json_vec = MakeJsonVector(dict); 1078 1079 ASSERT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); 1080 1081 const std::vector<uint8> message_raw = HexStringToBytes( 1082 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" 1083 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" 1084 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" 1085 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); 1086 1087 blink::WebArrayBuffer output; 1088 1089 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); 1090 1091 const std::string mac_raw = 1092 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b"; 1093 1094 ExpectArrayBufferMatchesHex(mac_raw, output); 1095 1096 // TODO(padolph): Import an RSA public key JWK and use it 1097 } 1098 1099 #if !defined(USE_OPENSSL) 1100 1101 TEST_F(WebCryptoImplTest, ImportExportSpki) { 1102 // openssl genrsa -out pair.pem 2048 1103 // openssl rsa -in pair.pem -out pubkey.der -outform DER -pubout 1104 // xxd -p pubkey.der 1105 const std::string hex_rsa_spki_der = 1106 "30820122300d06092a864886f70d01010105000382010f003082010a0282" 1107 "010100f19e40f94e3780858701577a571cca000cb9795db89ddf8e98ab0e" 1108 "5eecfa47516cb08dc591cae5ab7fa43d6db402e95991d4a2de52e7cd3a66" 1109 "4f58284be2eb4675d5a849a2582c585d2b3c6c225a8f2c53a0414d5dbd06" 1110 "172371cefdf953e9ec3000fc9ad000743023f74e82d12aa93917a2c9b832" 1111 "696085ee0711154cf98a6d098f44cee00ea3b7584236503a5483ba8b6792" 1112 "fee588d1a8f4a0618333c4cb3447d760b43d5a0d9ed6ef79763df670cd8b" 1113 "5eb869a20833f1e3e6d8b88240a5d4335c73fd20487f2a7d112af8692357" 1114 "6425e44a273e5ad2e93d6b50a28e65f9e133958e4f0c7d12e0adc90fedd4" 1115 "f6b6848e7b6900666642a08b520a6534a35d4f0203010001"; 1116 1117 // Passing case: Import a valid RSA key in SPKI format. 1118 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 1119 ASSERT_TRUE(ImportKeyInternal( 1120 blink::WebCryptoKeyFormatSpki, 1121 HexStringToBytes(hex_rsa_spki_der), 1122 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), 1123 true, 1124 blink::WebCryptoKeyUsageEncrypt, 1125 &key)); 1126 EXPECT_TRUE(key.handle()); 1127 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type()); 1128 EXPECT_TRUE(key.extractable()); 1129 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); 1130 1131 // Failing case: Empty SPKI data 1132 EXPECT_FALSE(ImportKeyInternal( 1133 blink::WebCryptoKeyFormatSpki, 1134 std::vector<uint8>(), 1135 blink::WebCryptoAlgorithm::createNull(), 1136 true, 1137 blink::WebCryptoKeyUsageEncrypt, 1138 &key)); 1139 1140 // Failing case: Import RSA key with NULL input algorithm. This is not 1141 // allowed because the SPKI ASN.1 format for RSA keys is not specific enough 1142 // to map to a Web Crypto algorithm. 1143 EXPECT_FALSE(ImportKeyInternal( 1144 blink::WebCryptoKeyFormatSpki, 1145 HexStringToBytes(hex_rsa_spki_der), 1146 blink::WebCryptoAlgorithm::createNull(), 1147 true, 1148 blink::WebCryptoKeyUsageEncrypt, 1149 &key)); 1150 1151 // Failing case: Bad DER encoding. 1152 EXPECT_FALSE(ImportKeyInternal( 1153 blink::WebCryptoKeyFormatSpki, 1154 HexStringToBytes("618333c4cb"), 1155 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), 1156 true, 1157 blink::WebCryptoKeyUsageEncrypt, 1158 &key)); 1159 1160 // Failing case: Import RSA key but provide an inconsistent input algorithm. 1161 EXPECT_FALSE(ImportKeyInternal( 1162 blink::WebCryptoKeyFormatSpki, 1163 HexStringToBytes(hex_rsa_spki_der), 1164 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 1165 true, 1166 blink::WebCryptoKeyUsageEncrypt, 1167 &key)); 1168 1169 // Passing case: Export a previously imported RSA public key in SPKI format 1170 // and compare to original data. 1171 blink::WebArrayBuffer output; 1172 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 1173 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); 1174 1175 // Failing case: Try to export a previously imported RSA public key in raw 1176 // format (not allowed for a public key). 1177 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output)); 1178 1179 // Failing case: Try to export a non-extractable key 1180 ASSERT_TRUE(ImportKeyInternal( 1181 blink::WebCryptoKeyFormatSpki, 1182 HexStringToBytes(hex_rsa_spki_der), 1183 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), 1184 false, 1185 blink::WebCryptoKeyUsageEncrypt, 1186 &key)); 1187 EXPECT_TRUE(key.handle()); 1188 EXPECT_FALSE(key.extractable()); 1189 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 1190 } 1191 1192 TEST_F(WebCryptoImplTest, ImportPkcs8) { 1193 1194 // The following is a DER-encoded PKCS#8 representation of the RSA key from 1195 // Example 1 of NIST's "Test vectors for RSA PKCS#1 v1.5 Signature". 1196 // ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt 1197 const std::string hex_rsa_pkcs8_der = 1198 "30820275020100300D06092A864886F70D01010105000482025F3082025B020100028181" 1199 "00A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C510" 1200 "56FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B" 1201 "2B8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E1" 1202 "386B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137020301000102818033A5042A90B27D" 1203 "4F5451CA9BBBD0B44771A101AF884340AEF9885F2A4BBE92E894A724AC3C568C8F97853A" 1204 "D07C0266C8C6A3CA0929F1E8F11231884429FC4D9AE55FEE896A10CE707C3ED7E734E447" 1205 "27A39574501A532683109C2ABACABA283C31B4BD2F53C3EE37E352CEE34F9E503BD80C06" 1206 "22AD79C6DCEE883547C6A3B325024100E7E8942720A877517273A356053EA2A1BC0C94AA" 1207 "72D55C6E86296B2DFC967948C0A72CBCCCA7EACB35706E09A1DF55A1535BD9B3CC34160B" 1208 "3B6DCD3EDA8E6443024100B69DCA1CF7D4D7EC81E75B90FCCA874ABCDE123FD2700180AA" 1209 "90479B6E48DE8D67ED24F9F19D85BA275874F542CD20DC723E6963364A1F9425452B269A" 1210 "6799FD024028FA13938655BE1F8A159CBACA5A72EA190C30089E19CD274A556F36C4F6E1" 1211 "9F554B34C077790427BBDD8DD3EDE2448328F385D81B30E8E43B2FFFA02786197902401A" 1212 "8B38F398FA712049898D7FB79EE0A77668791299CDFA09EFC0E507ACB21ED74301EF5BFD" 1213 "48BE455EAEB6E1678255827580A8E4E8E14151D1510A82A3F2E729024027156ABA4126D2" 1214 "4A81F3A528CBFB27F56886F840A9F6E86E17A44B94FE9319584B8E22FDDE1E5A2E3BD8AA" 1215 "5BA8D8584194EB2190ACF832B847F13A3D24A79F4D"; 1216 1217 // Passing case: Import a valid RSA key in PKCS#8 format. 1218 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 1219 ASSERT_TRUE(ImportKeyInternal( 1220 blink::WebCryptoKeyFormatPkcs8, 1221 HexStringToBytes(hex_rsa_pkcs8_der), 1222 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 1223 true, 1224 blink::WebCryptoKeyUsageSign, 1225 &key)); 1226 EXPECT_TRUE(key.handle()); 1227 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type()); 1228 EXPECT_TRUE(key.extractable()); 1229 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages()); 1230 1231 // Failing case: Empty PKCS#8 data 1232 EXPECT_FALSE(ImportKeyInternal( 1233 blink::WebCryptoKeyFormatPkcs8, 1234 std::vector<uint8>(), 1235 blink::WebCryptoAlgorithm::createNull(), 1236 true, 1237 blink::WebCryptoKeyUsageSign, 1238 &key)); 1239 1240 // Failing case: Import RSA key with NULL input algorithm. This is not 1241 // allowed because the PKCS#8 ASN.1 format for RSA keys is not specific enough 1242 // to map to a Web Crypto algorithm. 1243 EXPECT_FALSE(ImportKeyInternal( 1244 blink::WebCryptoKeyFormatPkcs8, 1245 HexStringToBytes(hex_rsa_pkcs8_der), 1246 blink::WebCryptoAlgorithm::createNull(), 1247 true, 1248 blink::WebCryptoKeyUsageSign, 1249 &key)); 1250 1251 // Failing case: Bad DER encoding. 1252 EXPECT_FALSE(ImportKeyInternal( 1253 blink::WebCryptoKeyFormatPkcs8, 1254 HexStringToBytes("618333c4cb"), 1255 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 1256 true, 1257 blink::WebCryptoKeyUsageSign, 1258 &key)); 1259 1260 // Failing case: Import RSA key but provide an inconsistent input algorithm. 1261 EXPECT_FALSE(ImportKeyInternal( 1262 blink::WebCryptoKeyFormatPkcs8, 1263 HexStringToBytes(hex_rsa_pkcs8_der), 1264 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 1265 true, 1266 blink::WebCryptoKeyUsageSign, 1267 &key)); 1268 } 1269 1270 TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) { 1271 // Note: using unrealistic short key lengths here to avoid bogging down tests. 1272 1273 // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation. 1274 const unsigned modulus_length = 256; 1275 const std::vector<uint8> public_exponent = HexStringToBytes("010001"); 1276 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1277 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 1278 modulus_length, 1279 public_exponent); 1280 bool extractable = false; 1281 const blink::WebCryptoKeyUsageMask usage_mask = 0; 1282 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1283 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 1284 EXPECT_TRUE(GenerateKeyPairInternal( 1285 algorithm, extractable, usage_mask, &public_key, &private_key)); 1286 EXPECT_FALSE(public_key.isNull()); 1287 EXPECT_FALSE(private_key.isNull()); 1288 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 1289 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 1290 EXPECT_EQ(true, public_key.extractable()); 1291 EXPECT_EQ(extractable, private_key.extractable()); 1292 EXPECT_EQ(usage_mask, public_key.usages()); 1293 EXPECT_EQ(usage_mask, private_key.usages()); 1294 1295 // Fail with bad modulus. 1296 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1297 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent); 1298 EXPECT_FALSE(GenerateKeyPairInternal( 1299 algorithm, extractable, usage_mask, &public_key, &private_key)); 1300 1301 // Fail with bad exponent: larger than unsigned long. 1302 unsigned exponent_length = sizeof(unsigned long) + 1; // NOLINT 1303 const std::vector<uint8> long_exponent(exponent_length, 0x01); 1304 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1305 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, modulus_length, long_exponent); 1306 EXPECT_FALSE(GenerateKeyPairInternal( 1307 algorithm, extractable, usage_mask, &public_key, &private_key)); 1308 1309 // Fail with bad exponent: empty. 1310 const std::vector<uint8> empty_exponent; 1311 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1312 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 1313 modulus_length, 1314 empty_exponent); 1315 EXPECT_FALSE(GenerateKeyPairInternal( 1316 algorithm, extractable, usage_mask, &public_key, &private_key)); 1317 1318 // Fail with bad exponent: all zeros. 1319 std::vector<uint8> exponent_with_leading_zeros(15, 0x00); 1320 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1321 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 1322 modulus_length, 1323 exponent_with_leading_zeros); 1324 EXPECT_FALSE(GenerateKeyPairInternal( 1325 algorithm, extractable, usage_mask, &public_key, &private_key)); 1326 1327 // Key generation success using exponent with leading zeros. 1328 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(), 1329 public_exponent.begin(), 1330 public_exponent.end()); 1331 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1332 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 1333 modulus_length, 1334 exponent_with_leading_zeros); 1335 EXPECT_TRUE(GenerateKeyPairInternal( 1336 algorithm, extractable, usage_mask, &public_key, &private_key)); 1337 EXPECT_FALSE(public_key.isNull()); 1338 EXPECT_FALSE(private_key.isNull()); 1339 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 1340 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 1341 EXPECT_EQ(true, public_key.extractable()); 1342 EXPECT_EQ(extractable, private_key.extractable()); 1343 EXPECT_EQ(usage_mask, public_key.usages()); 1344 EXPECT_EQ(usage_mask, private_key.usages()); 1345 1346 // Successful WebCryptoAlgorithmIdRsaOaep key generation. 1347 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1348 blink::WebCryptoAlgorithmIdRsaOaep, modulus_length, public_exponent); 1349 EXPECT_TRUE(GenerateKeyPairInternal( 1350 algorithm, extractable, usage_mask, &public_key, &private_key)); 1351 EXPECT_FALSE(public_key.isNull()); 1352 EXPECT_FALSE(private_key.isNull()); 1353 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 1354 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 1355 EXPECT_EQ(true, public_key.extractable()); 1356 EXPECT_EQ(extractable, private_key.extractable()); 1357 EXPECT_EQ(usage_mask, public_key.usages()); 1358 EXPECT_EQ(usage_mask, private_key.usages()); 1359 1360 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation. 1361 algorithm = webcrypto::CreateRsaKeyGenAlgorithm( 1362 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 1363 modulus_length, 1364 public_exponent); 1365 EXPECT_TRUE(GenerateKeyPairInternal( 1366 algorithm, extractable, usage_mask, &public_key, &private_key)); 1367 EXPECT_FALSE(public_key.isNull()); 1368 EXPECT_FALSE(private_key.isNull()); 1369 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 1370 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 1371 EXPECT_EQ(true, public_key.extractable()); 1372 EXPECT_EQ(extractable, private_key.extractable()); 1373 EXPECT_EQ(usage_mask, public_key.usages()); 1374 EXPECT_EQ(usage_mask, private_key.usages()); 1375 1376 // Fail SPKI export of private key. This is an ExportKey test, but do it here 1377 // since it is expensive to generate an RSA key pair and we already have a 1378 // private key here. 1379 blink::WebArrayBuffer output; 1380 EXPECT_FALSE( 1381 ExportKeyInternal(blink::WebCryptoKeyFormatSpki, private_key, &output)); 1382 } 1383 1384 TEST_F(WebCryptoImplTest, RsaEsRoundTrip) { 1385 // Note: using unrealistic short key length here to avoid bogging down tests. 1386 1387 // Create a key pair. 1388 const unsigned kModulusLength = 256; 1389 blink::WebCryptoAlgorithm algorithm = 1390 CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 1391 kModulusLength, 1392 HexStringToBytes("010001")); 1393 const blink::WebCryptoKeyUsageMask usage_mask = 1394 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt; 1395 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1396 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 1397 EXPECT_TRUE(GenerateKeyPairInternal( 1398 algorithm, false, usage_mask, &public_key, &private_key)); 1399 EXPECT_FALSE(public_key.isNull()); 1400 EXPECT_FALSE(private_key.isNull()); 1401 1402 // Make a maximum-length data message. RSAES can operate on messages up to 1403 // length of k - 11 bytes, where k is the octet length of the RSA modulus. 1404 const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11; 1405 // There are two hex chars for each byte. 1406 const unsigned kMsgHexSize = kMaxMsgSizeBytes * 2; 1407 char max_data_hex[kMsgHexSize+1]; 1408 std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a'); 1409 max_data_hex[kMsgHexSize] = '\0'; 1410 1411 // Verify encrypt / decrypt round trip on a few messages. Note that RSA 1412 // encryption does not support empty input. 1413 algorithm = 1414 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); 1415 const char* const kTestDataHex[] = { 1416 "ff", 1417 "0102030405060708090a0b0c0d0e0f", 1418 max_data_hex 1419 }; 1420 blink::WebArrayBuffer encrypted_data; 1421 blink::WebArrayBuffer decrypted_data; 1422 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) { 1423 SCOPED_TRACE(i); 1424 ASSERT_TRUE(EncryptInternal( 1425 algorithm, 1426 public_key, 1427 HexStringToBytes(kTestDataHex[i]), 1428 &encrypted_data)); 1429 EXPECT_EQ(kModulusLength/8, encrypted_data.byteLength()); 1430 ASSERT_TRUE(DecryptInternal( 1431 algorithm, 1432 private_key, 1433 reinterpret_cast<const unsigned char*>(encrypted_data.data()), 1434 encrypted_data.byteLength(), 1435 &decrypted_data)); 1436 ExpectArrayBufferMatchesHex(kTestDataHex[i], decrypted_data); 1437 } 1438 } 1439 1440 TEST_F(WebCryptoImplTest, RsaEsKnownAnswer) { 1441 // Because the random data in PKCS1.5 padding makes the encryption output non- 1442 // deterministic, we cannot easily do a typical known-answer test for RSA 1443 // encryption / decryption. Instead we will take a known-good encrypted 1444 // message, decrypt it, re-encrypt it, then decrypt again, verifying that the 1445 // original known cleartext is the result. 1446 1447 // The RSA public and private keys used for this test are produced by the 1448 // openssl command line: 1449 // % openssl genrsa -out pair.pem 1024 1450 // % openssl rsa -in pair.pem -out spki.der -outform DER -pubout 1451 // % openssl pkcs8 -topk8 -inform PEM -outform DER -in pair.pem -out 1452 // pkcs8.der -nocrypt 1453 // % xxd -p spki.der 1454 // % xxd -p pkcs8.der 1455 const std::string rsa_spki_der_hex = 1456 "30819f300d06092a864886f70d010101050003818d0030818902818100a8" 1457 "d30894b93f376f7822229bfd2483e50da944c4ab803ca31979e0f47e70bf" 1458 "683c687c6b3e80f280a237cea3643fd1f7f10f7cc664dbc2ecd45be53e1c" 1459 "9b15a53c37dbdad846c0f8340c472abc7821e4aa7df185867bf38228ac3e" 1460 "cc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab64a0b7743a927e94" 1461 "4d3420401f7dd50203010001"; 1462 const std::string rsa_pkcs8_der_hex = 1463 "30820276020100300d06092a864886f70d0101010500048202603082025c" 1464 "02010002818100a8d30894b93f376f7822229bfd2483e50da944c4ab803c" 1465 "a31979e0f47e70bf683c687c6b3e80f280a237cea3643fd1f7f10f7cc664" 1466 "dbc2ecd45be53e1c9b15a53c37dbdad846c0f8340c472abc7821e4aa7df1" 1467 "85867bf38228ac3ecc1d97d3c8b57e21ea6ba57b2bc3814a436e910ee8ab" 1468 "64a0b7743a927e944d3420401f7dd5020301000102818100896cdffb50a0" 1469 "691bd00ad9696933243a7c5861a64684e8d74b91aed0d76c28234da9303e" 1470 "8c6ea2f89b141a9d5ea9a4ddd3d8eb9503dcf05ba0b1fd76060b281e3ae4" 1471 "b9d497fb5519bdf1127db8ad412d6a722686c78df3e3002acca960c6b2a2" 1472 "42a83ace5410693c03ce3d74cb9c9a7bacc8e271812920d1f53fee9312ef" 1473 "4eb1024100d09c14418ce92af7cc62f7cdc79836d8c6e3d0d33e7229cc11" 1474 "d732cbac75aa4c56c92e409a3ccbe75d4ce63ac5adca33080690782c6371" 1475 "e3628134c3534ca603024100cf2d3206f6deea2f39b70351c51f85436200" 1476 "5aa8f643e49e22486736d536e040dc30a2b4f9be3ab212a88d1891280874" 1477 "b9a170cdeb22eaf61c27c4b082c7d1470240638411a5b3b307ec6e744802" 1478 "c2d4ba556f8bfe72c7b76e790b89bd91ac13f5c9b51d04138d80b3450c1d" 1479 "4337865601bf96748b36c8f627be719f71ac3c70b441024065ce92cfe34e" 1480 "a58bf173a2b8f3024b4d5282540ac581957db3e11a7f528535ec098808dc" 1481 "a0013ffcb3b88a25716757c86c540e07d2ad8502cdd129118822c30f0240" 1482 "420a4983040e9db46eb29f1315a0d7b41cf60428f7460fce748e9a1a7d22" 1483 "d7390fa328948e7e9d1724401374e99d45eb41474781201378a4330e8e80" 1484 "8ce63551"; 1485 1486 // Similarly, the cleartext and public key encrypted ciphertext for this test 1487 // are also produced by openssl. Note that since we are using a 1024-bit key, 1488 // the cleartext size must be less than or equal to 117 bytes (modulusLength / 1489 // 8 - 11). 1490 // % openssl rand -out cleartext.bin 64 1491 // % openssl rsautl -encrypt -inkey spki.der -keyform DER -pubin -in 1492 // cleartext.bin -out ciphertext.bin 1493 // % xxd -p cleartext.bin 1494 // % xxd -p ciphertext.bin 1495 const std::string cleartext_hex = 1496 "ec358ed141c45d7e03d4c6338aebad718e8bcbbf8f8ee6f8d9f4b9ef06d8" 1497 "84739a398c6bcbc688418b2ff64761dc0ccd40e7d52bed03e06946d0957a" 1498 "eef9e822"; 1499 const std::string ciphertext_hex = 1500 "6106441c2b7a4b1a16260ed1ae4fe6135247345dc8e674754bbda6588c6c" 1501 "0d95a3d4d26bb34cdbcbe327723e80343bd7a15cd4c91c3a44e6cb9c6cd6" 1502 "7ad2e8bf41523188d9b36dc364a838642dcbc2c25e85dfb2106ba47578ca" 1503 "3bbf8915055aea4fa7c3cbfdfbcc163f04c234fb6d847f39bab9612ecbee" 1504 "04626e945c3ccf42"; 1505 1506 // Import the public key. 1507 const blink::WebCryptoAlgorithm algorithm = 1508 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); 1509 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1510 ASSERT_TRUE(ImportKeyInternal( 1511 blink::WebCryptoKeyFormatSpki, 1512 HexStringToBytes(rsa_spki_der_hex), 1513 algorithm, 1514 true, 1515 blink::WebCryptoKeyUsageEncrypt, 1516 &public_key)); 1517 EXPECT_FALSE(public_key.isNull()); 1518 EXPECT_TRUE(public_key.handle()); 1519 1520 // Import the private key. 1521 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 1522 ASSERT_TRUE(ImportKeyInternal( 1523 blink::WebCryptoKeyFormatPkcs8, 1524 HexStringToBytes(rsa_pkcs8_der_hex), 1525 algorithm, 1526 true, 1527 blink::WebCryptoKeyUsageDecrypt, 1528 &private_key)); 1529 EXPECT_FALSE(private_key.isNull()); 1530 EXPECT_TRUE(private_key.handle()); 1531 1532 // Decrypt the known-good ciphertext with the private key. As a check we must 1533 // get the known original cleartext. 1534 blink::WebArrayBuffer decrypted_data; 1535 ASSERT_TRUE(DecryptInternal( 1536 algorithm, 1537 private_key, 1538 HexStringToBytes(ciphertext_hex), 1539 &decrypted_data)); 1540 EXPECT_FALSE(decrypted_data.isNull()); 1541 ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data); 1542 1543 // Encrypt this decrypted data with the public key. 1544 blink::WebArrayBuffer encrypted_data; 1545 ASSERT_TRUE(EncryptInternal( 1546 algorithm, 1547 public_key, 1548 reinterpret_cast<const unsigned char*>(decrypted_data.data()), 1549 decrypted_data.byteLength(), 1550 &encrypted_data)); 1551 EXPECT_EQ(128u, encrypted_data.byteLength()); 1552 1553 // Finally, decrypt the newly encrypted result with the private key, and 1554 // compare to the known original cleartext. 1555 decrypted_data.reset(); 1556 ASSERT_TRUE(DecryptInternal( 1557 algorithm, 1558 private_key, 1559 reinterpret_cast<const unsigned char*>(encrypted_data.data()), 1560 encrypted_data.byteLength(), 1561 &decrypted_data)); 1562 EXPECT_FALSE(decrypted_data.isNull()); 1563 ExpectArrayBufferMatchesHex(cleartext_hex, decrypted_data); 1564 } 1565 1566 TEST_F(WebCryptoImplTest, RsaEsFailures) { 1567 // Note: using unrealistic short key length here to avoid bogging down tests. 1568 1569 // Create a key pair. 1570 const unsigned kModulusLength = 256; 1571 blink::WebCryptoAlgorithm algorithm = 1572 CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 1573 kModulusLength, 1574 HexStringToBytes("010001")); 1575 const blink::WebCryptoKeyUsageMask usage_mask = 1576 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt; 1577 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1578 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 1579 EXPECT_TRUE(GenerateKeyPairInternal( 1580 algorithm, false, usage_mask, &public_key, &private_key)); 1581 EXPECT_FALSE(public_key.isNull()); 1582 EXPECT_FALSE(private_key.isNull()); 1583 1584 // Fail encrypt with a private key. 1585 algorithm = 1586 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); 1587 blink::WebArrayBuffer encrypted_data; 1588 const std::string message_hex_str("0102030405060708090a0b0c0d0e0f"); 1589 const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str)); 1590 EXPECT_FALSE( 1591 EncryptInternal(algorithm, private_key, message_hex, &encrypted_data)); 1592 1593 // Fail encrypt with empty message. 1594 EXPECT_FALSE(EncryptInternal( 1595 algorithm, public_key, std::vector<uint8>(), &encrypted_data)); 1596 1597 // Fail encrypt with message too large. RSAES can operate on messages up to 1598 // length of k - 11 bytes, where k is the octet length of the RSA modulus. 1599 const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11; 1600 EXPECT_FALSE(EncryptInternal(algorithm, 1601 public_key, 1602 std::vector<uint8>(kMaxMsgSizeBytes + 1, '0'), 1603 &encrypted_data)); 1604 1605 // Generate encrypted data. 1606 EXPECT_TRUE( 1607 EncryptInternal(algorithm, public_key, message_hex, &encrypted_data)); 1608 1609 // Fail decrypt with a public key. 1610 blink::WebArrayBuffer decrypted_data; 1611 EXPECT_FALSE(DecryptInternal( 1612 algorithm, 1613 public_key, 1614 reinterpret_cast<const unsigned char*>(encrypted_data.data()), 1615 encrypted_data.byteLength(), 1616 &decrypted_data)); 1617 1618 // Corrupt encrypted data; ensure decrypt fails because padding was disrupted. 1619 std::vector<uint8> corrupted_data( 1620 static_cast<uint8*>(encrypted_data.data()), 1621 static_cast<uint8*>(encrypted_data.data()) + encrypted_data.byteLength()); 1622 corrupted_data[corrupted_data.size() / 2] ^= 0x01; 1623 EXPECT_FALSE( 1624 DecryptInternal(algorithm, private_key, corrupted_data, &decrypted_data)); 1625 1626 // TODO(padolph): Are there other specific data corruption scenarios to 1627 // consider? 1628 1629 // Do a successful decrypt with good data just for confirmation. 1630 EXPECT_TRUE(DecryptInternal( 1631 algorithm, 1632 private_key, 1633 reinterpret_cast<const unsigned char*>(encrypted_data.data()), 1634 encrypted_data.byteLength(), 1635 &decrypted_data)); 1636 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data); 1637 } 1638 1639 #endif // #if !defined(USE_OPENSSL) 1640 1641 } // namespace content 1642