| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/logging.h" | 5 #include "base/logging.h" |
| 6 #include "base/stl_util.h" | 6 #include "base/stl_util.h" |
| 7 #include "content/child/webcrypto/algorithm_dispatch.h" | 7 #include "content/child/webcrypto/algorithm_dispatch.h" |
| 8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
| 9 #include "content/child/webcrypto/status.h" | 9 #include "content/child/webcrypto/status.h" |
| 10 #include "content/child/webcrypto/test/test_helpers.h" | 10 #include "content/child/webcrypto/test/test_helpers.h" |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 | 253 |
| 254 TEST(WebCryptoHmacTest, ImportJwkInputConsistency) { | 254 TEST(WebCryptoHmacTest, ImportJwkInputConsistency) { |
| 255 // The Web Crypto spec says that if a JWK value is present, but is | 255 // The Web Crypto spec says that if a JWK value is present, but is |
| 256 // inconsistent with the input value, the operation must fail. | 256 // inconsistent with the input value, the operation must fail. |
| 257 | 257 |
| 258 // Consistency rules when JWK value is not present: Inputs should be used. | 258 // Consistency rules when JWK value is not present: Inputs should be used. |
| 259 blink::WebCryptoKey key; | 259 blink::WebCryptoKey key; |
| 260 bool extractable = false; | 260 bool extractable = false; |
| 261 blink::WebCryptoAlgorithm algorithm = | 261 blink::WebCryptoAlgorithm algorithm = |
| 262 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256); | 262 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256); |
| 263 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify; | 263 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageVerify; |
| 264 base::DictionaryValue dict; | 264 base::DictionaryValue dict; |
| 265 dict.SetString("kty", "oct"); | 265 dict.SetString("kty", "oct"); |
| 266 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | 266 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 267 std::vector<uint8_t> json_vec = MakeJsonVector(dict); | 267 std::vector<uint8_t> json_vec = MakeJsonVector(dict); |
| 268 EXPECT_EQ(Status::Success(), | 268 EXPECT_EQ(Status::Success(), |
| 269 ImportKey(blink::WebCryptoKeyFormatJwk, | 269 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 270 CryptoData(json_vec), | 270 CryptoData(json_vec), |
| 271 algorithm, | 271 algorithm, |
| 272 extractable, | 272 extractable, |
| 273 usage_mask, | 273 usages, |
| 274 &key)); | 274 &key)); |
| 275 EXPECT_TRUE(key.handle()); | 275 EXPECT_TRUE(key.handle()); |
| 276 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | 276 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| 277 EXPECT_EQ(extractable, key.extractable()); | 277 EXPECT_EQ(extractable, key.extractable()); |
| 278 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); | 278 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); |
| 279 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, | 279 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, |
| 280 key.algorithm().hmacParams()->hash().id()); | 280 key.algorithm().hmacParams()->hash().id()); |
| 281 EXPECT_EQ(320u, key.algorithm().hmacParams()->lengthBits()); | 281 EXPECT_EQ(320u, key.algorithm().hmacParams()->lengthBits()); |
| 282 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages()); | 282 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages()); |
| 283 key = blink::WebCryptoKey::createNull(); | 283 key = blink::WebCryptoKey::createNull(); |
| 284 | 284 |
| 285 // Consistency rules when JWK value exists: Fail if inconsistency is found. | 285 // Consistency rules when JWK value exists: Fail if inconsistency is found. |
| 286 | 286 |
| 287 // Pass: All input values are consistent with the JWK values. | 287 // Pass: All input values are consistent with the JWK values. |
| 288 dict.Clear(); | 288 dict.Clear(); |
| 289 dict.SetString("kty", "oct"); | 289 dict.SetString("kty", "oct"); |
| 290 dict.SetString("alg", "HS256"); | 290 dict.SetString("alg", "HS256"); |
| 291 dict.SetString("use", "sig"); | 291 dict.SetString("use", "sig"); |
| 292 dict.SetBoolean("ext", false); | 292 dict.SetBoolean("ext", false); |
| 293 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | 293 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 294 json_vec = MakeJsonVector(dict); | 294 json_vec = MakeJsonVector(dict); |
| 295 EXPECT_EQ(Status::Success(), | 295 EXPECT_EQ(Status::Success(), |
| 296 ImportKey(blink::WebCryptoKeyFormatJwk, | 296 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 297 CryptoData(json_vec), | 297 CryptoData(json_vec), |
| 298 algorithm, | 298 algorithm, |
| 299 extractable, | 299 extractable, |
| 300 usage_mask, | 300 usages, |
| 301 &key)); | 301 &key)); |
| 302 | 302 |
| 303 // Extractable cases: | 303 // Extractable cases: |
| 304 // 1. input=T, JWK=F ==> fail (inconsistent) | 304 // 1. input=T, JWK=F ==> fail (inconsistent) |
| 305 // 4. input=F, JWK=F ==> pass, result extractable is F | 305 // 4. input=F, JWK=F ==> pass, result extractable is F |
| 306 // 2. input=T, JWK=T ==> pass, result extractable is T | 306 // 2. input=T, JWK=T ==> pass, result extractable is T |
| 307 // 3. input=F, JWK=T ==> pass, result extractable is F | 307 // 3. input=F, JWK=T ==> pass, result extractable is F |
| 308 EXPECT_EQ(Status::ErrorJwkExtInconsistent(), | 308 EXPECT_EQ(Status::ErrorJwkExtInconsistent(), |
| 309 ImportKey(blink::WebCryptoKeyFormatJwk, | 309 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 310 CryptoData(json_vec), | 310 CryptoData(json_vec), |
| 311 algorithm, | 311 algorithm, |
| 312 true, | 312 true, |
| 313 usage_mask, | 313 usages, |
| 314 &key)); | 314 &key)); |
| 315 EXPECT_EQ(Status::Success(), | 315 EXPECT_EQ(Status::Success(), |
| 316 ImportKey(blink::WebCryptoKeyFormatJwk, | 316 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 317 CryptoData(json_vec), | 317 CryptoData(json_vec), |
| 318 algorithm, | 318 algorithm, |
| 319 false, | 319 false, |
| 320 usage_mask, | 320 usages, |
| 321 &key)); | 321 &key)); |
| 322 EXPECT_FALSE(key.extractable()); | 322 EXPECT_FALSE(key.extractable()); |
| 323 dict.SetBoolean("ext", true); | 323 dict.SetBoolean("ext", true); |
| 324 EXPECT_EQ(Status::Success(), | 324 EXPECT_EQ(Status::Success(), |
| 325 ImportKeyJwkFromDict(dict, algorithm, true, usage_mask, &key)); | 325 ImportKeyJwkFromDict(dict, algorithm, true, usages, &key)); |
| 326 EXPECT_TRUE(key.extractable()); | 326 EXPECT_TRUE(key.extractable()); |
| 327 EXPECT_EQ(Status::Success(), | 327 EXPECT_EQ(Status::Success(), |
| 328 ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key)); | 328 ImportKeyJwkFromDict(dict, algorithm, false, usages, &key)); |
| 329 EXPECT_FALSE(key.extractable()); | 329 EXPECT_FALSE(key.extractable()); |
| 330 dict.SetBoolean("ext", true); // restore previous value | 330 dict.SetBoolean("ext", true); // restore previous value |
| 331 | 331 |
| 332 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value | 332 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value |
| 333 // (HMAC SHA256). | 333 // (HMAC SHA256). |
| 334 dict.Clear(); | 334 dict.Clear(); |
| 335 dict.SetString("kty", "oct"); | 335 dict.SetString("kty", "oct"); |
| 336 dict.SetString("alg", "HS256"); | 336 dict.SetString("alg", "HS256"); |
| 337 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | 337 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 338 EXPECT_EQ( | 338 EXPECT_EQ( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 352 &key)); | 352 &key)); |
| 353 | 353 |
| 354 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value | 354 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value |
| 355 // (HMAC SHA256). | 355 // (HMAC SHA256). |
| 356 EXPECT_EQ( | 356 EXPECT_EQ( |
| 357 Status::ErrorJwkAlgorithmInconsistent(), | 357 Status::ErrorJwkAlgorithmInconsistent(), |
| 358 ImportKey(blink::WebCryptoKeyFormatJwk, | 358 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 359 CryptoData(json_vec), | 359 CryptoData(json_vec), |
| 360 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1), | 360 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1), |
| 361 extractable, | 361 extractable, |
| 362 usage_mask, | 362 usages, |
| 363 &key)); | 363 &key)); |
| 364 | 364 |
| 365 // Pass: JWK alg missing but input algorithm specified: use input value | 365 // Pass: JWK alg missing but input algorithm specified: use input value |
| 366 dict.Remove("alg", NULL); | 366 dict.Remove("alg", NULL); |
| 367 EXPECT_EQ(Status::Success(), | 367 EXPECT_EQ(Status::Success(), |
| 368 ImportKeyJwkFromDict( | 368 ImportKeyJwkFromDict( |
| 369 dict, | 369 dict, |
| 370 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256), | 370 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256), |
| 371 extractable, | 371 extractable, |
| 372 usage_mask, | 372 usages, |
| 373 &key)); | 373 &key)); |
| 374 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); | 374 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id()); |
| 375 dict.SetString("alg", "HS256"); | 375 dict.SetString("alg", "HS256"); |
| 376 | 376 |
| 377 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value | 377 // Fail: Input usages (encrypt) is not a subset of the JWK value |
| 378 // (sign|verify). Moreover "encrypt" is not a valid usage for HMAC. | 378 // (sign|verify). Moreover "encrypt" is not a valid usage for HMAC. |
| 379 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(), | 379 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(), |
| 380 ImportKey(blink::WebCryptoKeyFormatJwk, | 380 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 381 CryptoData(json_vec), | 381 CryptoData(json_vec), |
| 382 algorithm, | 382 algorithm, |
| 383 extractable, | 383 extractable, |
| 384 blink::WebCryptoKeyUsageEncrypt, | 384 blink::WebCryptoKeyUsageEncrypt, |
| 385 &key)); | 385 &key)); |
| 386 | 386 |
| 387 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK | 387 // Fail: Input usages (encrypt|sign|verify) is not a subset of the JWK |
| 388 // value (sign|verify). Moreover "encrypt" is not a valid usage for HMAC. | 388 // value (sign|verify). Moreover "encrypt" is not a valid usage for HMAC. |
| 389 usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign | | 389 usages = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign | |
| 390 blink::WebCryptoKeyUsageVerify; | 390 blink::WebCryptoKeyUsageVerify; |
| 391 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(), | 391 EXPECT_EQ(Status::ErrorCreateKeyBadUsages(), |
| 392 ImportKey(blink::WebCryptoKeyFormatJwk, | 392 ImportKey(blink::WebCryptoKeyFormatJwk, |
| 393 CryptoData(json_vec), | 393 CryptoData(json_vec), |
| 394 algorithm, | 394 algorithm, |
| 395 extractable, | 395 extractable, |
| 396 usage_mask, | 396 usages, |
| 397 &key)); | 397 &key)); |
| 398 | 398 |
| 399 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value, | 399 // TODO(padolph): kty vs alg consistency tests: Depending on the kty value, |
| 400 // only certain alg values are permitted. For example, when kty = "RSA" alg | 400 // only certain alg values are permitted. For example, when kty = "RSA" alg |
| 401 // must be of the RSA family, or when kty = "oct" alg must be symmetric | 401 // must be of the RSA family, or when kty = "oct" alg must be symmetric |
| 402 // algorithm. | 402 // algorithm. |
| 403 | 403 |
| 404 // TODO(padolph): key_ops consistency tests | 404 // TODO(padolph): key_ops consistency tests |
| 405 } | 405 } |
| 406 | 406 |
| 407 TEST(WebCryptoHmacTest, ImportJwkHappy) { | 407 TEST(WebCryptoHmacTest, ImportJwkHappy) { |
| 408 // This test verifies the happy path of JWK import, including the application | 408 // This test verifies the happy path of JWK import, including the application |
| 409 // of the imported key material. | 409 // of the imported key material. |
| 410 | 410 |
| 411 blink::WebCryptoKey key; | 411 blink::WebCryptoKey key; |
| 412 bool extractable = false; | 412 bool extractable = false; |
| 413 blink::WebCryptoAlgorithm algorithm = | 413 blink::WebCryptoAlgorithm algorithm = |
| 414 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256); | 414 CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256); |
| 415 blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign; | 415 blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign; |
| 416 | 416 |
| 417 // Import a symmetric key JWK and HMAC-SHA256 sign() | 417 // Import a symmetric key JWK and HMAC-SHA256 sign() |
| 418 // Uses the first SHA256 test vector from the HMAC sample set above. | 418 // Uses the first SHA256 test vector from the HMAC sample set above. |
| 419 | 419 |
| 420 base::DictionaryValue dict; | 420 base::DictionaryValue dict; |
| 421 dict.SetString("kty", "oct"); | 421 dict.SetString("kty", "oct"); |
| 422 dict.SetString("alg", "HS256"); | 422 dict.SetString("alg", "HS256"); |
| 423 dict.SetString("use", "sig"); | 423 dict.SetString("use", "sig"); |
| 424 dict.SetBoolean("ext", false); | 424 dict.SetBoolean("ext", false); |
| 425 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | 425 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 426 | 426 |
| 427 ASSERT_EQ( | 427 ASSERT_EQ(Status::Success(), |
| 428 Status::Success(), | 428 ImportKeyJwkFromDict(dict, algorithm, extractable, usages, &key)); |
| 429 ImportKeyJwkFromDict(dict, algorithm, extractable, usage_mask, &key)); | |
| 430 | 429 |
| 431 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, | 430 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, |
| 432 key.algorithm().hmacParams()->hash().id()); | 431 key.algorithm().hmacParams()->hash().id()); |
| 433 | 432 |
| 434 const std::vector<uint8_t> message_raw = HexStringToBytes( | 433 const std::vector<uint8_t> message_raw = HexStringToBytes( |
| 435 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" | 434 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" |
| 436 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" | 435 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" |
| 437 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" | 436 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" |
| 438 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); | 437 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); |
| 439 | 438 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 true, | 535 true, |
| 537 blink::WebCryptoKeyUsageSign, | 536 blink::WebCryptoKeyUsageSign, |
| 538 &key)); | 537 &key)); |
| 539 } | 538 } |
| 540 | 539 |
| 541 } // namespace | 540 } // namespace |
| 542 | 541 |
| 543 } // namespace webcrypto | 542 } // namespace webcrypto |
| 544 | 543 |
| 545 } // namespace content | 544 } // namespace content |
| OLD | NEW |