blob: c81d7d692e2023643dc4ba6208e54acc47fe776e [file] [log] [blame]
//
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "tpm_encrypt_decrypt.h"
#include <algorithm>
#include <cstring>
#include <vector>
#include <android-base/logging.h>
#include <tss2/tss2_rc.h>
namespace cuttlefish {
using keymaster::KeymasterBlob;
static bool TpmEncryptDecrypt( //
ESYS_CONTEXT* esys, ESYS_TR key_handle, TpmAuth auth, const TPM2B_IV& iv,
uint8_t* data_in, uint8_t* data_out, size_t data_size, bool decrypt) {
if (iv.size != sizeof(iv.buffer)) {
LOG(ERROR) << "Input IV had wrong size: " << iv.size;
return false;
}
// TODO(schuffelen): Pipeline this for performance. Will require reevaluating
// the initialization vector logic.
std::vector<unsigned char> converted(data_size);
// malloc for parity with Esys_EncryptDecrypt2
TPM2B_IV* init_vector_in = (TPM2B_IV*) malloc(sizeof(TPM2B_IV));
*init_vector_in = iv;
for (auto processed = 0; processed < data_size;) {
TPM2B_MAX_BUFFER in_data;
in_data.size =
std::min(data_size - processed, sizeof(in_data.buffer));
std::memcpy(in_data.buffer, &data_in[processed], in_data.size);
TPM2B_IV* init_vector_out = nullptr;
TPM2B_MAX_BUFFER* out_data = nullptr;
auto rc = Esys_EncryptDecrypt2(
esys,
key_handle,
auth.auth1(),
auth.auth2(),
auth.auth3(),
&in_data,
decrypt ? TPM2_YES : TPM2_NO,
TPM2_ALG_NULL,
init_vector_in,
&out_data,
&init_vector_out);
if (rc != TPM2_RC_SUCCESS) {
LOG(ERROR) << "Esys_EncryptDecrypt2 failed: " << Tss2_RC_Decode(rc)
<< "(" << rc << ")";
Esys_Free(init_vector_in);
return false;
}
CHECK(init_vector_out != nullptr) << "init_vector_out was NULL";
CHECK(out_data != nullptr) << "out_data was NULL";
CHECK(out_data->size == in_data.size) << "data size mismatch";
std::memcpy(&data_out[processed], out_data->buffer, out_data->size);
Esys_Free(out_data);
Esys_Free(init_vector_in);
init_vector_in = init_vector_out;
processed += in_data.size;
}
Esys_Free(init_vector_in);
return true;
}
bool TpmEncrypt(ESYS_CONTEXT* esys, ESYS_TR key_handle, TpmAuth auth,
const TPM2B_IV& iv, uint8_t* data_in, uint8_t* data_out,
size_t data_size) {
return TpmEncryptDecrypt( //
esys, key_handle, auth, iv, data_in, data_out, data_size, false);
}
bool TpmDecrypt(ESYS_CONTEXT* esys, ESYS_TR key_handle, TpmAuth auth,
const TPM2B_IV& iv, uint8_t* data_in, uint8_t* data_out,
size_t data_size) {
return TpmEncryptDecrypt( //
esys, key_handle, auth, iv, data_in, data_out, data_size, true);
}
} // namespace cuttlefish