xref: /aosp_15_r20/system/keymaster/km_openssl/block_cipher_operation.cpp (revision 789431f29546679ab5188a97751fb38e3018d44d)
1*789431f2SAndroid Build Coastguard Worker /*
2*789431f2SAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
3*789431f2SAndroid Build Coastguard Worker  *
4*789431f2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*789431f2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*789431f2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*789431f2SAndroid Build Coastguard Worker  *
8*789431f2SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*789431f2SAndroid Build Coastguard Worker  *
10*789431f2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*789431f2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*789431f2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*789431f2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*789431f2SAndroid Build Coastguard Worker  * limitations under the License.
15*789431f2SAndroid Build Coastguard Worker  */
16*789431f2SAndroid Build Coastguard Worker 
17*789431f2SAndroid Build Coastguard Worker #include "block_cipher_operation.h"
18*789431f2SAndroid Build Coastguard Worker 
19*789431f2SAndroid Build Coastguard Worker #include <utility>
20*789431f2SAndroid Build Coastguard Worker 
21*789431f2SAndroid Build Coastguard Worker #include <stdio.h>
22*789431f2SAndroid Build Coastguard Worker 
23*789431f2SAndroid Build Coastguard Worker #include <keymaster/UniquePtr.h>
24*789431f2SAndroid Build Coastguard Worker 
25*789431f2SAndroid Build Coastguard Worker #include <openssl/aes.h>
26*789431f2SAndroid Build Coastguard Worker #include <openssl/err.h>
27*789431f2SAndroid Build Coastguard Worker #include <openssl/rand.h>
28*789431f2SAndroid Build Coastguard Worker 
29*789431f2SAndroid Build Coastguard Worker #include <keymaster/logger.h>
30*789431f2SAndroid Build Coastguard Worker 
31*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/aes_key.h>
32*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/openssl_err.h>
33*789431f2SAndroid Build Coastguard Worker #include <keymaster/km_openssl/openssl_utils.h>
34*789431f2SAndroid Build Coastguard Worker 
35*789431f2SAndroid Build Coastguard Worker namespace keymaster {
36*789431f2SAndroid Build Coastguard Worker 
37*789431f2SAndroid Build Coastguard Worker static const size_t GCM_NONCE_SIZE = 12;
38*789431f2SAndroid Build Coastguard Worker 
allows_padding(keymaster_block_mode_t block_mode)39*789431f2SAndroid Build Coastguard Worker inline bool allows_padding(keymaster_block_mode_t block_mode) {
40*789431f2SAndroid Build Coastguard Worker     switch (block_mode) {
41*789431f2SAndroid Build Coastguard Worker     case KM_MODE_CTR:
42*789431f2SAndroid Build Coastguard Worker     case KM_MODE_GCM:
43*789431f2SAndroid Build Coastguard Worker         return false;
44*789431f2SAndroid Build Coastguard Worker     case KM_MODE_ECB:
45*789431f2SAndroid Build Coastguard Worker     case KM_MODE_CBC:
46*789431f2SAndroid Build Coastguard Worker         return true;
47*789431f2SAndroid Build Coastguard Worker     }
48*789431f2SAndroid Build Coastguard Worker     assert(false /* Can't get here */);
49*789431f2SAndroid Build Coastguard Worker     return false;
50*789431f2SAndroid Build Coastguard Worker }
51*789431f2SAndroid Build Coastguard Worker 
GetAndValidateGcmTagLength(const AuthorizationSet & begin_params,const AuthProxy & key_params,size_t * tag_length)52*789431f2SAndroid Build Coastguard Worker static keymaster_error_t GetAndValidateGcmTagLength(const AuthorizationSet& begin_params,
53*789431f2SAndroid Build Coastguard Worker                                                     const AuthProxy& key_params,
54*789431f2SAndroid Build Coastguard Worker                                                     size_t* tag_length) {
55*789431f2SAndroid Build Coastguard Worker     uint32_t tag_length_bits;
56*789431f2SAndroid Build Coastguard Worker     if (!begin_params.GetTagValue(TAG_MAC_LENGTH, &tag_length_bits)) {
57*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_MISSING_MAC_LENGTH;
58*789431f2SAndroid Build Coastguard Worker     }
59*789431f2SAndroid Build Coastguard Worker 
60*789431f2SAndroid Build Coastguard Worker     uint32_t min_tag_length_bits;
61*789431f2SAndroid Build Coastguard Worker     if (!key_params.GetTagValue(TAG_MIN_MAC_LENGTH, &min_tag_length_bits)) {
62*789431f2SAndroid Build Coastguard Worker         LOG_E("AES GCM key must have KM_TAG_MIN_MAC_LENGTH");
63*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_KEY_BLOB;
64*789431f2SAndroid Build Coastguard Worker     }
65*789431f2SAndroid Build Coastguard Worker 
66*789431f2SAndroid Build Coastguard Worker     if (tag_length_bits % 8 != 0 || tag_length_bits > kMaxGcmTagLength ||
67*789431f2SAndroid Build Coastguard Worker         tag_length_bits < kMinGcmTagLength) {
68*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_MAC_LENGTH;
69*789431f2SAndroid Build Coastguard Worker     }
70*789431f2SAndroid Build Coastguard Worker 
71*789431f2SAndroid Build Coastguard Worker     if (tag_length_bits < min_tag_length_bits) {
72*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_MAC_LENGTH;
73*789431f2SAndroid Build Coastguard Worker     }
74*789431f2SAndroid Build Coastguard Worker 
75*789431f2SAndroid Build Coastguard Worker     *tag_length = tag_length_bits / 8;
76*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
77*789431f2SAndroid Build Coastguard Worker }
78*789431f2SAndroid Build Coastguard Worker 
CreateOperation(Key && key,const AuthorizationSet & begin_params,keymaster_error_t * error)79*789431f2SAndroid Build Coastguard Worker OperationPtr BlockCipherOperationFactory::CreateOperation(Key&& key,
80*789431f2SAndroid Build Coastguard Worker                                                           const AuthorizationSet& begin_params,
81*789431f2SAndroid Build Coastguard Worker                                                           keymaster_error_t* error) {
82*789431f2SAndroid Build Coastguard Worker     *error = KM_ERROR_OK;
83*789431f2SAndroid Build Coastguard Worker     keymaster_block_mode_t block_mode;
84*789431f2SAndroid Build Coastguard Worker     if (!begin_params.GetTagValue(TAG_BLOCK_MODE, &block_mode)) {
85*789431f2SAndroid Build Coastguard Worker         LOG_E("%zu block modes specified in begin params",
86*789431f2SAndroid Build Coastguard Worker               begin_params.GetTagCount(TAG_BLOCK_MODE));
87*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
88*789431f2SAndroid Build Coastguard Worker         return nullptr;
89*789431f2SAndroid Build Coastguard Worker     } else if (!supported(block_mode)) {
90*789431f2SAndroid Build Coastguard Worker         LOG_E("Block mode %d not supported", block_mode);
91*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_UNSUPPORTED_BLOCK_MODE;
92*789431f2SAndroid Build Coastguard Worker         return nullptr;
93*789431f2SAndroid Build Coastguard Worker     } else if (!key.authorizations().Contains(TAG_BLOCK_MODE, block_mode)) {
94*789431f2SAndroid Build Coastguard Worker         LOG_E("Block mode %d was specified, but not authorized by key", block_mode);
95*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_INCOMPATIBLE_BLOCK_MODE;
96*789431f2SAndroid Build Coastguard Worker         return nullptr;
97*789431f2SAndroid Build Coastguard Worker     }
98*789431f2SAndroid Build Coastguard Worker 
99*789431f2SAndroid Build Coastguard Worker     size_t tag_length = 0;
100*789431f2SAndroid Build Coastguard Worker     if (block_mode == KM_MODE_GCM) {
101*789431f2SAndroid Build Coastguard Worker         *error = GetAndValidateGcmTagLength(begin_params, key.authorizations(), &tag_length);
102*789431f2SAndroid Build Coastguard Worker         if (*error != KM_ERROR_OK) {
103*789431f2SAndroid Build Coastguard Worker             return nullptr;
104*789431f2SAndroid Build Coastguard Worker         }
105*789431f2SAndroid Build Coastguard Worker     }
106*789431f2SAndroid Build Coastguard Worker 
107*789431f2SAndroid Build Coastguard Worker     keymaster_padding_t padding;
108*789431f2SAndroid Build Coastguard Worker     if (!GetAndValidatePadding(begin_params, key, &padding, error)) {
109*789431f2SAndroid Build Coastguard Worker         return nullptr;
110*789431f2SAndroid Build Coastguard Worker     }
111*789431f2SAndroid Build Coastguard Worker     if (!allows_padding(block_mode) && padding != KM_PAD_NONE) {
112*789431f2SAndroid Build Coastguard Worker         LOG_E("Mode does not support padding");
113*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
114*789431f2SAndroid Build Coastguard Worker         return nullptr;
115*789431f2SAndroid Build Coastguard Worker     }
116*789431f2SAndroid Build Coastguard Worker 
117*789431f2SAndroid Build Coastguard Worker     bool caller_nonce = key.authorizations().GetTagValue(TAG_CALLER_NONCE);
118*789431f2SAndroid Build Coastguard Worker 
119*789431f2SAndroid Build Coastguard Worker     OperationPtr op;
120*789431f2SAndroid Build Coastguard Worker     switch (purpose_) {
121*789431f2SAndroid Build Coastguard Worker     case KM_PURPOSE_ENCRYPT:
122*789431f2SAndroid Build Coastguard Worker         op.reset(new (std::nothrow) BlockCipherEvpEncryptOperation(  //
123*789431f2SAndroid Build Coastguard Worker             block_mode, padding, caller_nonce, tag_length, std::move(key),
124*789431f2SAndroid Build Coastguard Worker             GetCipherDescription()));
125*789431f2SAndroid Build Coastguard Worker         break;
126*789431f2SAndroid Build Coastguard Worker     case KM_PURPOSE_DECRYPT:
127*789431f2SAndroid Build Coastguard Worker         op.reset(new (std::nothrow) BlockCipherEvpDecryptOperation(
128*789431f2SAndroid Build Coastguard Worker             block_mode, padding, tag_length, std::move(key), GetCipherDescription()));
129*789431f2SAndroid Build Coastguard Worker         break;
130*789431f2SAndroid Build Coastguard Worker     default:
131*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_UNSUPPORTED_PURPOSE;
132*789431f2SAndroid Build Coastguard Worker         return nullptr;
133*789431f2SAndroid Build Coastguard Worker     }
134*789431f2SAndroid Build Coastguard Worker 
135*789431f2SAndroid Build Coastguard Worker     if (!op) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
136*789431f2SAndroid Build Coastguard Worker     return op;
137*789431f2SAndroid Build Coastguard Worker }
138*789431f2SAndroid Build Coastguard Worker 
139*789431f2SAndroid Build Coastguard Worker static const keymaster_padding_t supported_padding_modes[] = {KM_PAD_NONE, KM_PAD_PKCS7};
140*789431f2SAndroid Build Coastguard Worker const keymaster_padding_t*
SupportedPaddingModes(size_t * padding_mode_count) const141*789431f2SAndroid Build Coastguard Worker BlockCipherOperationFactory::SupportedPaddingModes(size_t* padding_mode_count) const {
142*789431f2SAndroid Build Coastguard Worker     *padding_mode_count = array_length(supported_padding_modes);
143*789431f2SAndroid Build Coastguard Worker     return supported_padding_modes;
144*789431f2SAndroid Build Coastguard Worker }
145*789431f2SAndroid Build Coastguard Worker 
BlockCipherEvpOperation(keymaster_purpose_t purpose,keymaster_block_mode_t block_mode,keymaster_padding_t padding,bool caller_iv,size_t tag_length,Key && key,const EvpCipherDescription & cipher_description)146*789431f2SAndroid Build Coastguard Worker BlockCipherEvpOperation::BlockCipherEvpOperation(keymaster_purpose_t purpose,
147*789431f2SAndroid Build Coastguard Worker                                                  keymaster_block_mode_t block_mode,
148*789431f2SAndroid Build Coastguard Worker                                                  keymaster_padding_t padding, bool caller_iv,
149*789431f2SAndroid Build Coastguard Worker                                                  size_t tag_length, Key&& key,
150*789431f2SAndroid Build Coastguard Worker                                                  const EvpCipherDescription& cipher_description)
151*789431f2SAndroid Build Coastguard Worker     : Operation(purpose, key.hw_enforced_move(), key.sw_enforced_move()), block_mode_(block_mode),
152*789431f2SAndroid Build Coastguard Worker       caller_iv_(caller_iv), tag_length_(tag_length), data_started_(false), padding_(padding),
153*789431f2SAndroid Build Coastguard Worker       key_(key.key_material_move()), cipher_description_(cipher_description) {
154*789431f2SAndroid Build Coastguard Worker     EVP_CIPHER_CTX_init(&ctx_);
155*789431f2SAndroid Build Coastguard Worker }
156*789431f2SAndroid Build Coastguard Worker 
~BlockCipherEvpOperation()157*789431f2SAndroid Build Coastguard Worker BlockCipherEvpOperation::~BlockCipherEvpOperation() {
158*789431f2SAndroid Build Coastguard Worker     EVP_CIPHER_CTX_cleanup(&ctx_);
159*789431f2SAndroid Build Coastguard Worker }
160*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet &,AuthorizationSet *)161*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpOperation::Begin(const AuthorizationSet& /* input_params */,
162*789431f2SAndroid Build Coastguard Worker                                                  AuthorizationSet* /* output_params */) {
163*789431f2SAndroid Build Coastguard Worker     auto rc = GenerateRandom(reinterpret_cast<uint8_t*>(&operation_handle_),
164*789431f2SAndroid Build Coastguard Worker                              (size_t)sizeof(operation_handle_));
165*789431f2SAndroid Build Coastguard Worker     if (rc != KM_ERROR_OK) return rc;
166*789431f2SAndroid Build Coastguard Worker 
167*789431f2SAndroid Build Coastguard Worker     auto retval = InitializeCipher(key_);
168*789431f2SAndroid Build Coastguard Worker     key_ = {};
169*789431f2SAndroid Build Coastguard Worker     return retval;
170*789431f2SAndroid Build Coastguard Worker }
171*789431f2SAndroid Build Coastguard Worker 
Update(const AuthorizationSet & additional_params,const Buffer & input,AuthorizationSet *,Buffer * output,size_t * input_consumed)172*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpOperation::Update(const AuthorizationSet& additional_params,
173*789431f2SAndroid Build Coastguard Worker                                                   const Buffer& input,
174*789431f2SAndroid Build Coastguard Worker                                                   AuthorizationSet* /* output_params */,
175*789431f2SAndroid Build Coastguard Worker                                                   Buffer* output, size_t* input_consumed) {
176*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
177*789431f2SAndroid Build Coastguard Worker     if (block_mode_ == KM_MODE_GCM && !HandleAad(additional_params, input, &error)) return error;
178*789431f2SAndroid Build Coastguard Worker     if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error)) return error;
179*789431f2SAndroid Build Coastguard Worker     *input_consumed = input.available_read();
180*789431f2SAndroid Build Coastguard Worker 
181*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
182*789431f2SAndroid Build Coastguard Worker }
183*789431f2SAndroid Build Coastguard Worker 
184*789431f2SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-runtime-int)
is_bad_decrypt(unsigned long error)185*789431f2SAndroid Build Coastguard Worker inline bool is_bad_decrypt(unsigned long error) {
186*789431f2SAndroid Build Coastguard Worker     return (ERR_GET_LIB(error) == ERR_LIB_CIPHER &&  //
187*789431f2SAndroid Build Coastguard Worker             ERR_GET_REASON(error) == CIPHER_R_BAD_DECRYPT);
188*789431f2SAndroid Build Coastguard Worker }
189*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer &,AuthorizationSet * output_params,Buffer * output)190*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpOperation::Finish(const AuthorizationSet& additional_params,
191*789431f2SAndroid Build Coastguard Worker                                                   const Buffer& input,
192*789431f2SAndroid Build Coastguard Worker                                                   const Buffer& /* signature */,
193*789431f2SAndroid Build Coastguard Worker                                                   AuthorizationSet* output_params, Buffer* output) {
194*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
195*789431f2SAndroid Build Coastguard Worker     if (!UpdateForFinish(additional_params, input, output_params, output, &error)) return error;
196*789431f2SAndroid Build Coastguard Worker     if (!output->reserve(block_size_bytes())) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
197*789431f2SAndroid Build Coastguard Worker 
198*789431f2SAndroid Build Coastguard Worker     if (block_mode_ == KM_MODE_GCM && aad_block_buf_len_ > 0 && !ProcessBufferedAadBlock(&error)) {
199*789431f2SAndroid Build Coastguard Worker         return error;
200*789431f2SAndroid Build Coastguard Worker     }
201*789431f2SAndroid Build Coastguard Worker 
202*789431f2SAndroid Build Coastguard Worker     int output_written = -1;
203*789431f2SAndroid Build Coastguard Worker     if (!EVP_CipherFinal_ex(&ctx_, output->peek_write(), &output_written)) {
204*789431f2SAndroid Build Coastguard Worker         if (tag_length_ > 0) return KM_ERROR_VERIFICATION_FAILED;
205*789431f2SAndroid Build Coastguard Worker         char buf[128];
206*789431f2SAndroid Build Coastguard Worker         ERR_error_string_n(ERR_peek_last_error(), buf, sizeof(buf));
207*789431f2SAndroid Build Coastguard Worker         LOG_E("Error encrypting final block: %s", buf);
208*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
209*789431f2SAndroid Build Coastguard Worker     }
210*789431f2SAndroid Build Coastguard Worker 
211*789431f2SAndroid Build Coastguard Worker     assert(output_written >= 0);
212*789431f2SAndroid Build Coastguard Worker     assert(static_cast<size_t>(output_written) <= block_size_bytes());
213*789431f2SAndroid Build Coastguard Worker     if (!output->advance_write(output_written)) return KM_ERROR_UNKNOWN_ERROR;
214*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
215*789431f2SAndroid Build Coastguard Worker }
216*789431f2SAndroid Build Coastguard Worker 
need_iv() const217*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpOperation::need_iv() const {
218*789431f2SAndroid Build Coastguard Worker     switch (block_mode_) {
219*789431f2SAndroid Build Coastguard Worker     case KM_MODE_CBC:
220*789431f2SAndroid Build Coastguard Worker     case KM_MODE_CTR:
221*789431f2SAndroid Build Coastguard Worker     case KM_MODE_GCM:
222*789431f2SAndroid Build Coastguard Worker         return true;
223*789431f2SAndroid Build Coastguard Worker     case KM_MODE_ECB:
224*789431f2SAndroid Build Coastguard Worker         return false;
225*789431f2SAndroid Build Coastguard Worker     default:
226*789431f2SAndroid Build Coastguard Worker         // Shouldn't get here.
227*789431f2SAndroid Build Coastguard Worker         assert(false);
228*789431f2SAndroid Build Coastguard Worker         return false;
229*789431f2SAndroid Build Coastguard Worker     }
230*789431f2SAndroid Build Coastguard Worker }
231*789431f2SAndroid Build Coastguard Worker 
InitializeCipher(const KeymasterKeyBlob & key)232*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpOperation::InitializeCipher(const KeymasterKeyBlob& key) {
233*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
234*789431f2SAndroid Build Coastguard Worker     const EVP_CIPHER* cipher =
235*789431f2SAndroid Build Coastguard Worker         cipher_description_.GetCipherInstance(key.key_material_size, block_mode_, &error);
236*789431f2SAndroid Build Coastguard Worker     if (error) return error;
237*789431f2SAndroid Build Coastguard Worker 
238*789431f2SAndroid Build Coastguard Worker     if (!EVP_CipherInit_ex(&ctx_, cipher, nullptr /* engine */, key.key_material, iv_.data,
239*789431f2SAndroid Build Coastguard Worker                            evp_encrypt_mode())) {
240*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
241*789431f2SAndroid Build Coastguard Worker     }
242*789431f2SAndroid Build Coastguard Worker 
243*789431f2SAndroid Build Coastguard Worker     switch (padding_) {
244*789431f2SAndroid Build Coastguard Worker     case KM_PAD_NONE:
245*789431f2SAndroid Build Coastguard Worker         EVP_CIPHER_CTX_set_padding(&ctx_, 0 /* disable padding */);
246*789431f2SAndroid Build Coastguard Worker         break;
247*789431f2SAndroid Build Coastguard Worker     case KM_PAD_PKCS7:
248*789431f2SAndroid Build Coastguard Worker         // This is the default for OpenSSL EVP cipher operations.
249*789431f2SAndroid Build Coastguard Worker         break;
250*789431f2SAndroid Build Coastguard Worker     default:
251*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_UNSUPPORTED_PADDING_MODE;
252*789431f2SAndroid Build Coastguard Worker     }
253*789431f2SAndroid Build Coastguard Worker 
254*789431f2SAndroid Build Coastguard Worker     if (block_mode_ == KM_MODE_GCM) {
255*789431f2SAndroid Build Coastguard Worker         aad_block_buf_.reset(new (std::nothrow) uint8_t[block_size_bytes()]);
256*789431f2SAndroid Build Coastguard Worker         if (!aad_block_buf_) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
257*789431f2SAndroid Build Coastguard Worker         aad_block_buf_len_ = 0;
258*789431f2SAndroid Build Coastguard Worker     }
259*789431f2SAndroid Build Coastguard Worker 
260*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
261*789431f2SAndroid Build Coastguard Worker }
262*789431f2SAndroid Build Coastguard Worker 
GetIv(const AuthorizationSet & input_params)263*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpOperation::GetIv(const AuthorizationSet& input_params) {
264*789431f2SAndroid Build Coastguard Worker     keymaster_blob_t iv_blob;
265*789431f2SAndroid Build Coastguard Worker     if (!input_params.GetTagValue(TAG_NONCE, &iv_blob)) {
266*789431f2SAndroid Build Coastguard Worker         LOG_E("No IV provided");
267*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_ARGUMENT;
268*789431f2SAndroid Build Coastguard Worker     }
269*789431f2SAndroid Build Coastguard Worker 
270*789431f2SAndroid Build Coastguard Worker     if (block_mode_ != KM_MODE_GCM && iv_blob.data_length != block_size_bytes()) {
271*789431f2SAndroid Build Coastguard Worker         LOG_E("Expected %zu-byte IV for operation, but got %zu bytes", block_size_bytes(),
272*789431f2SAndroid Build Coastguard Worker               iv_blob.data_length);
273*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_NONCE;
274*789431f2SAndroid Build Coastguard Worker     }
275*789431f2SAndroid Build Coastguard Worker 
276*789431f2SAndroid Build Coastguard Worker     if (block_mode_ == KM_MODE_GCM && iv_blob.data_length != GCM_NONCE_SIZE) {
277*789431f2SAndroid Build Coastguard Worker         LOG_E("Expected %zu-byte nonce for GCM operation, but got %zu bytes", GCM_NONCE_SIZE,
278*789431f2SAndroid Build Coastguard Worker               iv_blob.data_length);
279*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_NONCE;
280*789431f2SAndroid Build Coastguard Worker     }
281*789431f2SAndroid Build Coastguard Worker 
282*789431f2SAndroid Build Coastguard Worker     iv_ = KeymasterBlob(iv_blob.data, iv_blob.data_length);
283*789431f2SAndroid Build Coastguard Worker     if (!iv_.data) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
284*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
285*789431f2SAndroid Build Coastguard Worker }
286*789431f2SAndroid Build Coastguard Worker 
287*789431f2SAndroid Build Coastguard Worker /*
288*789431f2SAndroid Build Coastguard Worker  * Process Incoming Associated Authentication Data.
289*789431f2SAndroid Build Coastguard Worker  *
290*789431f2SAndroid Build Coastguard Worker  * This method is more complex than might be expected, because the underlying library silently does
291*789431f2SAndroid Build Coastguard Worker  * the wrong thing when given partial AAD blocks, so we have to take care to process AAD in block
292*789431f2SAndroid Build Coastguard Worker  * size increments, buffering (in aad_block_buf_) when given smaller amounts of data.
293*789431f2SAndroid Build Coastguard Worker  */
HandleAad(const AuthorizationSet & input_params,const Buffer & input,keymaster_error_t * error)294*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpOperation::HandleAad(const AuthorizationSet& input_params, const Buffer& input,
295*789431f2SAndroid Build Coastguard Worker                                         keymaster_error_t* error) {
296*789431f2SAndroid Build Coastguard Worker     assert(tag_length_ > 0);
297*789431f2SAndroid Build Coastguard Worker     assert(error);
298*789431f2SAndroid Build Coastguard Worker 
299*789431f2SAndroid Build Coastguard Worker     keymaster_blob_t aad;
300*789431f2SAndroid Build Coastguard Worker     if (input_params.GetTagValue(TAG_ASSOCIATED_DATA, &aad)) {
301*789431f2SAndroid Build Coastguard Worker         if (data_started_) {
302*789431f2SAndroid Build Coastguard Worker             *error = KM_ERROR_INVALID_TAG;
303*789431f2SAndroid Build Coastguard Worker             return false;
304*789431f2SAndroid Build Coastguard Worker         }
305*789431f2SAndroid Build Coastguard Worker 
306*789431f2SAndroid Build Coastguard Worker         if (aad_block_buf_len_ > 0) {
307*789431f2SAndroid Build Coastguard Worker             FillBufferedAadBlock(&aad);
308*789431f2SAndroid Build Coastguard Worker             if (aad_block_buf_len_ == block_size_bytes() && !ProcessBufferedAadBlock(error))
309*789431f2SAndroid Build Coastguard Worker                 return false;
310*789431f2SAndroid Build Coastguard Worker         }
311*789431f2SAndroid Build Coastguard Worker 
312*789431f2SAndroid Build Coastguard Worker         size_t block_size = block_size_bytes();
313*789431f2SAndroid Build Coastguard Worker         size_t blocks_to_process = aad.data_length / block_size;
314*789431f2SAndroid Build Coastguard Worker         if (blocks_to_process && !ProcessAadBlocks(aad.data, blocks_to_process, error))
315*789431f2SAndroid Build Coastguard Worker             return false;
316*789431f2SAndroid Build Coastguard Worker         aad.data += blocks_to_process * block_size;
317*789431f2SAndroid Build Coastguard Worker         aad.data_length -= blocks_to_process * block_size;
318*789431f2SAndroid Build Coastguard Worker 
319*789431f2SAndroid Build Coastguard Worker         FillBufferedAadBlock(&aad);
320*789431f2SAndroid Build Coastguard Worker         assert(aad.data_length == 0);
321*789431f2SAndroid Build Coastguard Worker     }
322*789431f2SAndroid Build Coastguard Worker 
323*789431f2SAndroid Build Coastguard Worker     if (input.available_read()) {
324*789431f2SAndroid Build Coastguard Worker         data_started_ = true;
325*789431f2SAndroid Build Coastguard Worker         // Data has begun, no more AAD is allowed.  Process any buffered AAD.
326*789431f2SAndroid Build Coastguard Worker         if (aad_block_buf_len_ > 0 && !ProcessBufferedAadBlock(error)) return false;
327*789431f2SAndroid Build Coastguard Worker     }
328*789431f2SAndroid Build Coastguard Worker 
329*789431f2SAndroid Build Coastguard Worker     return true;
330*789431f2SAndroid Build Coastguard Worker }
331*789431f2SAndroid Build Coastguard Worker 
ProcessBufferedAadBlock(keymaster_error_t * error)332*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpOperation::ProcessBufferedAadBlock(keymaster_error_t* error) {
333*789431f2SAndroid Build Coastguard Worker     int output_written;
334*789431f2SAndroid Build Coastguard Worker     if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, aad_block_buf_.get(),
335*789431f2SAndroid Build Coastguard Worker                          aad_block_buf_len_)) {
336*789431f2SAndroid Build Coastguard Worker         aad_block_buf_len_ = 0;
337*789431f2SAndroid Build Coastguard Worker         return true;
338*789431f2SAndroid Build Coastguard Worker     }
339*789431f2SAndroid Build Coastguard Worker     *error = TranslateLastOpenSslError();
340*789431f2SAndroid Build Coastguard Worker     return false;
341*789431f2SAndroid Build Coastguard Worker }
342*789431f2SAndroid Build Coastguard Worker 
ProcessAadBlocks(const uint8_t * data,size_t blocks,keymaster_error_t * error)343*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpOperation::ProcessAadBlocks(const uint8_t* data, size_t blocks,
344*789431f2SAndroid Build Coastguard Worker                                                keymaster_error_t* error) {
345*789431f2SAndroid Build Coastguard Worker     int output_written;
346*789431f2SAndroid Build Coastguard Worker     if (EVP_CipherUpdate(&ctx_, nullptr /* out */, &output_written, data,
347*789431f2SAndroid Build Coastguard Worker                          blocks * block_size_bytes())) {
348*789431f2SAndroid Build Coastguard Worker         return true;
349*789431f2SAndroid Build Coastguard Worker     }
350*789431f2SAndroid Build Coastguard Worker     *error = TranslateLastOpenSslError();
351*789431f2SAndroid Build Coastguard Worker     return false;
352*789431f2SAndroid Build Coastguard Worker }
353*789431f2SAndroid Build Coastguard Worker 
min(size_t a,size_t b)354*789431f2SAndroid Build Coastguard Worker inline size_t min(size_t a, size_t b) {
355*789431f2SAndroid Build Coastguard Worker     return (a < b) ? a : b;
356*789431f2SAndroid Build Coastguard Worker }
357*789431f2SAndroid Build Coastguard Worker 
FillBufferedAadBlock(keymaster_blob_t * aad)358*789431f2SAndroid Build Coastguard Worker void BlockCipherEvpOperation::FillBufferedAadBlock(keymaster_blob_t* aad) {
359*789431f2SAndroid Build Coastguard Worker     size_t to_buffer = min(block_size_bytes() - aad_block_buf_len_, aad->data_length);
360*789431f2SAndroid Build Coastguard Worker     memcpy(aad_block_buf_.get() + aad_block_buf_len_, aad->data, to_buffer);
361*789431f2SAndroid Build Coastguard Worker     aad->data += to_buffer;
362*789431f2SAndroid Build Coastguard Worker     aad->data_length -= to_buffer;
363*789431f2SAndroid Build Coastguard Worker     aad_block_buf_len_ += to_buffer;
364*789431f2SAndroid Build Coastguard Worker }
365*789431f2SAndroid Build Coastguard Worker 
InternalUpdate(const uint8_t * input,size_t input_length,Buffer * output,keymaster_error_t * error)366*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpOperation::InternalUpdate(const uint8_t* input, size_t input_length,
367*789431f2SAndroid Build Coastguard Worker                                              Buffer* output, keymaster_error_t* error) {
368*789431f2SAndroid Build Coastguard Worker     assert(output);
369*789431f2SAndroid Build Coastguard Worker     assert(error);
370*789431f2SAndroid Build Coastguard Worker 
371*789431f2SAndroid Build Coastguard Worker     if (!input_length) return true;
372*789431f2SAndroid Build Coastguard Worker 
373*789431f2SAndroid Build Coastguard Worker     if (!output->reserve(input_length + block_size_bytes())) {
374*789431f2SAndroid Build Coastguard Worker         *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
375*789431f2SAndroid Build Coastguard Worker         return false;
376*789431f2SAndroid Build Coastguard Worker     }
377*789431f2SAndroid Build Coastguard Worker 
378*789431f2SAndroid Build Coastguard Worker     int output_written = -1;
379*789431f2SAndroid Build Coastguard Worker     if (!EVP_CipherUpdate(&ctx_, output->peek_write(), &output_written, input, input_length)) {
380*789431f2SAndroid Build Coastguard Worker         *error = TranslateLastOpenSslError();
381*789431f2SAndroid Build Coastguard Worker         return false;
382*789431f2SAndroid Build Coastguard Worker     }
383*789431f2SAndroid Build Coastguard Worker     return output->advance_write(output_written);
384*789431f2SAndroid Build Coastguard Worker }
385*789431f2SAndroid Build Coastguard Worker 
UpdateForFinish(const AuthorizationSet & additional_params,const Buffer & input,AuthorizationSet * output_params,Buffer * output,keymaster_error_t * error)386*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpOperation::UpdateForFinish(const AuthorizationSet& additional_params,
387*789431f2SAndroid Build Coastguard Worker                                               const Buffer& input, AuthorizationSet* output_params,
388*789431f2SAndroid Build Coastguard Worker                                               Buffer* output, keymaster_error_t* error) {
389*789431f2SAndroid Build Coastguard Worker     if (input.available_read() || !additional_params.empty()) {
390*789431f2SAndroid Build Coastguard Worker         size_t input_consumed;
391*789431f2SAndroid Build Coastguard Worker         *error = Update(additional_params, input, output_params, output, &input_consumed);
392*789431f2SAndroid Build Coastguard Worker         if (*error != KM_ERROR_OK) return false;
393*789431f2SAndroid Build Coastguard Worker         if (input_consumed != input.available_read()) {
394*789431f2SAndroid Build Coastguard Worker             *error = KM_ERROR_INVALID_INPUT_LENGTH;
395*789431f2SAndroid Build Coastguard Worker             return false;
396*789431f2SAndroid Build Coastguard Worker         }
397*789431f2SAndroid Build Coastguard Worker     }
398*789431f2SAndroid Build Coastguard Worker 
399*789431f2SAndroid Build Coastguard Worker     return true;
400*789431f2SAndroid Build Coastguard Worker }
401*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet & input_params,AuthorizationSet * output_params)402*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpEncryptOperation::Begin(const AuthorizationSet& input_params,
403*789431f2SAndroid Build Coastguard Worker                                                         AuthorizationSet* output_params) {
404*789431f2SAndroid Build Coastguard Worker     if (!output_params) return KM_ERROR_OUTPUT_PARAMETER_NULL;
405*789431f2SAndroid Build Coastguard Worker 
406*789431f2SAndroid Build Coastguard Worker     if (need_iv()) {
407*789431f2SAndroid Build Coastguard Worker         keymaster_error_t error = KM_ERROR_OK;
408*789431f2SAndroid Build Coastguard Worker         if (input_params.find(TAG_NONCE) == -1) {
409*789431f2SAndroid Build Coastguard Worker             error = GenerateIv();
410*789431f2SAndroid Build Coastguard Worker         } else if (caller_iv_) {
411*789431f2SAndroid Build Coastguard Worker             error = GetIv(input_params);
412*789431f2SAndroid Build Coastguard Worker         } else {
413*789431f2SAndroid Build Coastguard Worker             error = KM_ERROR_CALLER_NONCE_PROHIBITED;
414*789431f2SAndroid Build Coastguard Worker         }
415*789431f2SAndroid Build Coastguard Worker 
416*789431f2SAndroid Build Coastguard Worker         if (error != KM_ERROR_OK) return error;
417*789431f2SAndroid Build Coastguard Worker         output_params->push_back(TAG_NONCE, iv_.data, iv_.data_length);
418*789431f2SAndroid Build Coastguard Worker     }
419*789431f2SAndroid Build Coastguard Worker 
420*789431f2SAndroid Build Coastguard Worker     return BlockCipherEvpOperation::Begin(input_params, output_params);
421*789431f2SAndroid Build Coastguard Worker }
422*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer & signature,AuthorizationSet * output_params,Buffer * output)423*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpEncryptOperation::Finish(const AuthorizationSet& additional_params,
424*789431f2SAndroid Build Coastguard Worker                                                          const Buffer& input,
425*789431f2SAndroid Build Coastguard Worker                                                          const Buffer& signature,
426*789431f2SAndroid Build Coastguard Worker                                                          AuthorizationSet* output_params,
427*789431f2SAndroid Build Coastguard Worker                                                          Buffer* output) {
428*789431f2SAndroid Build Coastguard Worker     if (!output->reserve(input.available_read() + block_size_bytes() + tag_length_)) {
429*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_MEMORY_ALLOCATION_FAILED;
430*789431f2SAndroid Build Coastguard Worker     }
431*789431f2SAndroid Build Coastguard Worker 
432*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error =
433*789431f2SAndroid Build Coastguard Worker         BlockCipherEvpOperation::Finish(additional_params, input, signature, output_params, output);
434*789431f2SAndroid Build Coastguard Worker     if (error != KM_ERROR_OK) return error;
435*789431f2SAndroid Build Coastguard Worker 
436*789431f2SAndroid Build Coastguard Worker     if (tag_length_ > 0) {
437*789431f2SAndroid Build Coastguard Worker         if (!output->reserve(tag_length_)) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
438*789431f2SAndroid Build Coastguard Worker 
439*789431f2SAndroid Build Coastguard Worker         if (!EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_GET_TAG, tag_length_, output->peek_write()))
440*789431f2SAndroid Build Coastguard Worker             return TranslateLastOpenSslError();
441*789431f2SAndroid Build Coastguard Worker         if (!output->advance_write(tag_length_)) return KM_ERROR_UNKNOWN_ERROR;
442*789431f2SAndroid Build Coastguard Worker     }
443*789431f2SAndroid Build Coastguard Worker 
444*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
445*789431f2SAndroid Build Coastguard Worker }
446*789431f2SAndroid Build Coastguard Worker 
GenerateIv()447*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpEncryptOperation::GenerateIv() {
448*789431f2SAndroid Build Coastguard Worker     iv_.Reset((block_mode_ == KM_MODE_GCM) ? GCM_NONCE_SIZE : block_size_bytes());
449*789431f2SAndroid Build Coastguard Worker     if (!iv_.data) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
450*789431f2SAndroid Build Coastguard Worker     if (RAND_bytes(iv_.writable_data(), iv_.data_length) != 1) return TranslateLastOpenSslError();
451*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
452*789431f2SAndroid Build Coastguard Worker }
453*789431f2SAndroid Build Coastguard Worker 
Begin(const AuthorizationSet & input_params,AuthorizationSet * output_params)454*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpDecryptOperation::Begin(const AuthorizationSet& input_params,
455*789431f2SAndroid Build Coastguard Worker                                                         AuthorizationSet* output_params) {
456*789431f2SAndroid Build Coastguard Worker     if (need_iv()) {
457*789431f2SAndroid Build Coastguard Worker         keymaster_error_t error = GetIv(input_params);
458*789431f2SAndroid Build Coastguard Worker         if (error != KM_ERROR_OK) return error;
459*789431f2SAndroid Build Coastguard Worker     }
460*789431f2SAndroid Build Coastguard Worker 
461*789431f2SAndroid Build Coastguard Worker     if (tag_length_ > 0) {
462*789431f2SAndroid Build Coastguard Worker         tag_buf_.reset(new (std::nothrow) uint8_t[tag_length_]);
463*789431f2SAndroid Build Coastguard Worker         if (!tag_buf_) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
464*789431f2SAndroid Build Coastguard Worker         tag_buf_len_ = 0;
465*789431f2SAndroid Build Coastguard Worker     }
466*789431f2SAndroid Build Coastguard Worker 
467*789431f2SAndroid Build Coastguard Worker     return BlockCipherEvpOperation::Begin(input_params, output_params);
468*789431f2SAndroid Build Coastguard Worker }
469*789431f2SAndroid Build Coastguard Worker 
Update(const AuthorizationSet & additional_params,const Buffer & input,AuthorizationSet *,Buffer * output,size_t * input_consumed)470*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpDecryptOperation::Update(const AuthorizationSet& additional_params,
471*789431f2SAndroid Build Coastguard Worker                                                          const Buffer& input,
472*789431f2SAndroid Build Coastguard Worker                                                          AuthorizationSet* /* output_params */,
473*789431f2SAndroid Build Coastguard Worker                                                          Buffer* output, size_t* input_consumed) {
474*789431f2SAndroid Build Coastguard Worker     if (!output || !input_consumed) return KM_ERROR_OUTPUT_PARAMETER_NULL;
475*789431f2SAndroid Build Coastguard Worker 
476*789431f2SAndroid Build Coastguard Worker     // Barring error, we'll consume it all.
477*789431f2SAndroid Build Coastguard Worker     *input_consumed = input.available_read();
478*789431f2SAndroid Build Coastguard Worker 
479*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
480*789431f2SAndroid Build Coastguard Worker     if (block_mode_ == KM_MODE_GCM) {
481*789431f2SAndroid Build Coastguard Worker         if (!HandleAad(additional_params, input, &error)) return error;
482*789431f2SAndroid Build Coastguard Worker         return ProcessAllButTagLengthBytes(input, output);
483*789431f2SAndroid Build Coastguard Worker     }
484*789431f2SAndroid Build Coastguard Worker 
485*789431f2SAndroid Build Coastguard Worker     if (!InternalUpdate(input.peek_read(), input.available_read(), output, &error)) return error;
486*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
487*789431f2SAndroid Build Coastguard Worker }
488*789431f2SAndroid Build Coastguard Worker 
ProcessAllButTagLengthBytes(const Buffer & input,Buffer * output)489*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpDecryptOperation::ProcessAllButTagLengthBytes(const Buffer& input,
490*789431f2SAndroid Build Coastguard Worker                                                                               Buffer* output) {
491*789431f2SAndroid Build Coastguard Worker     if (input.available_read() <= tag_buf_unused()) {
492*789431f2SAndroid Build Coastguard Worker         BufferCandidateTagData(input.peek_read(), input.available_read());
493*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_OK;
494*789431f2SAndroid Build Coastguard Worker     }
495*789431f2SAndroid Build Coastguard Worker 
496*789431f2SAndroid Build Coastguard Worker     const size_t data_available = tag_buf_len_ + input.available_read();
497*789431f2SAndroid Build Coastguard Worker 
498*789431f2SAndroid Build Coastguard Worker     const size_t to_process = data_available - tag_length_;
499*789431f2SAndroid Build Coastguard Worker     const size_t to_process_from_tag_buf = min(to_process, tag_buf_len_);
500*789431f2SAndroid Build Coastguard Worker     const size_t to_process_from_input = to_process - to_process_from_tag_buf;
501*789431f2SAndroid Build Coastguard Worker 
502*789431f2SAndroid Build Coastguard Worker     if (!output->reserve(to_process + block_size_bytes())) return KM_ERROR_MEMORY_ALLOCATION_FAILED;
503*789431f2SAndroid Build Coastguard Worker 
504*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
505*789431f2SAndroid Build Coastguard Worker     if (!ProcessTagBufContentsAsData(to_process_from_tag_buf, output, &error)) return error;
506*789431f2SAndroid Build Coastguard Worker 
507*789431f2SAndroid Build Coastguard Worker     if (!InternalUpdate(input.peek_read(), to_process_from_input, output, &error)) return error;
508*789431f2SAndroid Build Coastguard Worker 
509*789431f2SAndroid Build Coastguard Worker     BufferCandidateTagData(input.peek_read() + to_process_from_input,
510*789431f2SAndroid Build Coastguard Worker                            input.available_read() - to_process_from_input);
511*789431f2SAndroid Build Coastguard Worker     assert(tag_buf_unused() == 0);
512*789431f2SAndroid Build Coastguard Worker 
513*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
514*789431f2SAndroid Build Coastguard Worker }
515*789431f2SAndroid Build Coastguard Worker 
ProcessTagBufContentsAsData(size_t to_process,Buffer * output,keymaster_error_t * error)516*789431f2SAndroid Build Coastguard Worker bool BlockCipherEvpDecryptOperation::ProcessTagBufContentsAsData(size_t to_process, Buffer* output,
517*789431f2SAndroid Build Coastguard Worker                                                                  keymaster_error_t* error) {
518*789431f2SAndroid Build Coastguard Worker     assert(to_process <= tag_buf_len_);
519*789431f2SAndroid Build Coastguard Worker     if (!InternalUpdate(tag_buf_.get(), to_process, output, error)) return false;
520*789431f2SAndroid Build Coastguard Worker     if (to_process < tag_buf_len_) {
521*789431f2SAndroid Build Coastguard Worker         memmove(tag_buf_.get(), tag_buf_.get() + to_process, tag_buf_len_ - to_process);
522*789431f2SAndroid Build Coastguard Worker     }
523*789431f2SAndroid Build Coastguard Worker     tag_buf_len_ -= to_process;
524*789431f2SAndroid Build Coastguard Worker     return true;
525*789431f2SAndroid Build Coastguard Worker }
526*789431f2SAndroid Build Coastguard Worker 
BufferCandidateTagData(const uint8_t * data,size_t data_length)527*789431f2SAndroid Build Coastguard Worker void BlockCipherEvpDecryptOperation::BufferCandidateTagData(const uint8_t* data,
528*789431f2SAndroid Build Coastguard Worker                                                             size_t data_length) {
529*789431f2SAndroid Build Coastguard Worker     assert(data_length <= tag_length_ - tag_buf_len_);
530*789431f2SAndroid Build Coastguard Worker     memcpy(tag_buf_.get() + tag_buf_len_, data, data_length);
531*789431f2SAndroid Build Coastguard Worker     tag_buf_len_ += data_length;
532*789431f2SAndroid Build Coastguard Worker }
533*789431f2SAndroid Build Coastguard Worker 
Finish(const AuthorizationSet & additional_params,const Buffer & input,const Buffer & signature,AuthorizationSet * output_params,Buffer * output)534*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpDecryptOperation::Finish(const AuthorizationSet& additional_params,
535*789431f2SAndroid Build Coastguard Worker                                                          const Buffer& input,
536*789431f2SAndroid Build Coastguard Worker                                                          const Buffer& signature,
537*789431f2SAndroid Build Coastguard Worker                                                          AuthorizationSet* output_params,
538*789431f2SAndroid Build Coastguard Worker                                                          Buffer* output) {
539*789431f2SAndroid Build Coastguard Worker     keymaster_error_t error;
540*789431f2SAndroid Build Coastguard Worker     if (!UpdateForFinish(additional_params, input, output_params, output, &error)) return error;
541*789431f2SAndroid Build Coastguard Worker 
542*789431f2SAndroid Build Coastguard Worker     if (tag_buf_len_ < tag_length_) {
543*789431f2SAndroid Build Coastguard Worker         return KM_ERROR_INVALID_INPUT_LENGTH;
544*789431f2SAndroid Build Coastguard Worker     } else if (tag_length_ > 0 &&
545*789431f2SAndroid Build Coastguard Worker                !EVP_CIPHER_CTX_ctrl(&ctx_, EVP_CTRL_GCM_SET_TAG, tag_length_, tag_buf_.get())) {
546*789431f2SAndroid Build Coastguard Worker         return TranslateLastOpenSslError();
547*789431f2SAndroid Build Coastguard Worker     }
548*789431f2SAndroid Build Coastguard Worker 
549*789431f2SAndroid Build Coastguard Worker     AuthorizationSet empty_params;
550*789431f2SAndroid Build Coastguard Worker     Buffer empty_input;
551*789431f2SAndroid Build Coastguard Worker     return BlockCipherEvpOperation::Finish(empty_params, empty_input, signature, output_params,
552*789431f2SAndroid Build Coastguard Worker                                            output);
553*789431f2SAndroid Build Coastguard Worker }
554*789431f2SAndroid Build Coastguard Worker 
Abort()555*789431f2SAndroid Build Coastguard Worker keymaster_error_t BlockCipherEvpOperation::Abort() {
556*789431f2SAndroid Build Coastguard Worker     return KM_ERROR_OK;
557*789431f2SAndroid Build Coastguard Worker }
558*789431f2SAndroid Build Coastguard Worker 
559*789431f2SAndroid Build Coastguard Worker }  // namespace keymaster
560