blob: 8695e4af0ac2e3632d9bcd26c36d85ed1fba9d0f [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_random_source.h"
#include <android-base/logging.h>
#include "tss2/tss2_esys.h"
#include "tss2/tss2_rc.h"
TpmRandomSource::TpmRandomSource(ESYS_CONTEXT* esys) : esys_(esys) {
}
keymaster_error_t TpmRandomSource::GenerateRandom(
uint8_t* random, size_t requested_length) const {
if (requested_length == 0) {
return KM_ERROR_OK;
}
// TODO(b/158790549): Pipeline these calls.
TPM2B_DIGEST* generated = nullptr;
while (requested_length > sizeof(generated->buffer)) {
auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
ESYS_TR_NONE, sizeof(generated->buffer),
&generated);
if (rc != TSS2_RC_SUCCESS) {
LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
<< Tss2_RC_Decode(rc) << ")";
// TODO(b/158790404): Return a better error code.
return KM_ERROR_UNKNOWN_ERROR;
}
memcpy(random, generated->buffer, sizeof(generated->buffer));
random = (uint8_t*) random + sizeof(generated->buffer);
requested_length -= sizeof(generated->buffer);
Esys_Free(generated);
}
auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
ESYS_TR_NONE, requested_length, &generated);
if (rc != TSS2_RC_SUCCESS) {
LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
<< Tss2_RC_Decode(rc) << ")";
// TODO(b/158790404): Return a better error code.
return KM_ERROR_UNKNOWN_ERROR;
}
memcpy(random, generated->buffer, requested_length);
Esys_Free(generated);
return KM_ERROR_OK;
}
// From TPM2_StirRandom specification.
static int MAX_STIR_RANDOM_BUFFER_SIZE = 128;
keymaster_error_t TpmRandomSource::AddRngEntropy(
const uint8_t* buffer, size_t size) const {
TPM2B_SENSITIVE_DATA in_data;
while (size > MAX_STIR_RANDOM_BUFFER_SIZE) {
memcpy(in_data.buffer, buffer, MAX_STIR_RANDOM_BUFFER_SIZE);
in_data.size = MAX_STIR_RANDOM_BUFFER_SIZE;
buffer += MAX_STIR_RANDOM_BUFFER_SIZE;
size -= MAX_STIR_RANDOM_BUFFER_SIZE;
auto rc = Esys_StirRandom(
esys_,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
&in_data);
if (rc != TSS2_RC_SUCCESS) {
LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
<< Tss2_RC_Decode(rc) << ")";
return KM_ERROR_UNKNOWN_ERROR;
}
}
if (size == 0) {
return KM_ERROR_OK;
}
memcpy(in_data.buffer, buffer, size);
auto rc = Esys_StirRandom(
esys_,
ESYS_TR_NONE,
ESYS_TR_NONE,
ESYS_TR_NONE,
&in_data);
if (rc != TSS2_RC_SUCCESS) {
LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
<< Tss2_RC_Decode(rc) << ")";
return KM_ERROR_UNKNOWN_ERROR;
}
return KM_ERROR_OK;
}