// // 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 #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; }