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
22 namespace cuttlefish {
23
TpmRandomSource(ESYS_CONTEXT * esys)24 TpmRandomSource::TpmRandomSource(ESYS_CONTEXT* esys) : esys_(esys) {
25 }
26
GenerateRandom(uint8_t * random,size_t requested_length) const27 keymaster_error_t TpmRandomSource::GenerateRandom(
28 uint8_t* random, size_t requested_length) const {
29 if (requested_length == 0) {
30 return KM_ERROR_OK;
31 }
32 // TODO(b/158790549): Pipeline these calls.
33 TPM2B_DIGEST* generated = nullptr;
34 while (requested_length > sizeof(generated->buffer)) {
35 auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
36 ESYS_TR_NONE, sizeof(generated->buffer),
37 &generated);
38 if (rc != TSS2_RC_SUCCESS) {
39 LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
40 << Tss2_RC_Decode(rc) << ")";
41 // TODO(b/158790404): Return a better error code.
42 return KM_ERROR_UNKNOWN_ERROR;
43 }
44 memcpy(random, generated->buffer, sizeof(generated->buffer));
45 random = (uint8_t*) random + sizeof(generated->buffer);
46 requested_length -= sizeof(generated->buffer);
47 Esys_Free(generated);
48 }
49 auto rc = Esys_GetRandom(esys_, ESYS_TR_NONE, ESYS_TR_NONE,
50 ESYS_TR_NONE, requested_length, &generated);
51 if (rc != TSS2_RC_SUCCESS) {
52 LOG(ERROR) << "Esys_GetRandom failed with " << rc << " ("
53 << Tss2_RC_Decode(rc) << ")";
54 // TODO(b/158790404): Return a better error code.
55 return KM_ERROR_UNKNOWN_ERROR;
56 }
57 memcpy(random, generated->buffer, requested_length);
58 Esys_Free(generated);
59 return KM_ERROR_OK;
60 }
61
62 // From TPM2_StirRandom specification.
63 static int MAX_STIR_RANDOM_BUFFER_SIZE = 128;
64
AddRngEntropy(const uint8_t * buffer,size_t size) const65 keymaster_error_t TpmRandomSource::AddRngEntropy(
66 const uint8_t* buffer, size_t size) const {
67 if (size > 2048) {
68 // IKeyMintDevice.aidl specifies that there's an upper limit of 2KiB.
69 return KM_ERROR_INVALID_INPUT_LENGTH;
70 }
71
72 TPM2B_SENSITIVE_DATA in_data;
73 while (size > MAX_STIR_RANDOM_BUFFER_SIZE) {
74 memcpy(in_data.buffer, buffer, MAX_STIR_RANDOM_BUFFER_SIZE);
75 in_data.size = MAX_STIR_RANDOM_BUFFER_SIZE;
76 buffer += MAX_STIR_RANDOM_BUFFER_SIZE;
77 size -= MAX_STIR_RANDOM_BUFFER_SIZE;
78 auto rc = Esys_StirRandom(
79 esys_,
80 ESYS_TR_NONE,
81 ESYS_TR_NONE,
82 ESYS_TR_NONE,
83 &in_data);
84 if (rc != TSS2_RC_SUCCESS) {
85 LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
86 << Tss2_RC_Decode(rc) << ")";
87 return KM_ERROR_UNKNOWN_ERROR;
88 }
89 }
90 if (size == 0) {
91 return KM_ERROR_OK;
92 }
93 memcpy(in_data.buffer, buffer, size);
94 auto rc = Esys_StirRandom(
95 esys_,
96 ESYS_TR_NONE,
97 ESYS_TR_NONE,
98 ESYS_TR_NONE,
99 &in_data);
100 if (rc != TSS2_RC_SUCCESS) {
101 LOG(ERROR) << "Esys_StirRandom failed with " << rc << "("
102 << Tss2_RC_Decode(rc) << ")";
103 return KM_ERROR_UNKNOWN_ERROR;
104 }
105 return KM_ERROR_OK;
106 }
107
108 } // namespace cuttlefish
109