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