1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "tpm_random_source.h"
17
18 #include <android-base/logging.h>
19 #include "tss2/tss2_esys.h"
20 #include "tss2/tss2_rc.h"
21
TpmRandomSource(ESYS_CONTEXT * esys)22 TpmRandomSource::TpmRandomSource(ESYS_CONTEXT* esys) : esys_(esys) {
23 }
24
GenerateRandom(uint8_t * random,size_t requested_length) const25 keymaster_error_t TpmRandomSource::GenerateRandom(
26 uint8_t* random, size_t requested_length) const {
27 if (requested_length == 0) {
28 return KM_ERROR_OK;
29 }
30 // TODO(b/158790549): Pipeline these calls.
31 TPM2B_DIGEST* generated = nullptr;
32 while (requested_length > sizeof(generated->buffer)) {
33 auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
34 ESYS_TR_NONE, sizeof(generated->buffer),
35 &generated);
36 if (rc != TSS2_RC_SUCCESS) {
37 LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
38 << Tss2_RC_Decode(rc) << ")";
39 // TODO(b/158790404): Return a better error code.
40 return KM_ERROR_UNKNOWN_ERROR;
41 }
42 memcpy(random, generated->buffer, sizeof(generated->buffer));
43 random = (uint8_t*) random + sizeof(generated->buffer);
44 requested_length -= sizeof(generated->buffer);
45 Esys_Free(generated);
46 }
47 auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
48 ESYS_TR_NONE, requested_length, &generated);
49 if (rc != TSS2_RC_SUCCESS) {
50 LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
51 << Tss2_RC_Decode(rc) << ")";
52 // TODO(b/158790404): Return a better error code.
53 return KM_ERROR_UNKNOWN_ERROR;
54 }
55 memcpy(random, generated->buffer, requested_length);
56 Esys_Free(generated);
57 return KM_ERROR_OK;
58 }
59
60 // From TPM2_StirRandom specification.
61 static int MAX_STIR_RANDOM_BUFFER_SIZE = 128;
62
AddRngEntropy(const uint8_t * buffer,size_t size) const63 keymaster_error_t TpmRandomSource::AddRngEntropy(
64 const uint8_t* buffer, size_t size) const {
65 TPM2B_SENSITIVE_DATA in_data;
66 while (size > MAX_STIR_RANDOM_BUFFER_SIZE) {
67 memcpy(in_data.buffer, buffer, MAX_STIR_RANDOM_BUFFER_SIZE);
68 in_data.size = MAX_STIR_RANDOM_BUFFER_SIZE;
69 buffer += MAX_STIR_RANDOM_BUFFER_SIZE;
70 size -= MAX_STIR_RANDOM_BUFFER_SIZE;
71 auto rc = Esys_StirRandom(
72 esys_,
73 ESYS_TR_NONE,
74 ESYS_TR_NONE,
75 ESYS_TR_NONE,
76 &in_data);
77 if (rc != TSS2_RC_SUCCESS) {
78 LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
79 << Tss2_RC_Decode(rc) << ")";
80 return KM_ERROR_UNKNOWN_ERROR;
81 }
82 }
83 if (size == 0) {
84 return KM_ERROR_OK;
85 }
86 memcpy(in_data.buffer, buffer, size);
87 auto rc = Esys_StirRandom(
88 esys_,
89 ESYS_TR_NONE,
90 ESYS_TR_NONE,
91 ESYS_TR_NONE,
92 &in_data);
93 if (rc != TSS2_RC_SUCCESS) {
94 LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
95 << Tss2_RC_Decode(rc) << ")";
96 return KM_ERROR_UNKNOWN_ERROR;
97 }
98 return KM_ERROR_OK;
99 }
100