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