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