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 |