xref: /aosp_15_r20/external/tink/cc/subtle/aes_siv_boringssl.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #ifndef TINK_SUBTLE_AES_SIV_BORINGSSL_H_
18 #define TINK_SUBTLE_AES_SIV_BORINGSSL_H_
19 
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 #include "absl/strings/string_view.h"
25 #include "absl/types/span.h"
26 #include "openssl/aes.h"
27 #include "tink/deterministic_aead.h"
28 #include "tink/internal/aes_util.h"
29 #include "tink/internal/fips_utils.h"
30 #include "tink/util/secret_data.h"
31 #include "tink/util/status.h"
32 #include "tink/util/statusor.h"
33 
34 namespace crypto {
35 namespace tink {
36 namespace subtle {
37 
38 // AesSivBoringSsl is an implemenatation of AES-SIV-CMAC as defined in
39 // https://tools.ietf.org/html/rfc5297 .
40 // AesSivBoringSsl implements a deterministic encryption with associated
41 // data (i.e. the DeterministicAead interface). Hence the implementation
42 // below is restricted to one AD component.
43 //
44 // Thread safety: This class is thread safe and thus can be used
45 // concurrently.
46 //
47 // Security:
48 // =========
49 // Chatterjee, Menezes and Sarkar analyze AES-SIV in Section 5.1 of
50 // https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf
51 // Their analysis shows that AES-SIV is susceptible to an attack in
52 // a multi-user setting. Concretely, if an attacker knows the encryption
53 // of a message m encrypted and authenticated with k different keys,
54 // then it is possible  to find one of the MAC keys in time 2^b / k
55 // where b is the size of the MAC key. A consequence of this attack
56 // is that 128-bit MAC keys give unsufficient security.
57 // Since 192-bit AES keys are not supported by tink for voodoo reasons
58 // and RFC 5297 only supports same size encryption and MAC keys this
59 // implies that keys must be 64 bytes (2*256 bits) long.
60 class AesSivBoringSsl : public DeterministicAead {
61  public:
62   static crypto::tink::util::StatusOr<std::unique_ptr<DeterministicAead>> New(
63       const util::SecretData& key);
64 
65   crypto::tink::util::StatusOr<std::string> EncryptDeterministically(
66       absl::string_view plaintext,
67       absl::string_view associated_data) const override;
68 
69   crypto::tink::util::StatusOr<std::string> DecryptDeterministically(
70       absl::string_view ciphertext,
71       absl::string_view associated_data) const override;
72 
IsValidKeySizeInBytes(size_t size)73   static bool IsValidKeySizeInBytes(size_t size) { return size == 64; }
74 
75   static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus =
76       crypto::tink::internal::FipsCompatibility::kNotFips;
77 
78  private:
79   static constexpr size_t kBlockSize = internal::AesBlockSize();
80 
AesSivBoringSsl(util::SecretUniquePtr<AES_KEY> k1,util::SecretUniquePtr<AES_KEY> k2)81   AesSivBoringSsl(util::SecretUniquePtr<AES_KEY> k1,
82                   util::SecretUniquePtr<AES_KEY> k2)
83       : k1_(std::move(k1)),
84         k2_(std::move(k2)),
85         cmac_k1_(ComputeCmacK1()),
86         cmac_k2_(ComputeCmacK2()) {}
87 
88   // Precomputes cmac_k1
89   util::SecretData ComputeCmacK1() const;
90   // Precomputes cmac_k2
91   util::SecretData ComputeCmacK2() const;
92 
93   // Encrypts a single block using k2_.
94   // This is used for CMACs.
95   void EncryptBlock(const uint8_t in[kBlockSize],
96                     uint8_t out[kBlockSize]) const;
97 
98   // Computes a CMAC of some data.
99   void Cmac(absl::Span<const uint8_t> data, uint8_t mac[kBlockSize]) const;
100 
101   // Computes CMAC(XorEnd(data, last)), where XorEnd
102   // xors the bytes in last to the last bytes in data.
103   // The size of the data must be at least 16 bytes.
104   void CmacLong(absl::Span<const uint8_t> data, const uint8_t last[kBlockSize],
105                 uint8_t mac[kBlockSize]) const;
106 
107   // Multiplying an element in GF(2^128) by its generator.
108   // This functions is incorrectly named "doubling" in section 2.3 of RFC 5297.
109   static void MultiplyByX(uint8_t block[kBlockSize]);
110 
111   // Xors a block
112   // res = x ^ y
113   static void XorBlock(const uint8_t x[kBlockSize], const uint8_t y[kBlockSize],
114                        uint8_t res[kBlockSize]);
115 
116   void S2v(absl::Span<const uint8_t> aad, absl::Span<const uint8_t> msg,
117            uint8_t siv[kBlockSize]) const;
118 
119   // Encrypts (or decrypts) `in` using an SIV `siv` and key `key`, and writes
120   // the result to `out`.
121   util::Status AesCtrCrypt(absl::string_view in, const uint8_t siv[kBlockSize],
122                            const AES_KEY* key, absl::Span<char> out) const;
123 
124   const util::SecretUniquePtr<AES_KEY> k1_;
125   const util::SecretUniquePtr<AES_KEY> k2_;
126   const util::SecretData cmac_k1_;
127   const util::SecretData cmac_k2_;
128 };
129 
130 }  // namespace subtle
131 }  // namespace tink
132 }  // namespace crypto
133 
134 #endif  // TINK_SUBTLE_AES_SIV_BORINGSSL_H_
135