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
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <memory>
9 #include <vector>
10
11 #include "base/stl_util.h"
12 #include "components/webcrypto/algorithms/aes.h"
13 #include "components/webcrypto/algorithms/util.h"
14 #include "components/webcrypto/blink_key_handle.h"
15 #include "components/webcrypto/crypto_data.h"
16 #include "components/webcrypto/status.h"
17 #include "crypto/openssl_util.h"
18 #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
19 #include "third_party/boringssl/src/include/openssl/aead.h"
20
21 namespace webcrypto {
22
23 namespace {
24
GetAesGcmAlgorithmFromKeySize(size_t key_size_bytes)25 const EVP_AEAD* GetAesGcmAlgorithmFromKeySize(size_t key_size_bytes) {
26 switch (key_size_bytes) {
27 case 16:
28 return EVP_aead_aes_128_gcm();
29 case 32:
30 return EVP_aead_aes_256_gcm();
31 default:
32 return nullptr;
33 }
34 }
35
AesGcmEncryptDecrypt(EncryptOrDecrypt mode,const blink::WebCryptoAlgorithm & algorithm,const blink::WebCryptoKey & key,const CryptoData & data,std::vector<uint8_t> * buffer)36 Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
37 const blink::WebCryptoAlgorithm& algorithm,
38 const blink::WebCryptoKey& key,
39 const CryptoData& data,
40 std::vector<uint8_t>* buffer) {
41 const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key);
42 const blink::WebCryptoAesGcmParams* params = algorithm.AesGcmParams();
43
44 // The WebCrypto spec defines the default value for the tag length, as well as
45 // the allowed values for tag length.
46 unsigned int tag_length_bits = 128;
47 if (params->HasTagLengthBits()) {
48 tag_length_bits = params->OptionalTagLengthBits();
49 if (tag_length_bits != 32 && tag_length_bits != 64 &&
50 tag_length_bits != 96 && tag_length_bits != 104 &&
51 tag_length_bits != 112 && tag_length_bits != 120 &&
52 tag_length_bits != 128) {
53 return Status::ErrorInvalidAesGcmTagLength();
54 }
55 }
56
57 return AeadEncryptDecrypt(
58 mode, raw_key, data, tag_length_bits / 8, CryptoData(params->Iv()),
59 CryptoData(params->OptionalAdditionalData()),
60 GetAesGcmAlgorithmFromKeySize(raw_key.size()), buffer);
61 }
62
63 class AesGcmImplementation : public AesAlgorithm {
64 public:
AesGcmImplementation()65 AesGcmImplementation() : AesAlgorithm("GCM") {}
66
Encrypt(const blink::WebCryptoAlgorithm & algorithm,const blink::WebCryptoKey & key,const CryptoData & data,std::vector<uint8_t> * buffer) const67 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
68 const blink::WebCryptoKey& key,
69 const CryptoData& data,
70 std::vector<uint8_t>* buffer) const override {
71 return AesGcmEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
72 }
73
Decrypt(const blink::WebCryptoAlgorithm & algorithm,const blink::WebCryptoKey & key,const CryptoData & data,std::vector<uint8_t> * buffer) const74 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
75 const blink::WebCryptoKey& key,
76 const CryptoData& data,
77 std::vector<uint8_t>* buffer) const override {
78 return AesGcmEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
79 }
80 };
81
82 } // namespace
83
CreateAesGcmImplementation()84 std::unique_ptr<AlgorithmImplementation> CreateAesGcmImplementation() {
85 return std::make_unique<AesGcmImplementation>();
86 }
87
88 } // namespace webcrypto
89