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