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
17 #include <errno.h>
18 #include <getopt.h>
19 #include <libxml/xmlreader.h>
20 #include <openssl/pem.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/uio.h>
26 #include <unistd.h>
27 #include <string>
28
29 using std::string;
30
31 #include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
32
33 static const char* _sopts = "h";
34 static const struct option _lopts[] = {
35 {"help", no_argument, 0, 'h'},
36 {0, 0, 0, 0},
37 };
38
39 static const char* usage =
40 "Usage: %s [options] xml-file\n"
41 "\n"
42 "options:\n"
43 " -h, --help prints this message and exit\n"
44 "\n";
45
print_usage_and_exit(const char * prog,int code)46 static void print_usage_and_exit(const char* prog, int code) {
47 fprintf(stderr, usage, prog);
48 exit(code);
49 }
50
parse_options(int argc,char ** argv)51 static void parse_options(int argc, char** argv) {
52 int c;
53 int oidx = 0;
54
55 while (1) {
56 c = getopt_long(argc, argv, _sopts, _lopts, &oidx);
57 if (c == -1) {
58 break; /* done */
59 }
60
61 switch (c) {
62 case 'h':
63 print_usage_and_exit(argv[0], EXIT_SUCCESS);
64 break;
65
66 default:
67 print_usage_and_exit(argv[0], EXIT_FAILURE);
68 }
69 }
70 }
71
72 struct SetAttestationKeyRequest : public keymaster::KeymasterMessage {
SetAttestationKeyRequestSetAttestationKeyRequest73 explicit SetAttestationKeyRequest(int32_t ver = keymaster::kDefaultMessageVersion)
74 : KeymasterMessage(ver) {}
75
SerializedSizeSetAttestationKeyRequest76 size_t SerializedSize() const override { return sizeof(uint32_t) + key_data.SerializedSize(); }
SerializeSetAttestationKeyRequest77 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
78 buf = keymaster::append_uint32_to_buf(buf, end, algorithm);
79 return key_data.Serialize(buf, end);
80 }
DeserializeSetAttestationKeyRequest81 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
82 return keymaster::copy_uint32_from_buf(buf_ptr, end, &algorithm) &&
83 key_data.Deserialize(buf_ptr, end);
84 }
85
86 keymaster_algorithm_t algorithm;
87 keymaster::Buffer key_data;
88 };
89
90 struct KeymasterNoResponse : public keymaster::KeymasterResponse {
KeymasterNoResponseKeymasterNoResponse91 explicit KeymasterNoResponse(int32_t ver = keymaster::kDefaultMessageVersion)
92 : keymaster::KeymasterResponse(ver) {}
93
NonErrorSerializedSizeKeymasterNoResponse94 size_t NonErrorSerializedSize() const override { return 0; }
NonErrorSerializeKeymasterNoResponse95 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
NonErrorDeserializeKeymasterNoResponse96 bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
97 };
98
99 struct SetAttestationKeyResponse : public KeymasterNoResponse {};
100
101 struct ClearAttestationCertChainRequest : public keymaster::KeymasterMessage {
ClearAttestationCertChainRequestClearAttestationCertChainRequest102 explicit ClearAttestationCertChainRequest(int32_t ver = keymaster::kDefaultMessageVersion)
103 : KeymasterMessage(ver) {}
104
SerializedSizeClearAttestationCertChainRequest105 size_t SerializedSize() const override { return sizeof(uint32_t); }
SerializeClearAttestationCertChainRequest106 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
107 return keymaster::append_uint32_to_buf(buf, end, algorithm);
108 }
DeserializeClearAttestationCertChainRequest109 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
110 return keymaster::copy_uint32_from_buf(buf_ptr, end, &algorithm);
111 }
112
113 keymaster_algorithm_t algorithm;
114 };
115
116 struct ClearAttestationCertChainResponse : public KeymasterNoResponse {};
117
set_attestation_key_or_cert_bin(uint32_t cmd,keymaster_algorithm_t algorithm,const void * key_data,size_t key_data_size)118 static int set_attestation_key_or_cert_bin(uint32_t cmd, keymaster_algorithm_t algorithm,
119 const void* key_data, size_t key_data_size) {
120 int ret;
121
122 SetAttestationKeyRequest req;
123 req.algorithm = algorithm;
124 req.key_data.Reinitialize(key_data, key_data_size);
125 SetAttestationKeyResponse rsp;
126
127 ret = trusty_keymaster_send(cmd, req, &rsp);
128 if (ret) {
129 fprintf(stderr, "trusty_keymaster_send cmd 0x%x failed %d\n", cmd, ret);
130 return ret;
131 }
132
133 return 0;
134 }
135
set_attestation_key_or_cert_pem(uint32_t cmd,keymaster_algorithm_t algorithm,const xmlChar * pemkey)136 static int set_attestation_key_or_cert_pem(uint32_t cmd, keymaster_algorithm_t algorithm,
137 const xmlChar* pemkey) {
138 int ret;
139 int sslret;
140
141 /* Convert from pem to binary */
142 BIO* bio = BIO_new_mem_buf(pemkey, xmlStrlen(pemkey));
143 if (!bio) {
144 fprintf(stderr, "BIO_new_mem_buf failed\n");
145 ERR_print_errors_fp(stderr);
146 return -1;
147 }
148
149 char* key_name;
150 char* key_header;
151 uint8_t* key;
152 long keylen;
153 sslret = PEM_read_bio(bio, &key_name, &key_header, &key, &keylen);
154 BIO_free(bio);
155
156 if (!sslret) {
157 fprintf(stderr, "PEM_read_bio failed\n");
158 ERR_print_errors_fp(stderr);
159 return -1;
160 }
161
162 /* Send key in binary format to trusty */
163 ret = set_attestation_key_or_cert_bin(cmd, algorithm, key, keylen);
164
165 OPENSSL_free(key_name);
166 OPENSSL_free(key_header);
167 OPENSSL_free(key);
168
169 return ret;
170 }
171
set_attestation_key_or_cert_iecs(uint32_t cmd,keymaster_algorithm_t algorithm,const xmlChar * key_base64)172 static int set_attestation_key_or_cert_iecs(uint32_t cmd, keymaster_algorithm_t algorithm,
173 const xmlChar* key_base64) {
174 int ret;
175 int sslret;
176
177 /* Remove all whitespace. EVP_DecodeBase64 does not support whitespace. */
178 string key_base64_str((const char*)key_base64);
179 key_base64_str.erase(remove_if(key_base64_str.begin(), key_base64_str.end(), isspace),
180 key_base64_str.end());
181
182 /* Convert from base64 to binary */
183 uint8_t* key;
184 size_t keylen;
185 size_t key_base64_len = key_base64_str.length();
186
187 sslret = EVP_DecodedLength(&keylen, key_base64_len);
188 if (!sslret) {
189 fprintf(stderr, "invalid input length, %zu\n", key_base64_len);
190 return -1;
191 }
192 key = (uint8_t*)malloc(keylen);
193 if (!key) {
194 fprintf(stderr, "failed to allocate key, size %zu\n", key_base64_len);
195 return -1;
196 }
197 sslret = EVP_DecodeBase64(key, &keylen, keylen, (const uint8_t*)key_base64_str.data(),
198 key_base64_len);
199 if (!sslret) {
200 fprintf(stderr, "EVP_DecodeBase64 failed\n");
201 ERR_print_errors_fp(stderr);
202 free(key);
203 return -1;
204 }
205
206 /* Send key in binary format to trusty */
207 ret = set_attestation_key_or_cert_bin(cmd, algorithm, key, keylen);
208
209 free(key);
210
211 return ret;
212 }
213
str_to_algorithm(keymaster_algorithm_t * algorithm,const xmlChar * algorithm_str)214 static int str_to_algorithm(keymaster_algorithm_t* algorithm, const xmlChar* algorithm_str) {
215 if (xmlStrEqual(algorithm_str, BAD_CAST "rsa")) {
216 *algorithm = KM_ALGORITHM_RSA;
217 } else if (xmlStrEqual(algorithm_str, BAD_CAST "ecdsa")) {
218 *algorithm = KM_ALGORITHM_EC;
219 } else {
220 printf("unsupported algorithm: %s\n", algorithm_str);
221 return -1;
222 }
223 return 0;
224 }
225
set_attestation_key_or_cert(uint32_t cmd,const xmlChar * algorithm_str,const xmlChar * format,const xmlChar * str)226 static int set_attestation_key_or_cert(uint32_t cmd, const xmlChar* algorithm_str,
227 const xmlChar* format, const xmlChar* str) {
228 int ret;
229 keymaster_algorithm_t algorithm;
230
231 ret = str_to_algorithm(&algorithm, algorithm_str);
232 if (ret) {
233 return ret;
234 }
235
236 if (xmlStrEqual(format, BAD_CAST "pem")) {
237 ret = set_attestation_key_or_cert_pem(cmd, algorithm, str);
238 } else if (xmlStrEqual(format, BAD_CAST "iecs")) {
239 ret = set_attestation_key_or_cert_iecs(cmd, algorithm, str);
240 } else {
241 printf("unsupported key/cert format: %s\n", format);
242 return -1;
243 }
244 return ret;
245 }
246
clear_cert_chain(const xmlChar * algorithm_str)247 static int clear_cert_chain(const xmlChar* algorithm_str) {
248 int ret;
249 ClearAttestationCertChainRequest req;
250 ClearAttestationCertChainResponse rsp;
251
252 ret = str_to_algorithm(&req.algorithm, algorithm_str);
253 if (ret) {
254 return ret;
255 }
256
257 ret = trusty_keymaster_send(KM_CLEAR_ATTESTATION_CERT_CHAIN, req, &rsp);
258 if (ret) {
259 fprintf(stderr, "%s: trusty_keymaster_send failed %d\n", __func__, ret);
260 return ret;
261 }
262 return 0;
263 }
264
process_xml(xmlTextReaderPtr xml)265 static int process_xml(xmlTextReaderPtr xml) {
266 int ret;
267 const xmlChar* algorithm = NULL;
268 const xmlChar* element = NULL;
269 const xmlChar* element_format = NULL;
270
271 while ((ret = xmlTextReaderRead(xml)) == 1) {
272 int nodetype = xmlTextReaderNodeType(xml);
273 const xmlChar *name, *value;
274 name = xmlTextReaderConstName(xml);
275 switch (nodetype) {
276 case XML_READER_TYPE_ELEMENT:
277 element = name;
278 element_format = xmlTextReaderGetAttribute(xml, BAD_CAST "format");
279 if (xmlStrEqual(name, BAD_CAST "Key")) {
280 algorithm = xmlTextReaderGetAttribute(xml, BAD_CAST "algorithm");
281 } else if (xmlStrEqual(name, BAD_CAST "CertificateChain")) {
282 ret = clear_cert_chain(algorithm);
283 if (ret) {
284 fprintf(stderr, "%s, algorithm %s: Clear cert chain cmd failed, %d\n",
285 element, algorithm, ret);
286 return ret;
287 }
288 printf("%s, algorithm %s: Clear cert chain cmd done\n", element, algorithm);
289 }
290 break;
291 case XML_READER_TYPE_TEXT:
292 value = xmlTextReaderConstValue(xml);
293 uint32_t cmd;
294 if (xmlStrEqual(element, BAD_CAST "PrivateKey")) {
295 if (xmlStrEqual(element_format, BAD_CAST "pem")) {
296 cmd = KM_SET_ATTESTATION_KEY;
297 } else if (xmlStrEqual(element_format, BAD_CAST "iecs")) {
298 cmd = KM_SET_WRAPPED_ATTESTATION_KEY;
299 } else {
300 printf("unsupported key format: %s\n", element_format);
301 return -1;
302 }
303 } else if (xmlStrEqual(element, BAD_CAST "Certificate")) {
304 cmd = KM_APPEND_ATTESTATION_CERT_CHAIN;
305 } else {
306 break;
307 }
308
309 ret = set_attestation_key_or_cert(cmd, algorithm, element_format, value);
310 if (ret) {
311 fprintf(stderr, "%s, algorithm %s, format %s: Cmd 0x%x failed, %d\n", element,
312 algorithm, element_format, cmd, ret);
313 return ret;
314 }
315 printf("%s, algorithm %s, format %s: Cmd 0x%x done\n", element, algorithm,
316 element_format, cmd);
317 break;
318 case XML_READER_TYPE_END_ELEMENT:
319 element = NULL;
320 break;
321 }
322 }
323 return ret;
324 }
325
parse_xml_file(const char * filename)326 static int parse_xml_file(const char* filename) {
327 int ret;
328 xmlTextReaderPtr xml = xmlReaderForFile(filename, NULL, 0);
329 if (!xml) {
330 fprintf(stderr, "failed to open %s\n", filename);
331 return -1;
332 }
333
334 ret = process_xml(xml);
335
336 xmlFreeTextReader(xml);
337 if (ret != 0) {
338 fprintf(stderr, "Failed to parse or process %s\n", filename);
339 return -1;
340 }
341
342 return 0;
343 }
344
provision_ids(void)345 static int provision_ids(void) {
346 keymaster::SetAttestationIdsRequest req(4 /* ver */);
347 keymaster::EmptyKeymasterResponse rsp(4 /* ver */);
348
349 req.brand.Reinitialize("trusty", 6);
350 req.device.Reinitialize("trusty", 6);
351 req.product.Reinitialize("trusty", 6);
352 req.manufacturer.Reinitialize("trusty", 6);
353 req.model.Reinitialize("trusty", 6);
354
355 return trusty_keymaster_send(KM_SET_ATTESTATION_IDS, req, &rsp);
356 }
357
main(int argc,char ** argv)358 int main(int argc, char** argv) {
359 int ret = 0;
360
361 parse_options(argc, argv);
362 if (optind + 1 != argc) {
363 print_usage_and_exit(argv[0], EXIT_FAILURE);
364 }
365
366 ret = trusty_keymaster_connect();
367 if (ret) {
368 fprintf(stderr, "trusty_keymaster_connect failed %d\n", ret);
369 return EXIT_FAILURE;
370 }
371
372 ret = parse_xml_file(argv[optind]);
373 if (ret) {
374 fprintf(stderr, "parse_xml_file failed %d\n", ret);
375 trusty_keymaster_disconnect();
376 return EXIT_FAILURE;
377 }
378
379 ret = provision_ids();
380 if (ret) {
381 fprintf(stderr, "provision_ids failed %d\n", ret);
382 trusty_keymaster_disconnect();
383 return EXIT_FAILURE;
384 }
385
386 return EXIT_SUCCESS;
387 }
388