| 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 "content/child/webcrypto/shared_crypto.h" | 5 #include "content/child/webcrypto/shared_crypto.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
| 9 #include "content/child/webcrypto/jwk.h" | 9 #include "content/child/webcrypto/jwk.h" |
| 10 #include "content/child/webcrypto/platform_crypto.h" | 10 #include "content/child/webcrypto/platform_crypto.h" |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 case blink::WebCryptoKeyAlgorithmParamsTypeNone: | 301 case blink::WebCryptoKeyAlgorithmParamsTypeNone: |
| 302 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: | 302 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: |
| 303 break; | 303 break; |
| 304 default: | 304 default: |
| 305 return false; | 305 return false; |
| 306 } | 306 } |
| 307 | 307 |
| 308 return true; | 308 return true; |
| 309 } | 309 } |
| 310 | 310 |
| 311 // Validates the size of data input to AES-KW. AES-KW requires the input data | 311 Status EncryptDecryptAesKw(EncryptOrDecrypt mode, |
| 312 // size to be at least 24 bytes and a multiple of 8 bytes. | 312 const blink::WebCryptoAlgorithm& algorithm, |
| 313 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) { | 313 const blink::WebCryptoKey& key, |
| 314 if (aeskw_input_data.byte_length() < 24) | 314 const CryptoData& data, |
| 315 return Status::ErrorDataTooSmall(); | 315 std::vector<uint8>* buffer) { |
| 316 if (aeskw_input_data.byte_length() % 8) | |
| 317 return Status::ErrorInvalidAesKwDataLength(); | |
| 318 return Status::Success(); | |
| 319 } | |
| 320 | |
| 321 Status UnwrapKeyRaw(const CryptoData& wrapped_key_data, | |
| 322 const blink::WebCryptoKey& wrapping_key, | |
| 323 const blink::WebCryptoAlgorithm& wrapping_algorithm, | |
| 324 const blink::WebCryptoAlgorithm& algorithm, | |
| 325 bool extractable, | |
| 326 blink::WebCryptoKeyUsageMask usage_mask, | |
| 327 blink::WebCryptoKey* key) { | |
| 328 // TODO(padolph): Handle other wrapping algorithms | |
| 329 switch (wrapping_algorithm.id()) { | |
| 330 case blink::WebCryptoAlgorithmIdAesKw: { | |
| 331 platform::SymKey* platform_wrapping_key; | |
| 332 Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); | |
| 333 if (status.IsError()) | |
| 334 return status; | |
| 335 status = CheckAesKwInputSize(wrapped_key_data); | |
| 336 if (status.IsError()) | |
| 337 return status; | |
| 338 return platform::UnwrapSymKeyAesKw(wrapped_key_data, | |
| 339 platform_wrapping_key, | |
| 340 algorithm, | |
| 341 extractable, | |
| 342 usage_mask, | |
| 343 key); | |
| 344 } | |
| 345 default: | |
| 346 return Status::ErrorUnsupported(); | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 Status WrapKeyRaw(const blink::WebCryptoKey& key_to_wrap, | |
| 351 const blink::WebCryptoKey& wrapping_key, | |
| 352 const blink::WebCryptoAlgorithm& wrapping_algorithm, | |
| 353 std::vector<uint8>* buffer) { | |
| 354 // A raw key is always a symmetric key. | |
| 355 platform::SymKey* platform_key; | |
| 356 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); | |
| 357 if (status.IsError()) | |
| 358 return status; | |
| 359 | |
| 360 // TODO(padolph): Handle other wrapping algorithms | |
| 361 switch (wrapping_algorithm.id()) { | |
| 362 case blink::WebCryptoAlgorithmIdAesKw: { | |
| 363 platform::SymKey* platform_wrapping_key; | |
| 364 status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); | |
| 365 if (status.IsError()) | |
| 366 return status; | |
| 367 return platform::WrapSymKeyAesKw( | |
| 368 platform_key, platform_wrapping_key, buffer); | |
| 369 } | |
| 370 default: | |
| 371 return Status::ErrorUnsupported(); | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, | |
| 376 const blink::WebCryptoKey& key, | |
| 377 const CryptoData& data, | |
| 378 std::vector<uint8>* buffer) { | |
| 379 platform::SymKey* sym_key; | 316 platform::SymKey* sym_key; |
| 380 Status status = ToPlatformSymKey(key, &sym_key); | 317 Status status = ToPlatformSymKey(key, &sym_key); |
| 381 if (status.IsError()) | 318 if (status.IsError()) |
| 382 return status; | 319 return status; |
| 383 status = CheckAesKwInputSize(data); | 320 |
| 321 unsigned int min_length = mode == ENCRYPT ? 16 : 24; |
| 322 |
| 323 if (data.byte_length() < min_length) |
| 324 return Status::ErrorDataTooSmall(); |
| 325 if (data.byte_length() % 8) |
| 326 return Status::ErrorInvalidAesKwDataLength(); |
| 327 |
| 384 if (status.IsError()) | 328 if (status.IsError()) |
| 385 return status; | 329 return status; |
| 386 return platform::DecryptAesKw(sym_key, data, buffer); | 330 return platform::EncryptDecryptAesKw(mode, sym_key, data, buffer); |
| 387 } | 331 } |
| 388 | 332 |
| 389 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm, | 333 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm, |
| 390 const blink::WebCryptoKey& key, | 334 const blink::WebCryptoKey& key, |
| 391 const CryptoData& data, | 335 const CryptoData& data, |
| 392 std::vector<uint8>* buffer) { | 336 std::vector<uint8>* buffer) { |
| 393 if (algorithm.id() != key.algorithm().id()) | 337 if (algorithm.id() != key.algorithm().id()) |
| 394 return Status::ErrorUnexpected(); | 338 return Status::ErrorUnexpected(); |
| 395 switch (algorithm.id()) { | 339 switch (algorithm.id()) { |
| 396 case blink::WebCryptoAlgorithmIdAesCbc: | 340 case blink::WebCryptoAlgorithmIdAesCbc: |
| 397 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer); | 341 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer); |
| 398 case blink::WebCryptoAlgorithmIdAesGcm: | 342 case blink::WebCryptoAlgorithmIdAesGcm: |
| 399 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); | 343 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); |
| 400 case blink::WebCryptoAlgorithmIdRsaOaep: | 344 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 401 return DecryptRsaOaep(algorithm, key, data, buffer); | 345 return DecryptRsaOaep(algorithm, key, data, buffer); |
| 402 case blink::WebCryptoAlgorithmIdAesKw: | 346 case blink::WebCryptoAlgorithmIdAesKw: |
| 403 return DecryptAesKw(algorithm, key, data, buffer); | 347 return EncryptDecryptAesKw(DECRYPT, algorithm, key, data, buffer); |
| 404 default: | 348 default: |
| 405 return Status::ErrorUnsupported(); | 349 return Status::ErrorUnsupported(); |
| 406 } | 350 } |
| 407 } | 351 } |
| 408 | 352 |
| 409 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, | 353 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, |
| 410 const blink::WebCryptoKey& key, | 354 const blink::WebCryptoKey& key, |
| 411 const CryptoData& data, | 355 const CryptoData& data, |
| 412 std::vector<uint8>* buffer) { | 356 std::vector<uint8>* buffer) { |
| 413 if (algorithm.id() != key.algorithm().id()) | 357 if (algorithm.id() != key.algorithm().id()) |
| 414 return Status::ErrorUnexpected(); | 358 return Status::ErrorUnexpected(); |
| 415 switch (algorithm.id()) { | 359 switch (algorithm.id()) { |
| 416 case blink::WebCryptoAlgorithmIdAesCbc: | 360 case blink::WebCryptoAlgorithmIdAesCbc: |
| 417 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); | 361 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); |
| 418 case blink::WebCryptoAlgorithmIdAesGcm: | 362 case blink::WebCryptoAlgorithmIdAesGcm: |
| 419 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); | 363 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); |
| 364 case blink::WebCryptoAlgorithmIdAesKw: |
| 365 return EncryptDecryptAesKw(ENCRYPT, algorithm, key, data, buffer); |
| 420 case blink::WebCryptoAlgorithmIdRsaOaep: | 366 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 421 return EncryptRsaOaep(algorithm, key, data, buffer); | 367 return EncryptRsaOaep(algorithm, key, data, buffer); |
| 422 default: | 368 default: |
| 423 return Status::ErrorUnsupported(); | 369 return Status::ErrorUnsupported(); |
| 424 } | 370 } |
| 425 } | 371 } |
| 426 | 372 |
| 427 Status UnwrapKeyDecryptAndImport( | 373 Status UnwrapKeyDecryptAndImport( |
| 428 blink::WebCryptoKeyFormat format, | 374 blink::WebCryptoKeyFormat format, |
| 429 const CryptoData& wrapped_key_data, | 375 const CryptoData& wrapped_key_data, |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 Status WrapKey(blink::WebCryptoKeyFormat format, | 831 Status WrapKey(blink::WebCryptoKeyFormat format, |
| 886 const blink::WebCryptoKey& key_to_wrap, | 832 const blink::WebCryptoKey& key_to_wrap, |
| 887 const blink::WebCryptoKey& wrapping_key, | 833 const blink::WebCryptoKey& wrapping_key, |
| 888 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 834 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
| 889 std::vector<uint8>* buffer) { | 835 std::vector<uint8>* buffer) { |
| 890 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) | 836 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) |
| 891 return Status::ErrorUnexpected(); | 837 return Status::ErrorUnexpected(); |
| 892 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) | 838 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) |
| 893 return Status::ErrorUnexpected(); | 839 return Status::ErrorUnexpected(); |
| 894 | 840 |
| 895 if (format == blink::WebCryptoKeyFormatRaw && | |
| 896 wrapping_algorithm.id() == blink::WebCryptoAlgorithmIdAesKw) { | |
| 897 // AES-KW is a special case, due to NSS's implementation only | |
| 898 // supporting C_Wrap/C_Unwrap with AES-KW | |
| 899 return WrapKeyRaw(key_to_wrap, wrapping_key, wrapping_algorithm, buffer); | |
| 900 } | |
| 901 | |
| 902 return WrapKeyExportAndEncrypt( | 841 return WrapKeyExportAndEncrypt( |
| 903 format, key_to_wrap, wrapping_key, wrapping_algorithm, buffer); | 842 format, key_to_wrap, wrapping_key, wrapping_algorithm, buffer); |
| 904 } | 843 } |
| 905 | 844 |
| 906 Status UnwrapKey(blink::WebCryptoKeyFormat format, | 845 Status UnwrapKey(blink::WebCryptoKeyFormat format, |
| 907 const CryptoData& wrapped_key_data, | 846 const CryptoData& wrapped_key_data, |
| 908 const blink::WebCryptoKey& wrapping_key, | 847 const blink::WebCryptoKey& wrapping_key, |
| 909 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 848 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
| 910 const blink::WebCryptoAlgorithm& algorithm, | 849 const blink::WebCryptoAlgorithm& algorithm, |
| 911 bool extractable, | 850 bool extractable, |
| 912 blink::WebCryptoKeyUsageMask usage_mask, | 851 blink::WebCryptoKeyUsageMask usage_mask, |
| 913 blink::WebCryptoKey* key) { | 852 blink::WebCryptoKey* key) { |
| 914 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) | 853 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) |
| 915 return Status::ErrorUnexpected(); | 854 return Status::ErrorUnexpected(); |
| 916 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) | 855 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) |
| 917 return Status::ErrorUnexpected(); | 856 return Status::ErrorUnexpected(); |
| 918 | 857 |
| 919 // Fail-fast if the key usages don't make sense. This avoids decrypting the | 858 // Fail-fast if the key usages don't make sense. This avoids decrypting the |
| 920 // key only to then have import fail. It is "best effort" because when | 859 // key only to then have import fail. It is "best effort" because when |
| 921 // unwrapping JWK for asymmetric algorithms the key type isn't known yet. | 860 // unwrapping JWK for asymmetric algorithms the key type isn't known yet. |
| 922 Status status = | 861 Status status = |
| 923 BestEffortCheckKeyUsagesForImport(algorithm.id(), format, usage_mask); | 862 BestEffortCheckKeyUsagesForImport(algorithm.id(), format, usage_mask); |
| 924 if (status.IsError()) | 863 if (status.IsError()) |
| 925 return status; | 864 return status; |
| 926 | 865 |
| 927 if (format == blink::WebCryptoKeyFormatRaw && | |
| 928 wrapping_algorithm.id() == blink::WebCryptoAlgorithmIdAesKw) { | |
| 929 // AES-KW is a special case, due to NSS's implementation only | |
| 930 // supporting C_Wrap/C_Unwrap with AES-KW | |
| 931 return UnwrapKeyRaw(wrapped_key_data, | |
| 932 wrapping_key, | |
| 933 wrapping_algorithm, | |
| 934 algorithm, | |
| 935 extractable, | |
| 936 usage_mask, | |
| 937 key); | |
| 938 } | |
| 939 | |
| 940 return UnwrapKeyDecryptAndImport(format, | 866 return UnwrapKeyDecryptAndImport(format, |
| 941 wrapped_key_data, | 867 wrapped_key_data, |
| 942 wrapping_key, | 868 wrapping_key, |
| 943 wrapping_algorithm, | 869 wrapping_algorithm, |
| 944 algorithm, | 870 algorithm, |
| 945 extractable, | 871 extractable, |
| 946 usage_mask, | 872 usage_mask, |
| 947 key); | 873 key); |
| 948 } | 874 } |
| 949 | 875 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 if (!ContainsKeyUsages(GetValidKeyUsagesForKeyType(algorithm, key_type), | 938 if (!ContainsKeyUsages(GetValidKeyUsagesForKeyType(algorithm, key_type), |
| 1013 usages)) | 939 usages)) |
| 1014 return Status::ErrorCreateKeyBadUsages(); | 940 return Status::ErrorCreateKeyBadUsages(); |
| 1015 | 941 |
| 1016 return Status::Success(); | 942 return Status::Success(); |
| 1017 } | 943 } |
| 1018 | 944 |
| 1019 } // namespace webcrypto | 945 } // namespace webcrypto |
| 1020 | 946 |
| 1021 } // namespace content | 947 } // namespace content |
| OLD | NEW |