| 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 <openssl/aead.h> | 5 #include <openssl/aes.h> |
| 6 #include <stddef.h> | 6 #include <stddef.h> |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/location.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/numerics/safe_math.h" | 13 #include "base/numerics/safe_math.h" |
| 14 #include "base/stl_util.h" | |
| 15 #include "components/webcrypto/algorithms/aes.h" | 14 #include "components/webcrypto/algorithms/aes.h" |
| 16 #include "components/webcrypto/algorithms/util.h" | |
| 17 #include "components/webcrypto/blink_key_handle.h" | 15 #include "components/webcrypto/blink_key_handle.h" |
| 18 #include "components/webcrypto/crypto_data.h" | 16 #include "components/webcrypto/crypto_data.h" |
| 19 #include "components/webcrypto/status.h" | 17 #include "components/webcrypto/status.h" |
| 20 #include "crypto/openssl_util.h" | 18 #include "crypto/openssl_util.h" |
| 21 | 19 |
| 22 namespace webcrypto { | 20 namespace webcrypto { |
| 23 | 21 |
| 24 namespace { | 22 namespace { |
| 25 | 23 |
| 26 const EVP_AEAD* GetAesKwAlgorithmFromKeySize(size_t key_size_bytes) { | |
| 27 switch (key_size_bytes) { | |
| 28 case 16: | |
| 29 return EVP_aead_aes_128_key_wrap(); | |
| 30 case 32: | |
| 31 return EVP_aead_aes_256_key_wrap(); | |
| 32 default: | |
| 33 return NULL; | |
| 34 } | |
| 35 } | |
| 36 | |
| 37 Status AesKwEncryptDecrypt(EncryptOrDecrypt mode, | |
| 38 const blink::WebCryptoAlgorithm& algorithm, | |
| 39 const blink::WebCryptoKey& key, | |
| 40 const CryptoData& data, | |
| 41 std::vector<uint8_t>* buffer) { | |
| 42 // These length checks are done in order to give a more specific error. These | |
| 43 // are not required for correctness. | |
| 44 if ((mode == ENCRYPT && data.byte_length() < 16) || | |
| 45 (mode == DECRYPT && data.byte_length() < 24)) { | |
| 46 return Status::ErrorDataTooSmall(); | |
| 47 } | |
| 48 if (data.byte_length() % 8) | |
| 49 return Status::ErrorInvalidAesKwDataLength(); | |
| 50 | |
| 51 const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); | |
| 52 | |
| 53 return AeadEncryptDecrypt(mode, raw_key, data, | |
| 54 8, // tag_length_bytes | |
| 55 CryptoData(), // iv | |
| 56 CryptoData(), // additional_data | |
| 57 GetAesKwAlgorithmFromKeySize(raw_key.size()), | |
| 58 buffer); | |
| 59 } | |
| 60 | |
| 61 class AesKwImplementation : public AesAlgorithm { | 24 class AesKwImplementation : public AesAlgorithm { |
| 62 public: | 25 public: |
| 63 AesKwImplementation() | 26 AesKwImplementation() |
| 64 : AesAlgorithm( | 27 : AesAlgorithm( |
| 65 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, | 28 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, |
| 66 "KW") {} | 29 "KW") {} |
| 67 | 30 |
| 68 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 31 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 69 const blink::WebCryptoKey& key, | 32 const blink::WebCryptoKey& key, |
| 70 const CryptoData& data, | 33 const CryptoData& data, |
| 71 std::vector<uint8_t>* buffer) const override { | 34 std::vector<uint8_t>* buffer) const override { |
| 72 return AesKwEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer); | 35 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 36 |
| 37 // These length checks are done in order to give a more specific |
| 38 // error. These are not required for correctness. |
| 39 if (data.byte_length() < 16) |
| 40 return Status::ErrorDataTooSmall(); |
| 41 if (data.byte_length() % 8) |
| 42 return Status::ErrorInvalidAesKwDataLength(); |
| 43 |
| 44 // Key import validates key sizes, so the bits computation will not |
| 45 // overflow. |
| 46 const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); |
| 47 AES_KEY aes_key; |
| 48 if (AES_set_encrypt_key(raw_key.data(), |
| 49 static_cast<unsigned>(raw_key.size() * 8), |
| 50 &aes_key) < 0) { |
| 51 return Status::OperationError(); |
| 52 } |
| 53 |
| 54 // Key wrap's overhead is 8 bytes. |
| 55 base::CheckedNumeric<size_t> length(data.byte_length()); |
| 56 length += 8; |
| 57 if (!length.IsValid()) |
| 58 return Status::ErrorDataTooLarge(); |
| 59 |
| 60 buffer->resize(length.ValueOrDie()); |
| 61 if (AES_wrap_key(&aes_key, nullptr /* default IV */, buffer->data(), |
| 62 data.bytes(), data.byte_length()) < 0) { |
| 63 return Status::OperationError(); |
| 64 } |
| 65 |
| 66 return Status::Success(); |
| 73 } | 67 } |
| 74 | 68 |
| 75 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | 69 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 76 const blink::WebCryptoKey& key, | 70 const blink::WebCryptoKey& key, |
| 77 const CryptoData& data, | 71 const CryptoData& data, |
| 78 std::vector<uint8_t>* buffer) const override { | 72 std::vector<uint8_t>* buffer) const override { |
| 79 return AesKwEncryptDecrypt(DECRYPT, algorithm, key, data, buffer); | 73 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 74 |
| 75 // These length checks are done in order to give a more specific |
| 76 // error. These are not required for correctness. |
| 77 if (data.byte_length() < 24) |
| 78 return Status::ErrorDataTooSmall(); |
| 79 if (data.byte_length() % 8) |
| 80 return Status::ErrorInvalidAesKwDataLength(); |
| 81 |
| 82 // Key import validates key sizes, so the bits computation will not |
| 83 // overflow. |
| 84 const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); |
| 85 AES_KEY aes_key; |
| 86 if (AES_set_decrypt_key(raw_key.data(), |
| 87 static_cast<unsigned>(raw_key.size() * 8), |
| 88 &aes_key) < 0) { |
| 89 return Status::OperationError(); |
| 90 } |
| 91 |
| 92 // Key wrap's overhead is 8 bytes. |
| 93 buffer->resize(data.byte_length() - 8); |
| 94 |
| 95 if (AES_unwrap_key(&aes_key, nullptr /* default IV */, buffer->data(), |
| 96 data.bytes(), data.byte_length()) < 0) { |
| 97 return Status::OperationError(); |
| 98 } |
| 99 |
| 100 return Status::Success(); |
| 80 } | 101 } |
| 81 }; | 102 }; |
| 82 | 103 |
| 83 } // namespace | 104 } // namespace |
| 84 | 105 |
| 85 std::unique_ptr<AlgorithmImplementation> CreateAesKwImplementation() { | 106 std::unique_ptr<AlgorithmImplementation> CreateAesKwImplementation() { |
| 86 return base::WrapUnique(new AesKwImplementation); | 107 return base::WrapUnique(new AesKwImplementation); |
| 87 } | 108 } |
| 88 | 109 |
| 89 } // namespace webcrypto | 110 } // namespace webcrypto |
| OLD | NEW |