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_attestation_record.h"
17 
18 #include <keymaster/contexts/soft_attestation_cert.h>
19 #include <keymaster/km_openssl/attestation_record.h>
20 
21 #include <openssl/rand.h>
22 
23 #include <android-base/logging.h>
24 
25 namespace cuttlefish {
26 
27 namespace {
28 using VerifiedBootParams = keymaster::AttestationContext::VerifiedBootParams;
29 using keymaster::AuthorizationSet;
30 
MakeVbParams()31 VerifiedBootParams MakeVbParams() {
32   VerifiedBootParams vb_params;
33 
34   // TODO: If Cuttlefish ever supports a boot state other than "orange", we'll
35   // also need to plumb in the public key.
36   static uint8_t empty_vb_key[32] = {};
37   vb_params.verified_boot_key = {empty_vb_key, sizeof(empty_vb_key)};
38   vb_params.verified_boot_hash = {empty_vb_key, sizeof(empty_vb_key)};
39   vb_params.verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
40   vb_params.device_locked = false;
41   return vb_params;
42 }
43 
44 }  // namespace
45 
TpmAttestationRecordContext()46 TpmAttestationRecordContext::TpmAttestationRecordContext()
47     : keymaster::AttestationContext(::keymaster::KmVersion::KEYMINT_3),
48       vb_params_(MakeVbParams()),
49       unique_id_hbk_(16) {
50   RAND_bytes(unique_id_hbk_.data(), unique_id_hbk_.size());
51 }
52 
GetSecurityLevel() const53 keymaster_security_level_t TpmAttestationRecordContext::GetSecurityLevel() const {
54   return KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
55 }
56 
57 // Return true if entries match, false otherwise.
matchAttestationId(keymaster_blob_t blob,const std::vector<uint8_t> & id)58 bool matchAttestationId(keymaster_blob_t blob, const std::vector<uint8_t>& id) {
59   if (blob.data_length != id.size()) {
60     return false;
61   }
62   if (memcmp(blob.data, id.data(), id.size())) {
63     return false;
64   }
65   return true;
66 }
67 
VerifyAndCopyDeviceIds(const AuthorizationSet & attestation_params,AuthorizationSet * attestation) const68 keymaster_error_t TpmAttestationRecordContext::VerifyAndCopyDeviceIds(
69     const AuthorizationSet& attestation_params,
70     AuthorizationSet* attestation) const {
71   const AttestationIds& ids = attestation_ids_;
72   bool found_mismatch = false;
73   for (auto& entry : attestation_params) {
74     switch (entry.tag) {
75       case KM_TAG_ATTESTATION_ID_BRAND:
76         found_mismatch |= !matchAttestationId(entry.blob, ids.brand);
77         attestation->push_back(entry);
78         break;
79 
80       case KM_TAG_ATTESTATION_ID_DEVICE:
81         found_mismatch |= !matchAttestationId(entry.blob, ids.device);
82         attestation->push_back(entry);
83         break;
84 
85       case KM_TAG_ATTESTATION_ID_PRODUCT:
86         found_mismatch |= !matchAttestationId(entry.blob, ids.product);
87         attestation->push_back(entry);
88         break;
89 
90       case KM_TAG_ATTESTATION_ID_SERIAL:
91         found_mismatch |= !matchAttestationId(entry.blob, ids.serial);
92         attestation->push_back(entry);
93         break;
94 
95       case KM_TAG_ATTESTATION_ID_IMEI:
96         found_mismatch |= !matchAttestationId(entry.blob, ids.imei);
97         attestation->push_back(entry);
98         break;
99 
100       case KM_TAG_ATTESTATION_ID_MEID:
101         found_mismatch |= !matchAttestationId(entry.blob, ids.meid);
102         attestation->push_back(entry);
103         break;
104 
105       case KM_TAG_ATTESTATION_ID_MANUFACTURER:
106         found_mismatch |= !matchAttestationId(entry.blob, ids.manufacturer);
107         attestation->push_back(entry);
108         break;
109 
110       case KM_TAG_ATTESTATION_ID_MODEL:
111         found_mismatch |= !matchAttestationId(entry.blob, ids.model);
112         attestation->push_back(entry);
113         break;
114 
115       case KM_TAG_ATTESTATION_ID_SECOND_IMEI:
116         found_mismatch |= !matchAttestationId(entry.blob, ids.second_imei);
117         attestation->push_back(entry);
118         break;
119 
120       default:
121         // Ignore non-ID tags.
122         break;
123     }
124   }
125 
126   if (found_mismatch) {
127     attestation->Clear();
128     return KM_ERROR_CANNOT_ATTEST_IDS;
129   }
130 
131   return KM_ERROR_OK;
132 }
133 
GenerateUniqueId(uint64_t creation_date_time,const keymaster_blob_t & application_id,bool reset_since_rotation,keymaster_error_t * error) const134 keymaster::Buffer TpmAttestationRecordContext::GenerateUniqueId(
135     uint64_t creation_date_time, const keymaster_blob_t& application_id,
136     bool reset_since_rotation, keymaster_error_t* error) const {
137   keymaster::Buffer unique_id;
138   *error = keymaster::generate_unique_id(unique_id_hbk_, creation_date_time,
139                                          application_id, reset_since_rotation,
140                                          &unique_id);
141   return unique_id;
142 }
143 
GetVerifiedBootParams(keymaster_error_t * error) const144 const VerifiedBootParams* TpmAttestationRecordContext::GetVerifiedBootParams(
145     keymaster_error_t* error) const {
146   *error = KM_ERROR_OK;
147   return &vb_params_;
148 }
149 
150 keymaster::KeymasterKeyBlob
GetAttestationKey(keymaster_algorithm_t algorithm,keymaster_error_t * error) const151 TpmAttestationRecordContext::GetAttestationKey(keymaster_algorithm_t algorithm,
152                                                keymaster_error_t* error) const {
153   return keymaster::KeymasterKeyBlob(*keymaster::getAttestationKey(algorithm, error));
154 }
155 
156 keymaster::CertificateChain
GetAttestationChain(keymaster_algorithm_t algorithm,keymaster_error_t * error) const157 TpmAttestationRecordContext::GetAttestationChain(keymaster_algorithm_t algorithm,
158                                                  keymaster_error_t* error) const {
159   return keymaster::getAttestationChain(algorithm, error);
160 }
161 
SetVerifiedBootInfo(std::string_view verified_boot_state,std::string_view bootloader_state,const std::vector<uint8_t> & vbmeta_digest)162 void TpmAttestationRecordContext::SetVerifiedBootInfo(
163     std::string_view verified_boot_state, std::string_view bootloader_state,
164     const std::vector<uint8_t>& vbmeta_digest) {
165   vbmeta_digest_ = vbmeta_digest;
166   vb_params_.verified_boot_hash = {vbmeta_digest_.data(),
167                                    vbmeta_digest_.size()};
168 
169   if (verified_boot_state == "green") {
170     vb_params_.verified_boot_state = KM_VERIFIED_BOOT_VERIFIED;
171   } else if (verified_boot_state == "yellow") {
172     vb_params_.verified_boot_state = KM_VERIFIED_BOOT_SELF_SIGNED;
173   } else if (verified_boot_state == "red") {
174     vb_params_.verified_boot_state = KM_VERIFIED_BOOT_FAILED;
175   } else {  // Default to orange
176     vb_params_.verified_boot_state = KM_VERIFIED_BOOT_UNVERIFIED;
177   }
178 
179   vb_params_.device_locked = bootloader_state == "locked";
180 }
181 
SetAttestationIds(const keymaster::SetAttestationIdsRequest & request)182 keymaster_error_t TpmAttestationRecordContext::SetAttestationIds(
183     const keymaster::SetAttestationIdsRequest& request) {
184   attestation_ids_.brand.assign(request.brand.begin(), request.brand.end());
185   attestation_ids_.device.assign(request.device.begin(), request.device.end());
186   attestation_ids_.product.assign(request.product.begin(),
187                                   request.product.end());
188   attestation_ids_.serial.assign(request.serial.begin(), request.serial.end());
189   attestation_ids_.imei.assign(request.imei.begin(), request.imei.end());
190   attestation_ids_.meid.assign(request.meid.begin(), request.meid.end());
191   attestation_ids_.manufacturer.assign(request.manufacturer.begin(),
192                                        request.manufacturer.end());
193   attestation_ids_.model.assign(request.model.begin(), request.model.end());
194 
195   return KM_ERROR_OK;
196 }
197 
SetAttestationIdsKM3(const keymaster::SetAttestationIdsKM3Request & request)198 keymaster_error_t TpmAttestationRecordContext::SetAttestationIdsKM3(
199     const keymaster::SetAttestationIdsKM3Request& request) {
200   SetAttestationIds(request.base);
201   attestation_ids_.second_imei.assign(request.second_imei.begin(),
202                                       request.second_imei.end());
203 
204   return KM_ERROR_OK;
205 }
206 }  // namespace cuttlefish
207