| 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/aes.h> | 5 #include <openssl/aead.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/location.h" | 11 #include "base/logging.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" |
| 14 #include "components/webcrypto/algorithms/aes.h" | 15 #include "components/webcrypto/algorithms/aes.h" |
| 16 #include "components/webcrypto/algorithms/util.h" |
| 15 #include "components/webcrypto/blink_key_handle.h" | 17 #include "components/webcrypto/blink_key_handle.h" |
| 16 #include "components/webcrypto/crypto_data.h" | 18 #include "components/webcrypto/crypto_data.h" |
| 17 #include "components/webcrypto/status.h" | 19 #include "components/webcrypto/status.h" |
| 18 #include "crypto/openssl_util.h" | 20 #include "crypto/openssl_util.h" |
| 19 | 21 |
| 20 namespace webcrypto { | 22 namespace webcrypto { |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 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 |
| 24 class AesKwImplementation : public AesAlgorithm { | 61 class AesKwImplementation : public AesAlgorithm { |
| 25 public: | 62 public: |
| 26 AesKwImplementation() | 63 AesKwImplementation() |
| 27 : AesAlgorithm( | 64 : AesAlgorithm( |
| 28 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, | 65 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, |
| 29 "KW") {} | 66 "KW") {} |
| 30 | 67 |
| 31 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 68 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 32 const blink::WebCryptoKey& key, | 69 const blink::WebCryptoKey& key, |
| 33 const CryptoData& data, | 70 const CryptoData& data, |
| 34 std::vector<uint8_t>* buffer) const override { | 71 std::vector<uint8_t>* buffer) const override { |
| 35 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 72 return AesKwEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer); |
| 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(); | |
| 67 } | 73 } |
| 68 | 74 |
| 69 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | 75 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 70 const blink::WebCryptoKey& key, | 76 const blink::WebCryptoKey& key, |
| 71 const CryptoData& data, | 77 const CryptoData& data, |
| 72 std::vector<uint8_t>* buffer) const override { | 78 std::vector<uint8_t>* buffer) const override { |
| 73 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 79 return AesKwEncryptDecrypt(DECRYPT, algorithm, key, data, buffer); |
| 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(); | |
| 101 } | 80 } |
| 102 }; | 81 }; |
| 103 | 82 |
| 104 } // namespace | 83 } // namespace |
| 105 | 84 |
| 106 std::unique_ptr<AlgorithmImplementation> CreateAesKwImplementation() { | 85 std::unique_ptr<AlgorithmImplementation> CreateAesKwImplementation() { |
| 107 return base::WrapUnique(new AesKwImplementation); | 86 return base::WrapUnique(new AesKwImplementation); |
| 108 } | 87 } |
| 109 | 88 |
| 110 } // namespace webcrypto | 89 } // namespace webcrypto |
| OLD | NEW |