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