1*e7b1675dSTing-Kang Chang // Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang // http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ///////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang #include "tink/internal/aes_util.h"
17*e7b1675dSTing-Kang Chang
18*e7b1675dSTing-Kang Chang #include <cstdint>
19*e7b1675dSTing-Kang Chang #include <string>
20*e7b1675dSTing-Kang Chang #include <vector>
21*e7b1675dSTing-Kang Chang
22*e7b1675dSTing-Kang Chang #include "absl/status/status.h"
23*e7b1675dSTing-Kang Chang #include "absl/strings/str_cat.h"
24*e7b1675dSTing-Kang Chang #include "absl/strings/string_view.h"
25*e7b1675dSTing-Kang Chang #include "absl/types/span.h"
26*e7b1675dSTing-Kang Chang #include "openssl/aes.h"
27*e7b1675dSTing-Kang Chang #include "openssl/evp.h"
28*e7b1675dSTing-Kang Chang #include "tink/util/statusor.h"
29*e7b1675dSTing-Kang Chang #ifndef OPENSSL_IS_BORINGSSL
30*e7b1675dSTing-Kang Chang // This is needed to use block128_f, which is necessary when OpenSSL is used.
31*e7b1675dSTing-Kang Chang #include "openssl/modes.h"
32*e7b1675dSTing-Kang Chang #endif
33*e7b1675dSTing-Kang Chang #include "tink/internal/util.h"
34*e7b1675dSTing-Kang Chang #include "tink/util/secret_data.h"
35*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
36*e7b1675dSTing-Kang Chang
37*e7b1675dSTing-Kang Chang namespace crypto {
38*e7b1675dSTing-Kang Chang namespace tink {
39*e7b1675dSTing-Kang Chang namespace internal {
40*e7b1675dSTing-Kang Chang
AesCtr128Crypt(absl::string_view data,uint8_t iv[AesBlockSize ()],const AES_KEY * key,absl::Span<char> out)41*e7b1675dSTing-Kang Chang util::Status AesCtr128Crypt(absl::string_view data, uint8_t iv[AesBlockSize()],
42*e7b1675dSTing-Kang Chang const AES_KEY* key, absl::Span<char> out) {
43*e7b1675dSTing-Kang Chang if (out.size() < data.size()) {
44*e7b1675dSTing-Kang Chang return util::Status(
45*e7b1675dSTing-Kang Chang absl::StatusCode::kInvalidArgument,
46*e7b1675dSTing-Kang Chang absl::StrCat("Invalid size for output buffer; expected at least ",
47*e7b1675dSTing-Kang Chang data.size(), " got ", out.size()));
48*e7b1675dSTing-Kang Chang }
49*e7b1675dSTing-Kang Chang
50*e7b1675dSTing-Kang Chang // Only full overlap or no overlap is allowed.
51*e7b1675dSTing-Kang Chang if (!BuffersAreIdentical(data, absl::string_view(out.data(), out.size())) &&
52*e7b1675dSTing-Kang Chang BuffersOverlap(data, absl::string_view(out.data(), out.size()))) {
53*e7b1675dSTing-Kang Chang return util::Status(absl::StatusCode::kInvalidArgument,
54*e7b1675dSTing-Kang Chang "Buffers must not partially overlap");
55*e7b1675dSTing-Kang Chang }
56*e7b1675dSTing-Kang Chang
57*e7b1675dSTing-Kang Chang unsigned int num = 0;
58*e7b1675dSTing-Kang Chang std::vector<uint8_t> ecount_buf(AesBlockSize(), 0);
59*e7b1675dSTing-Kang Chang // OpenSSL >= v1.1.0 public APIs no longer exposes an AES_ctr128_encrypt
60*e7b1675dSTing-Kang Chang // function; as an alternative we use CRYPTO_ctr128_encrypt when OpenSSL is
61*e7b1675dSTing-Kang Chang // used as a backend. The latter is not part of the public API of BoringSSL,
62*e7b1675dSTing-Kang Chang // so we must selectively compile using either of them.
63*e7b1675dSTing-Kang Chang #ifdef OPENSSL_IS_BORINGSSL
64*e7b1675dSTing-Kang Chang AES_ctr128_encrypt(reinterpret_cast<const uint8_t*>(data.data()),
65*e7b1675dSTing-Kang Chang reinterpret_cast<uint8_t*>(out.data()), data.size(), key,
66*e7b1675dSTing-Kang Chang iv, ecount_buf.data(), &num);
67*e7b1675dSTing-Kang Chang #else
68*e7b1675dSTing-Kang Chang CRYPTO_ctr128_encrypt(reinterpret_cast<const uint8_t*>(data.data()),
69*e7b1675dSTing-Kang Chang reinterpret_cast<uint8_t*>(out.data()), data.size(),
70*e7b1675dSTing-Kang Chang key, iv, ecount_buf.data(), &num,
71*e7b1675dSTing-Kang Chang reinterpret_cast<block128_f>(AES_encrypt));
72*e7b1675dSTing-Kang Chang #endif
73*e7b1675dSTing-Kang Chang return util::OkStatus();
74*e7b1675dSTing-Kang Chang }
75*e7b1675dSTing-Kang Chang
GetAesCtrCipherForKeySize(uint32_t key_size_in_bytes)76*e7b1675dSTing-Kang Chang util::StatusOr<const EVP_CIPHER*> GetAesCtrCipherForKeySize(
77*e7b1675dSTing-Kang Chang uint32_t key_size_in_bytes) {
78*e7b1675dSTing-Kang Chang switch (key_size_in_bytes) {
79*e7b1675dSTing-Kang Chang case 16:
80*e7b1675dSTing-Kang Chang return EVP_aes_128_ctr();
81*e7b1675dSTing-Kang Chang case 32:
82*e7b1675dSTing-Kang Chang return EVP_aes_256_ctr();
83*e7b1675dSTing-Kang Chang default:
84*e7b1675dSTing-Kang Chang return util::Status(absl::StatusCode::kInvalidArgument,
85*e7b1675dSTing-Kang Chang absl::StrCat("Invalid key size ", key_size_in_bytes));
86*e7b1675dSTing-Kang Chang }
87*e7b1675dSTing-Kang Chang }
88*e7b1675dSTing-Kang Chang
GetAesCbcCipherForKeySize(uint32_t key_size_in_bytes)89*e7b1675dSTing-Kang Chang util::StatusOr<const EVP_CIPHER*> GetAesCbcCipherForKeySize(
90*e7b1675dSTing-Kang Chang uint32_t key_size_in_bytes) {
91*e7b1675dSTing-Kang Chang switch (key_size_in_bytes) {
92*e7b1675dSTing-Kang Chang case 16:
93*e7b1675dSTing-Kang Chang return EVP_aes_128_cbc();
94*e7b1675dSTing-Kang Chang case 32:
95*e7b1675dSTing-Kang Chang return EVP_aes_256_cbc();
96*e7b1675dSTing-Kang Chang }
97*e7b1675dSTing-Kang Chang return util::Status(absl::StatusCode::kInvalidArgument,
98*e7b1675dSTing-Kang Chang absl::StrCat("Invalid key size ", key_size_in_bytes));
99*e7b1675dSTing-Kang Chang }
100*e7b1675dSTing-Kang Chang
101*e7b1675dSTing-Kang Chang } // namespace internal
102*e7b1675dSTing-Kang Chang } // namespace tink
103*e7b1675dSTing-Kang Chang } // namespace crypto
104