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/logging.h" 6 #include "base/stl_util.h" 7 #include "content/child/webcrypto/algorithm_dispatch.h" 8 #include "content/child/webcrypto/crypto_data.h" 9 #include "content/child/webcrypto/status.h" 10 #include "content/child/webcrypto/test/test_helpers.h" 11 #include "content/child/webcrypto/webcrypto_util.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 14 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 16 17 namespace content { 18 19 namespace webcrypto { 20 21 namespace { 22 23 // Helper for ImportJwkRsaFailures. Restores the JWK JSON 24 // dictionary to a good state 25 void RestoreJwkRsaDictionary(base::DictionaryValue* dict) { 26 dict->Clear(); 27 dict->SetString("kty", "RSA"); 28 dict->SetString("alg", "RS256"); 29 dict->SetString("use", "sig"); 30 dict->SetBoolean("ext", false); 31 dict->SetString( 32 "n", 33 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk" 34 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm" 35 "e7PUJHYW1PW6ENTP0ibeiNOfFvs"); 36 dict->SetString("e", "AQAB"); 37 } 38 39 TEST(WebCryptoRsaSsaTest, ImportExportSpki) { 40 // Passing case: Import a valid RSA key in SPKI format. 41 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 42 ASSERT_EQ(Status::Success(), 43 ImportKey(blink::WebCryptoKeyFormatSpki, 44 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)), 45 CreateRsaHashedImportAlgorithm( 46 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 47 blink::WebCryptoAlgorithmIdSha256), 48 true, 49 blink::WebCryptoKeyUsageVerify, 50 &key)); 51 EXPECT_TRUE(key.handle()); 52 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type()); 53 EXPECT_TRUE(key.extractable()); 54 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages()); 55 EXPECT_EQ(kModulusLengthBits, 56 key.algorithm().rsaHashedParams()->modulusLengthBits()); 57 EXPECT_BYTES_EQ_HEX( 58 "010001", 59 CryptoData(key.algorithm().rsaHashedParams()->publicExponent())); 60 61 // Failing case: Empty SPKI data 62 EXPECT_EQ( 63 Status::ErrorImportEmptyKeyData(), 64 ImportKey(blink::WebCryptoKeyFormatSpki, 65 CryptoData(std::vector<uint8_t>()), 66 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 67 true, 68 blink::WebCryptoKeyUsageVerify, 69 &key)); 70 71 // Failing case: Bad DER encoding. 72 EXPECT_EQ( 73 Status::DataError(), 74 ImportKey(blink::WebCryptoKeyFormatSpki, 75 CryptoData(HexStringToBytes("618333c4cb")), 76 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 77 true, 78 blink::WebCryptoKeyUsageVerify, 79 &key)); 80 81 // Failing case: Import RSA key but provide an inconsistent input algorithm. 82 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(), 83 ImportKey(blink::WebCryptoKeyFormatSpki, 84 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)), 85 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 86 true, 87 blink::WebCryptoKeyUsageEncrypt, 88 &key)); 89 90 // Passing case: Export a previously imported RSA public key in SPKI format 91 // and compare to original data. 92 std::vector<uint8_t> output; 93 ASSERT_EQ(Status::Success(), 94 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output)); 95 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output); 96 97 // Failing case: Try to export a previously imported RSA public key in raw 98 // format (not allowed for a public key). 99 EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(), 100 ExportKey(blink::WebCryptoKeyFormatRaw, key, &output)); 101 102 // Failing case: Try to export a non-extractable key 103 ASSERT_EQ(Status::Success(), 104 ImportKey(blink::WebCryptoKeyFormatSpki, 105 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)), 106 CreateRsaHashedImportAlgorithm( 107 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 108 blink::WebCryptoAlgorithmIdSha256), 109 false, 110 blink::WebCryptoKeyUsageVerify, 111 &key)); 112 EXPECT_TRUE(key.handle()); 113 EXPECT_FALSE(key.extractable()); 114 EXPECT_EQ(Status::ErrorKeyNotExtractable(), 115 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output)); 116 117 // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID 118 // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params 119 // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters 120 // (e.g. SHA-1 in OID, SHA-256 in params) 121 // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params 122 // as OAEP/PSS 123 } 124 125 TEST(WebCryptoRsaSsaTest, ImportExportPkcs8) { 126 if (!SupportsRsaPrivateKeyImport()) 127 return; 128 129 // Passing case: Import a valid RSA key in PKCS#8 format. 130 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 131 ASSERT_EQ(Status::Success(), 132 ImportKey(blink::WebCryptoKeyFormatPkcs8, 133 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), 134 CreateRsaHashedImportAlgorithm( 135 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 136 blink::WebCryptoAlgorithmIdSha1), 137 true, 138 blink::WebCryptoKeyUsageSign, 139 &key)); 140 EXPECT_TRUE(key.handle()); 141 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type()); 142 EXPECT_TRUE(key.extractable()); 143 EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages()); 144 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1, 145 key.algorithm().rsaHashedParams()->hash().id()); 146 EXPECT_EQ(kModulusLengthBits, 147 key.algorithm().rsaHashedParams()->modulusLengthBits()); 148 EXPECT_BYTES_EQ_HEX( 149 "010001", 150 CryptoData(key.algorithm().rsaHashedParams()->publicExponent())); 151 152 std::vector<uint8_t> exported_key; 153 ASSERT_EQ(Status::Success(), 154 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key)); 155 EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key); 156 157 // Failing case: Empty PKCS#8 data 158 EXPECT_EQ(Status::ErrorImportEmptyKeyData(), 159 ImportKey(blink::WebCryptoKeyFormatPkcs8, 160 CryptoData(std::vector<uint8_t>()), 161 CreateRsaHashedImportAlgorithm( 162 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 163 blink::WebCryptoAlgorithmIdSha1), 164 true, 165 blink::WebCryptoKeyUsageSign, 166 &key)); 167 168 // Failing case: Bad DER encoding. 169 EXPECT_EQ( 170 Status::DataError(), 171 ImportKey(blink::WebCryptoKeyFormatPkcs8, 172 CryptoData(HexStringToBytes("618333c4cb")), 173 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 174 true, 175 blink::WebCryptoKeyUsageSign, 176 &key)); 177 178 // Failing case: Import RSA key but provide an inconsistent input algorithm 179 // and usage. Several issues here: 180 // * AES-CBC doesn't support PKCS8 key format 181 // * AES-CBC doesn't support "sign" usage 182 EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(), 183 ImportKey(blink::WebCryptoKeyFormatPkcs8, 184 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), 185 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 186 true, 187 blink::WebCryptoKeyUsageSign, 188 &key)); 189 } 190 191 // Tests importing of PKCS8 data that does not define a valid RSA key. 192 TEST(WebCryptoRsaSsaTest, ImportInvalidPkcs8) { 193 if (!SupportsRsaPrivateKeyImport()) 194 return; 195 196 // kPrivateKeyPkcs8DerHex defines an RSA private key in PKCS8 format, whose 197 // parameters appear at the following offsets: 198 // 199 // n: (offset=36, len=129) 200 // e: (offset=167, len=3) 201 // d: (offset=173, len=128) 202 // p: (offset=303, len=65) 203 // q: (offset=370, len=65) 204 // dp: (offset=437, len=64) 205 // dq; (offset=503, len=64) 206 // qi: (offset=569, len=64) 207 208 // Do several tests, each of which invert a single byte within the input. 209 const unsigned int kOffsetsToCorrupt[] = { 210 50, // inside n 211 168, // inside e 212 175, // inside d 213 333, // inside p 214 373, // inside q 215 450, // inside dp 216 550, // inside dq 217 600, // inside qi 218 }; 219 220 for (size_t test_index = 0; test_index < arraysize(kOffsetsToCorrupt); 221 ++test_index) { 222 SCOPED_TRACE(test_index); 223 224 unsigned int i = kOffsetsToCorrupt[test_index]; 225 std::vector<uint8_t> corrupted_data = 226 HexStringToBytes(kPrivateKeyPkcs8DerHex); 227 corrupted_data[i] = ~corrupted_data[i]; 228 229 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 230 EXPECT_EQ(Status::DataError(), 231 ImportKey(blink::WebCryptoKeyFormatPkcs8, 232 CryptoData(corrupted_data), 233 CreateRsaHashedImportAlgorithm( 234 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 235 blink::WebCryptoAlgorithmIdSha1), 236 true, 237 blink::WebCryptoKeyUsageSign, 238 &key)); 239 } 240 } 241 242 // Tests JWK import and export by doing a roundtrip key conversion and ensuring 243 // it was lossless: 244 // 245 // PKCS8 --> JWK --> PKCS8 246 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) { 247 if (!SupportsRsaPrivateKeyImport()) 248 return; 249 250 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 251 ASSERT_EQ(Status::Success(), 252 ImportKey(blink::WebCryptoKeyFormatPkcs8, 253 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), 254 CreateRsaHashedImportAlgorithm( 255 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 256 blink::WebCryptoAlgorithmIdSha1), 257 true, 258 blink::WebCryptoKeyUsageSign, 259 &key)); 260 261 std::vector<uint8_t> exported_key_jwk; 262 ASSERT_EQ(Status::Success(), 263 ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk)); 264 265 // All of the optional parameters (p, q, dp, dq, qi) should be present in the 266 // output. 267 const char* expected_jwk = 268 "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-" 269 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ" 270 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":" 271 "\"KPoTk4ZVvh-" 272 "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-" 273 "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-" 274 "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_" 275 "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":" 276 "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_" 277 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_" 278 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-" 279 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg" 280 "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_" 281 "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":" 282 "\"JxVqukEm0kqB86Uoy_sn9WiG-" 283 "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}"; 284 285 ASSERT_EQ(CryptoData(std::string(expected_jwk)), 286 CryptoData(exported_key_jwk)); 287 288 ASSERT_EQ(Status::Success(), 289 ImportKey(blink::WebCryptoKeyFormatJwk, 290 CryptoData(exported_key_jwk), 291 CreateRsaHashedImportAlgorithm( 292 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 293 blink::WebCryptoAlgorithmIdSha1), 294 true, 295 blink::WebCryptoKeyUsageSign, 296 &key)); 297 298 std::vector<uint8_t> exported_key_pkcs8; 299 ASSERT_EQ( 300 Status::Success(), 301 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8)); 302 303 ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), 304 CryptoData(exported_key_pkcs8)); 305 } 306 307 // Tests importing multiple RSA private keys from JWK, and then exporting to 308 // PKCS8. 309 // 310 // This is a regression test for http://crbug.com/378315, for which importing 311 // a sequence of keys from JWK could yield the wrong key. The first key would 312 // be imported correctly, however every key after that would actually import 313 // the first key. 314 TEST(WebCryptoRsaSsaTest, ImportMultipleRSAPrivateKeysJwk) { 315 if (!SupportsRsaPrivateKeyImport()) 316 return; 317 318 scoped_ptr<base::ListValue> key_list; 319 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list)); 320 321 // For this test to be meaningful the keys MUST be kept alive before importing 322 // new keys. 323 std::vector<blink::WebCryptoKey> live_keys; 324 325 for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) { 326 SCOPED_TRACE(key_index); 327 328 base::DictionaryValue* key_values; 329 ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values)); 330 331 // Get the JWK representation of the key. 332 base::DictionaryValue* key_jwk; 333 ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk)); 334 335 // Get the PKCS8 representation of the key. 336 std::string pkcs8_hex_string; 337 ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string)); 338 std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string); 339 340 // Get the modulus length for the key. 341 int modulus_length_bits = 0; 342 ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits)); 343 344 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 345 346 // Import the key from JWK. 347 ASSERT_EQ( 348 Status::Success(), 349 ImportKeyJwkFromDict(*key_jwk, 350 CreateRsaHashedImportAlgorithm( 351 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 352 blink::WebCryptoAlgorithmIdSha256), 353 true, 354 blink::WebCryptoKeyUsageSign, 355 &private_key)); 356 357 live_keys.push_back(private_key); 358 359 EXPECT_EQ( 360 modulus_length_bits, 361 static_cast<int>( 362 private_key.algorithm().rsaHashedParams()->modulusLengthBits())); 363 364 // Export to PKCS8 and verify that it matches expectation. 365 std::vector<uint8_t> exported_key_pkcs8; 366 ASSERT_EQ( 367 Status::Success(), 368 ExportKey( 369 blink::WebCryptoKeyFormatPkcs8, private_key, &exported_key_pkcs8)); 370 371 EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8); 372 } 373 } 374 375 // Import an RSA private key using JWK. Next import a JWK containing the same 376 // modulus, but mismatched parameters for the rest. It should NOT be possible 377 // that the second import retrieves the first key. See http://crbug.com/378315 378 // for how that could happen. 379 TEST(WebCryptoRsaSsaTest, ImportJwkExistingModulusAndInvalid) { 380 if (!SupportsRsaPrivateKeyImport()) 381 return; 382 383 scoped_ptr<base::ListValue> key_list; 384 ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list)); 385 386 // Import a 1024-bit private key. 387 base::DictionaryValue* key1_props; 388 ASSERT_TRUE(key_list->GetDictionary(1, &key1_props)); 389 base::DictionaryValue* key1_jwk; 390 ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk)); 391 392 blink::WebCryptoKey key1 = blink::WebCryptoKey::createNull(); 393 ASSERT_EQ(Status::Success(), 394 ImportKeyJwkFromDict(*key1_jwk, 395 CreateRsaHashedImportAlgorithm( 396 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 397 blink::WebCryptoAlgorithmIdSha256), 398 true, 399 blink::WebCryptoKeyUsageSign, 400 &key1)); 401 402 ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits()); 403 404 // Construct a JWK using the modulus of key1, but all the other fields from 405 // another key (also a 1024-bit private key). 406 base::DictionaryValue* key2_props; 407 ASSERT_TRUE(key_list->GetDictionary(5, &key2_props)); 408 base::DictionaryValue* key2_jwk; 409 ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk)); 410 std::string modulus; 411 key1_jwk->GetString("n", &modulus); 412 key2_jwk->SetString("n", modulus); 413 414 // This should fail, as the n,e,d parameters are not consistent. It MUST NOT 415 // somehow return the key created earlier. 416 blink::WebCryptoKey key2 = blink::WebCryptoKey::createNull(); 417 ASSERT_EQ(Status::OperationError(), 418 ImportKeyJwkFromDict(*key2_jwk, 419 CreateRsaHashedImportAlgorithm( 420 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 421 blink::WebCryptoAlgorithmIdSha256), 422 true, 423 blink::WebCryptoKeyUsageSign, 424 &key2)); 425 } 426 427 // Import a JWK RSA private key with some optional parameters missing (q, dp, 428 // dq, qi). 429 // 430 // The only optional parameter included is "p". 431 // 432 // This fails because JWA says that producers must include either ALL optional 433 // parameters or NONE. 434 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkMissingOptionalParams) { 435 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 436 437 base::DictionaryValue dict; 438 dict.SetString("kty", "RSA"); 439 dict.SetString("alg", "RS1"); 440 441 dict.SetString( 442 "n", 443 "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_" 444 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_" 445 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc"); 446 dict.SetString("e", "AQAB"); 447 dict.SetString( 448 "d", 449 "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-" 450 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ" 451 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU"); 452 453 dict.SetString("p", 454 "5-" 455 "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31W" 456 "hU1vZs8w0Fgs7bc0-2o5kQw"); 457 458 ASSERT_EQ(Status::ErrorJwkPropertyMissing("q"), 459 ImportKeyJwkFromDict(dict, 460 CreateRsaHashedImportAlgorithm( 461 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 462 blink::WebCryptoAlgorithmIdSha1), 463 true, 464 blink::WebCryptoKeyUsageSign, 465 &key)); 466 } 467 468 // Import a JWK RSA private key, without any of the optional parameters. 469 // 470 // According to JWA, such keys are valid, but applications SHOULD 471 // include all the parameters when sending, and recipients MAY 472 // accept them, but are not required to. Chromium's WebCrypto does 473 // not allow such degenerate keys. 474 TEST(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkIncorrectOptionalEmpty) { 475 if (!SupportsRsaPrivateKeyImport()) 476 return; 477 478 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 479 480 base::DictionaryValue dict; 481 dict.SetString("kty", "RSA"); 482 dict.SetString("alg", "RS1"); 483 484 dict.SetString( 485 "n", 486 "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_" 487 "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_" 488 "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc"); 489 dict.SetString("e", "AQAB"); 490 dict.SetString( 491 "d", 492 "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-" 493 "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ" 494 "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU"); 495 496 ASSERT_EQ(Status::ErrorJwkPropertyMissing("p"), 497 ImportKeyJwkFromDict(dict, 498 CreateRsaHashedImportAlgorithm( 499 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 500 blink::WebCryptoAlgorithmIdSha1), 501 true, 502 blink::WebCryptoKeyUsageSign, 503 &key)); 504 } 505 506 // Tries importing a public RSA key whose exponent contains leading zeros. 507 TEST(WebCryptoRsaSsaTest, ImportJwkRsaNonMinimalExponent) { 508 base::DictionaryValue dict; 509 510 dict.SetString("kty", "RSA"); 511 dict.SetString("e", "AAEAAQ"); // 00 01 00 01 512 dict.SetString( 513 "n", 514 "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk" 515 "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm" 516 "e7PUJHYW1PW6ENTP0ibeiNOfFvs"); 517 518 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 519 520 EXPECT_EQ(Status::ErrorJwkBigIntegerHasLeadingZero("e"), 521 ImportKeyJwkFromDict(dict, 522 CreateRsaHashedImportAlgorithm( 523 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 524 blink::WebCryptoAlgorithmIdSha256), 525 false, 526 blink::WebCryptoKeyUsageVerify, 527 &key)); 528 } 529 530 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsa) { 531 // Note: using unrealistic short key lengths here to avoid bogging down tests. 532 533 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256) 534 const unsigned int modulus_length = 256; 535 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001"); 536 blink::WebCryptoAlgorithm algorithm = 537 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 538 blink::WebCryptoAlgorithmIdSha256, 539 modulus_length, 540 public_exponent); 541 bool extractable = true; 542 const blink::WebCryptoKeyUsageMask usage_mask = 0; 543 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 544 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 545 546 EXPECT_EQ(Status::Success(), 547 GenerateKeyPair( 548 algorithm, extractable, usage_mask, &public_key, &private_key)); 549 EXPECT_FALSE(public_key.isNull()); 550 EXPECT_FALSE(private_key.isNull()); 551 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 552 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 553 EXPECT_EQ(modulus_length, 554 public_key.algorithm().rsaHashedParams()->modulusLengthBits()); 555 EXPECT_EQ(modulus_length, 556 private_key.algorithm().rsaHashedParams()->modulusLengthBits()); 557 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, 558 public_key.algorithm().rsaHashedParams()->hash().id()); 559 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, 560 private_key.algorithm().rsaHashedParams()->hash().id()); 561 EXPECT_TRUE(public_key.extractable()); 562 EXPECT_EQ(extractable, private_key.extractable()); 563 EXPECT_EQ(usage_mask, public_key.usages()); 564 EXPECT_EQ(usage_mask, private_key.usages()); 565 566 // Try exporting the generated key pair, and then re-importing to verify that 567 // the exported data was valid. 568 std::vector<uint8_t> public_key_spki; 569 EXPECT_EQ( 570 Status::Success(), 571 ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki)); 572 573 if (SupportsRsaPrivateKeyImport()) { 574 public_key = blink::WebCryptoKey::createNull(); 575 EXPECT_EQ(Status::Success(), 576 ImportKey(blink::WebCryptoKeyFormatSpki, 577 CryptoData(public_key_spki), 578 CreateRsaHashedImportAlgorithm( 579 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 580 blink::WebCryptoAlgorithmIdSha256), 581 true, 582 usage_mask, 583 &public_key)); 584 EXPECT_EQ(modulus_length, 585 public_key.algorithm().rsaHashedParams()->modulusLengthBits()); 586 587 std::vector<uint8_t> private_key_pkcs8; 588 EXPECT_EQ( 589 Status::Success(), 590 ExportKey( 591 blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8)); 592 private_key = blink::WebCryptoKey::createNull(); 593 EXPECT_EQ(Status::Success(), 594 ImportKey(blink::WebCryptoKeyFormatPkcs8, 595 CryptoData(private_key_pkcs8), 596 CreateRsaHashedImportAlgorithm( 597 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 598 blink::WebCryptoAlgorithmIdSha256), 599 true, 600 usage_mask, 601 &private_key)); 602 EXPECT_EQ(modulus_length, 603 private_key.algorithm().rsaHashedParams()->modulusLengthBits()); 604 } 605 606 // Fail with bad modulus. 607 algorithm = 608 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 609 blink::WebCryptoAlgorithmIdSha256, 610 0, 611 public_exponent); 612 EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(), 613 GenerateKeyPair( 614 algorithm, extractable, usage_mask, &public_key, &private_key)); 615 616 // Fail with bad exponent: larger than unsigned long. 617 unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT 618 const std::vector<uint8_t> long_exponent(exponent_length, 0x01); 619 algorithm = 620 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 621 blink::WebCryptoAlgorithmIdSha256, 622 modulus_length, 623 long_exponent); 624 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(), 625 GenerateKeyPair( 626 algorithm, extractable, usage_mask, &public_key, &private_key)); 627 628 // Fail with bad exponent: empty. 629 const std::vector<uint8_t> empty_exponent; 630 algorithm = 631 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 632 blink::WebCryptoAlgorithmIdSha256, 633 modulus_length, 634 empty_exponent); 635 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(), 636 GenerateKeyPair( 637 algorithm, extractable, usage_mask, &public_key, &private_key)); 638 639 // Fail with bad exponent: all zeros. 640 std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00); 641 algorithm = 642 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 643 blink::WebCryptoAlgorithmIdSha256, 644 modulus_length, 645 exponent_with_leading_zeros); 646 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(), 647 GenerateKeyPair( 648 algorithm, extractable, usage_mask, &public_key, &private_key)); 649 650 // Key generation success using exponent with leading zeros. 651 exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(), 652 public_exponent.begin(), 653 public_exponent.end()); 654 algorithm = 655 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 656 blink::WebCryptoAlgorithmIdSha256, 657 modulus_length, 658 exponent_with_leading_zeros); 659 EXPECT_EQ(Status::Success(), 660 GenerateKeyPair( 661 algorithm, extractable, usage_mask, &public_key, &private_key)); 662 EXPECT_FALSE(public_key.isNull()); 663 EXPECT_FALSE(private_key.isNull()); 664 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 665 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 666 EXPECT_TRUE(public_key.extractable()); 667 EXPECT_EQ(extractable, private_key.extractable()); 668 EXPECT_EQ(usage_mask, public_key.usages()); 669 EXPECT_EQ(usage_mask, private_key.usages()); 670 671 // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1) 672 algorithm = 673 CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 674 blink::WebCryptoAlgorithmIdSha1, 675 modulus_length, 676 public_exponent); 677 EXPECT_EQ( 678 Status::Success(), 679 GenerateKeyPair(algorithm, false, usage_mask, &public_key, &private_key)); 680 EXPECT_FALSE(public_key.isNull()); 681 EXPECT_FALSE(private_key.isNull()); 682 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type()); 683 EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type()); 684 EXPECT_EQ(modulus_length, 685 public_key.algorithm().rsaHashedParams()->modulusLengthBits()); 686 EXPECT_EQ(modulus_length, 687 private_key.algorithm().rsaHashedParams()->modulusLengthBits()); 688 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1, 689 public_key.algorithm().rsaHashedParams()->hash().id()); 690 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1, 691 private_key.algorithm().rsaHashedParams()->hash().id()); 692 // Even though "extractable" was set to false, the public key remains 693 // extractable. 694 EXPECT_TRUE(public_key.extractable()); 695 EXPECT_FALSE(private_key.extractable()); 696 EXPECT_EQ(usage_mask, public_key.usages()); 697 EXPECT_EQ(usage_mask, private_key.usages()); 698 699 // Exporting a private key as SPKI format doesn't make sense. However this 700 // will first fail because the key is not extractable. 701 std::vector<uint8_t> output; 702 EXPECT_EQ(Status::ErrorKeyNotExtractable(), 703 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output)); 704 705 // Re-generate an extractable private_key and try to export it as SPKI format. 706 // This should fail since spki is for public keys. 707 EXPECT_EQ( 708 Status::Success(), 709 GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key)); 710 EXPECT_EQ(Status::ErrorUnexpectedKeyType(), 711 ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output)); 712 } 713 714 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadModulusLength) { 715 const unsigned int kBadModulusBits[] = { 716 0, 717 248, // Too small. 718 257, // Not a multiple of 8. 719 1023, // Not a multiple of 8. 720 0xFFFFFFFF, // Too big. 721 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for. 722 }; 723 724 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001"); 725 726 for (size_t i = 0; i < arraysize(kBadModulusBits); ++i) { 727 const unsigned int modulus_length_bits = kBadModulusBits[i]; 728 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm( 729 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 730 blink::WebCryptoAlgorithmIdSha256, 731 modulus_length_bits, 732 public_exponent); 733 bool extractable = true; 734 const blink::WebCryptoKeyUsageMask usage_mask = 0; 735 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 736 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 737 738 EXPECT_EQ( 739 Status::ErrorGenerateRsaUnsupportedModulus(), 740 GenerateKeyPair( 741 algorithm, extractable, usage_mask, &public_key, &private_key)); 742 } 743 } 744 745 // Try generating RSA key pairs using unsupported public exponents. Only 746 // exponents of 3 and 65537 are supported. While both OpenSSL and NSS can 747 // support other values, OpenSSL hangs when given invalid exponents, so use a 748 // whitelist to validate the parameters. 749 TEST(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) { 750 const unsigned int modulus_length = 1024; 751 752 const char* const kPublicExponents[] = { 753 "11", // 17 - This is a valid public exponent, but currently disallowed. 754 "00", "01", "02", 755 "010000", // 65536 756 }; 757 758 for (size_t i = 0; i < arraysize(kPublicExponents); ++i) { 759 SCOPED_TRACE(i); 760 blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm( 761 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 762 blink::WebCryptoAlgorithmIdSha256, 763 modulus_length, 764 HexStringToBytes(kPublicExponents[i])); 765 766 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 767 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 768 769 EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(), 770 GenerateKeyPair(algorithm, true, 0, &public_key, &private_key)); 771 } 772 } 773 774 TEST(WebCryptoRsaSsaTest, SignVerifyFailures) { 775 if (!SupportsRsaPrivateKeyImport()) 776 return; 777 778 // Import a key pair. 779 blink::WebCryptoAlgorithm import_algorithm = 780 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 781 blink::WebCryptoAlgorithmIdSha1); 782 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 783 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 784 ASSERT_NO_FATAL_FAILURE( 785 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), 786 HexStringToBytes(kPrivateKeyPkcs8DerHex), 787 import_algorithm, 788 false, 789 blink::WebCryptoKeyUsageVerify, 790 blink::WebCryptoKeyUsageSign, 791 &public_key, 792 &private_key)); 793 794 blink::WebCryptoAlgorithm algorithm = 795 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); 796 797 std::vector<uint8_t> signature; 798 bool signature_match; 799 800 // Compute a signature. 801 const std::vector<uint8_t> data = HexStringToBytes("010203040506070809"); 802 ASSERT_EQ(Status::Success(), 803 Sign(algorithm, private_key, CryptoData(data), &signature)); 804 805 // Ensure truncated signature does not verify by passing one less byte. 806 EXPECT_EQ( 807 Status::Success(), 808 Verify(algorithm, 809 public_key, 810 CryptoData(vector_as_array(&signature), signature.size() - 1), 811 CryptoData(data), 812 &signature_match)); 813 EXPECT_FALSE(signature_match); 814 815 // Ensure truncated signature does not verify by passing no bytes. 816 EXPECT_EQ(Status::Success(), 817 Verify(algorithm, 818 public_key, 819 CryptoData(), 820 CryptoData(data), 821 &signature_match)); 822 EXPECT_FALSE(signature_match); 823 824 // Ensure corrupted signature does not verify. 825 std::vector<uint8_t> corrupt_sig = signature; 826 corrupt_sig[corrupt_sig.size() / 2] ^= 0x1; 827 EXPECT_EQ(Status::Success(), 828 Verify(algorithm, 829 public_key, 830 CryptoData(corrupt_sig), 831 CryptoData(data), 832 &signature_match)); 833 EXPECT_FALSE(signature_match); 834 835 // Ensure signatures that are greater than the modulus size fail. 836 const unsigned int long_message_size_bytes = 1024; 837 DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8); 838 const unsigned char kLongSignature[long_message_size_bytes] = {0}; 839 EXPECT_EQ(Status::Success(), 840 Verify(algorithm, 841 public_key, 842 CryptoData(kLongSignature, sizeof(kLongSignature)), 843 CryptoData(data), 844 &signature_match)); 845 EXPECT_FALSE(signature_match); 846 847 // Ensure that signing and verifying with an incompatible algorithm fails. 848 algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep); 849 850 EXPECT_EQ(Status::ErrorUnexpected(), 851 Sign(algorithm, private_key, CryptoData(data), &signature)); 852 EXPECT_EQ(Status::ErrorUnexpected(), 853 Verify(algorithm, 854 public_key, 855 CryptoData(signature), 856 CryptoData(data), 857 &signature_match)); 858 859 // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash 860 // based solely on the contents of the input signature data. In the Web Crypto 861 // implementation, the inner hash should be specified uniquely by the key 862 // algorithm parameter. To validate this behavior, call Verify with a computed 863 // signature that used one hash type (SHA-1), but pass in a key with a 864 // different inner hash type (SHA-256). If the hash type is determined by the 865 // signature itself (undesired), the verify will pass, while if the hash type 866 // is specified by the key algorithm (desired), the verify will fail. 867 868 // Compute a signature using SHA-1 as the inner hash. 869 EXPECT_EQ(Status::Success(), 870 Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 871 private_key, 872 CryptoData(data), 873 &signature)); 874 875 blink::WebCryptoKey public_key_256 = blink::WebCryptoKey::createNull(); 876 EXPECT_EQ(Status::Success(), 877 ImportKey(blink::WebCryptoKeyFormatSpki, 878 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)), 879 CreateRsaHashedImportAlgorithm( 880 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 881 blink::WebCryptoAlgorithmIdSha256), 882 true, 883 blink::WebCryptoKeyUsageVerify, 884 &public_key_256)); 885 886 // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The 887 // signature should not verify. 888 // NOTE: public_key was produced by generateKey, and so its associated 889 // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus 890 // it has no inner hash to conflict with the input algorithm. 891 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1, 892 private_key.algorithm().rsaHashedParams()->hash().id()); 893 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, 894 public_key_256.algorithm().rsaHashedParams()->hash().id()); 895 896 bool is_match; 897 EXPECT_EQ(Status::Success(), 898 Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5), 899 public_key_256, 900 CryptoData(signature), 901 CryptoData(data), 902 &is_match)); 903 EXPECT_FALSE(is_match); 904 } 905 906 TEST(WebCryptoRsaSsaTest, SignVerifyKnownAnswer) { 907 if (!SupportsRsaPrivateKeyImport()) 908 return; 909 910 scoped_ptr<base::ListValue> tests; 911 ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests)); 912 913 // Import the key pair. 914 blink::WebCryptoAlgorithm import_algorithm = 915 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 916 blink::WebCryptoAlgorithmIdSha1); 917 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 918 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 919 ASSERT_NO_FATAL_FAILURE( 920 ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex), 921 HexStringToBytes(kPrivateKeyPkcs8DerHex), 922 import_algorithm, 923 false, 924 blink::WebCryptoKeyUsageVerify, 925 blink::WebCryptoKeyUsageSign, 926 &public_key, 927 &private_key)); 928 929 blink::WebCryptoAlgorithm algorithm = 930 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); 931 932 // Validate the signatures are computed and verified as expected. 933 std::vector<uint8_t> signature; 934 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { 935 SCOPED_TRACE(test_index); 936 937 base::DictionaryValue* test; 938 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); 939 940 std::vector<uint8_t> test_message = 941 GetBytesFromHexString(test, "message_hex"); 942 std::vector<uint8_t> test_signature = 943 GetBytesFromHexString(test, "signature_hex"); 944 945 signature.clear(); 946 ASSERT_EQ( 947 Status::Success(), 948 Sign(algorithm, private_key, CryptoData(test_message), &signature)); 949 EXPECT_BYTES_EQ(test_signature, signature); 950 951 bool is_match = false; 952 ASSERT_EQ(Status::Success(), 953 Verify(algorithm, 954 public_key, 955 CryptoData(test_signature), 956 CryptoData(test_message), 957 &is_match)); 958 EXPECT_TRUE(is_match); 959 } 960 } 961 962 // Try importing an RSA-SSA public key with unsupported key usages using SPKI 963 // format. RSA-SSA public keys only support the 'verify' usage. 964 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_SPKI) { 965 const blink::WebCryptoAlgorithm algorithm = 966 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 967 blink::WebCryptoAlgorithmIdSha256); 968 969 blink::WebCryptoKeyUsageMask bad_usages[] = { 970 blink::WebCryptoKeyUsageSign, 971 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, 972 blink::WebCryptoKeyUsageEncrypt, 973 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt, 974 }; 975 976 for (size_t i = 0; i < arraysize(bad_usages); ++i) { 977 SCOPED_TRACE(i); 978 979 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 980 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), 981 ImportKey(blink::WebCryptoKeyFormatSpki, 982 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)), 983 algorithm, 984 false, 985 bad_usages[i], 986 &public_key)); 987 } 988 } 989 990 // Try importing an RSA-SSA public key with unsupported key usages using JWK 991 // format. RSA-SSA public keys only support the 'verify' usage. 992 TEST(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_JWK) { 993 const blink::WebCryptoAlgorithm algorithm = 994 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 995 blink::WebCryptoAlgorithmIdSha256); 996 997 blink::WebCryptoKeyUsageMask bad_usages[] = { 998 blink::WebCryptoKeyUsageSign, 999 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, 1000 blink::WebCryptoKeyUsageEncrypt, 1001 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt, 1002 }; 1003 1004 base::DictionaryValue dict; 1005 RestoreJwkRsaDictionary(&dict); 1006 dict.Remove("use", NULL); 1007 dict.SetString("alg", "RS256"); 1008 1009 for (size_t i = 0; i < arraysize(bad_usages); ++i) { 1010 SCOPED_TRACE(i); 1011 1012 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1013 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), 1014 ImportKeyJwkFromDict( 1015 dict, algorithm, false, bad_usages[i], &public_key)); 1016 } 1017 } 1018 1019 // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports: 1020 // 'sign', 'verify' 1021 TEST(WebCryptoRsaSsaTest, GenerateKeyBadUsages) { 1022 blink::WebCryptoKeyUsageMask bad_usages[] = { 1023 blink::WebCryptoKeyUsageDecrypt, 1024 blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt, 1025 blink::WebCryptoKeyUsageWrapKey, 1026 }; 1027 1028 const unsigned int modulus_length = 256; 1029 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001"); 1030 1031 for (size_t i = 0; i < arraysize(bad_usages); ++i) { 1032 SCOPED_TRACE(i); 1033 1034 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1035 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 1036 1037 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), 1038 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm( 1039 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 1040 blink::WebCryptoAlgorithmIdSha256, 1041 modulus_length, 1042 public_exponent), 1043 true, 1044 bad_usages[i], 1045 &public_key, 1046 &private_key)); 1047 } 1048 } 1049 1050 // Generate an RSA-SSA key pair. The public and private keys should select the 1051 // key usages which are applicable, and not have the exact same usages as was 1052 // specified to GenerateKey 1053 TEST(WebCryptoRsaSsaTest, GenerateKeyPairIntersectUsages) { 1054 const unsigned int modulus_length = 256; 1055 const std::vector<uint8_t> public_exponent = HexStringToBytes("010001"); 1056 1057 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1058 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 1059 1060 ASSERT_EQ(Status::Success(), 1061 GenerateKeyPair( 1062 CreateRsaHashedKeyGenAlgorithm( 1063 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 1064 blink::WebCryptoAlgorithmIdSha256, 1065 modulus_length, 1066 public_exponent), 1067 true, 1068 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, 1069 &public_key, 1070 &private_key)); 1071 1072 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages()); 1073 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages()); 1074 1075 // Try again but this time without the Verify usages. 1076 ASSERT_EQ(Status::Success(), 1077 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm( 1078 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 1079 blink::WebCryptoAlgorithmIdSha256, 1080 modulus_length, 1081 public_exponent), 1082 true, 1083 blink::WebCryptoKeyUsageSign, 1084 &public_key, 1085 &private_key)); 1086 1087 EXPECT_EQ(0, public_key.usages()); 1088 EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages()); 1089 } 1090 1091 TEST(WebCryptoRsaSsaTest, ImportExportJwkRsaPublicKey) { 1092 struct TestCase { 1093 const blink::WebCryptoAlgorithmId hash; 1094 const blink::WebCryptoKeyUsageMask usage; 1095 const char* const jwk_alg; 1096 }; 1097 const TestCase kTests[] = { 1098 {blink::WebCryptoAlgorithmIdSha1, blink::WebCryptoKeyUsageVerify, "RS1"}, 1099 {blink::WebCryptoAlgorithmIdSha256, blink::WebCryptoKeyUsageVerify, 1100 "RS256"}, 1101 {blink::WebCryptoAlgorithmIdSha384, blink::WebCryptoKeyUsageVerify, 1102 "RS384"}, 1103 {blink::WebCryptoAlgorithmIdSha512, blink::WebCryptoKeyUsageVerify, 1104 "RS512"}}; 1105 1106 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); 1107 ++test_index) { 1108 SCOPED_TRACE(test_index); 1109 const TestCase& test = kTests[test_index]; 1110 1111 const blink::WebCryptoAlgorithm import_algorithm = 1112 CreateRsaHashedImportAlgorithm( 1113 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, test.hash); 1114 1115 // Import the spki to create a public key 1116 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 1117 ASSERT_EQ(Status::Success(), 1118 ImportKey(blink::WebCryptoKeyFormatSpki, 1119 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)), 1120 import_algorithm, 1121 true, 1122 test.usage, 1123 &public_key)); 1124 1125 // Export the public key as JWK and verify its contents 1126 std::vector<uint8_t> jwk; 1127 ASSERT_EQ(Status::Success(), 1128 ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk)); 1129 EXPECT_TRUE(VerifyPublicJwk(jwk, 1130 test.jwk_alg, 1131 kPublicKeyModulusHex, 1132 kPublicKeyExponentHex, 1133 test.usage)); 1134 1135 // Import the JWK back in to create a new key 1136 blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull(); 1137 ASSERT_EQ(Status::Success(), 1138 ImportKey(blink::WebCryptoKeyFormatJwk, 1139 CryptoData(jwk), 1140 import_algorithm, 1141 true, 1142 test.usage, 1143 &public_key2)); 1144 ASSERT_TRUE(public_key2.handle()); 1145 EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type()); 1146 EXPECT_TRUE(public_key2.extractable()); 1147 EXPECT_EQ(import_algorithm.id(), public_key2.algorithm().id()); 1148 1149 // Export the new key as spki and compare to the original. 1150 std::vector<uint8_t> spki; 1151 ASSERT_EQ(Status::Success(), 1152 ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki)); 1153 EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki)); 1154 } 1155 } 1156 1157 TEST(WebCryptoRsaSsaTest, ImportJwkRsaFailures) { 1158 base::DictionaryValue dict; 1159 RestoreJwkRsaDictionary(&dict); 1160 blink::WebCryptoAlgorithm algorithm = 1161 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, 1162 blink::WebCryptoAlgorithmIdSha256); 1163 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify; 1164 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 1165 1166 // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent) 1167 // entry, while an RSA private key must have those plus at least a "d" 1168 // (private exponent) entry. 1169 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, 1170 // section 6.3. 1171 1172 // Baseline pass. 1173 EXPECT_EQ(Status::Success(), 1174 ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key)); 1175 EXPECT_EQ(algorithm.id(), key.algorithm().id()); 1176 EXPECT_FALSE(key.extractable()); 1177 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages()); 1178 EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type()); 1179 1180 // The following are specific failure cases for when kty = "RSA". 1181 1182 // Fail if either "n" or "e" is not present or malformed. 1183 const std::string kKtyParmName[] = {"n", "e"}; 1184 for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) { 1185 // Fail on missing parameter. 1186 dict.Remove(kKtyParmName[idx], NULL); 1187 EXPECT_NE(Status::Success(), 1188 ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key)); 1189 RestoreJwkRsaDictionary(&dict); 1190 1191 // Fail on bad b64 parameter encoding. 1192 dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0"); 1193 EXPECT_NE(Status::Success(), 1194 ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key)); 1195 RestoreJwkRsaDictionary(&dict); 1196 1197 // Fail on empty parameter. 1198 dict.SetString(kKtyParmName[idx], ""); 1199 EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(kKtyParmName[idx]), 1200 ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key)); 1201 RestoreJwkRsaDictionary(&dict); 1202 } 1203 } 1204 1205 } // namespace 1206 1207 } // namespace webcrypto 1208 1209 } // namespace content 1210