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