Loading trusty/keymaster/Android.bp +33 −0 Original line number Diff line number Diff line Loading @@ -75,3 +75,36 @@ cc_binary { vintf_fragments: ["4.0/android.hardware.keymaster@4.0-service.trusty.xml"], } prebuilt_etc { name: "keymaster_soft_attestation_keys.xml", vendor: true, src: "set_attestation_key/keymaster_soft_attestation_keys.xml", } cc_binary { name: "trusty_keymaster_set_attestation_key", vendor: true, srcs: [ "set_attestation_key/set_attestation_key.cpp", "ipc/trusty_keymaster_ipc.cpp", ], local_include_dirs: ["include"], shared_libs: [ "libc", "libcrypto", "liblog", "libtrusty", "libhardware", "libkeymaster_messages", "libxml2", ], cflags: [ "-Wall", "-Werror", ], } trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h +13 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,19 @@ enum keymaster_command : uint32_t { KM_DELETE_ALL_KEYS = (23 << KEYMASTER_REQ_SHIFT), KM_DESTROY_ATTESTATION_IDS = (24 << KEYMASTER_REQ_SHIFT), KM_IMPORT_WRAPPED_KEY = (25 << KEYMASTER_REQ_SHIFT), // Bootloader/provisioning calls. KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT), KM_SET_ATTESTATION_KEY = (0x2000 << KEYMASTER_REQ_SHIFT), KM_APPEND_ATTESTATION_CERT_CHAIN = (0x3000 << KEYMASTER_REQ_SHIFT), KM_ATAP_GET_CA_REQUEST = (0x4000 << KEYMASTER_REQ_SHIFT), KM_ATAP_SET_CA_RESPONSE_BEGIN = (0x5000 << KEYMASTER_REQ_SHIFT), KM_ATAP_SET_CA_RESPONSE_UPDATE = (0x6000 << KEYMASTER_REQ_SHIFT), KM_ATAP_SET_CA_RESPONSE_FINISH = (0x7000 << KEYMASTER_REQ_SHIFT), KM_ATAP_READ_UUID = (0x8000 << KEYMASTER_REQ_SHIFT), KM_SET_PRODUCT_ID = (0x9000 << KEYMASTER_REQ_SHIFT), KM_CLEAR_ATTESTATION_CERT_CHAIN = (0xa000 << KEYMASTER_REQ_SHIFT), KM_SET_WRAPPED_ATTESTATION_KEY = (0xb000 << KEYMASTER_REQ_SHIFT), }; #ifdef __ANDROID__ Loading trusty/keymaster/set_attestation_key/keymaster_soft_attestation_keys.xml 0 → 100644 +116 −0 Original line number Diff line number Diff line <?xml version="1.0"?> <AndroidAttestation> <NumberOfKeyboxes>10</NumberOfKeyboxes> <Keybox DeviceID="dev1"> <Key algorithm="rsa"> <PrivateKey format="pem"> -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1qEIEir6LR752/q7yXPKb KvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX4YVBeuVKvClqOm21wAQI O2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmdXX0jYvKcXgLocQIDAQAB AoGBAL6GCwuZqAKm+xpZQ4p7txUGWwmjbcbpysxr88AsNNfXnpTGYGQo2Ix7f2V3 wc3qZAdKvo5yht8fCBHclygmCGjeldMu/Ja20IT/JxpfYN78xwPno45uKbqaPF/C woB2tqiWrx0014gozpvdsfNPnJQEQweBKY4gExZyW728mTpBAkEA4cbZJ2RsCRbs NoJtWUmDdAwh8bB0xKGlmGfGaXlchdPcRkxbkp6Uv7NODcxQFLEPEzQat/3V9gQU 0qMmytQcxQJBANpIWZd4XNVjD7D9jFJU+Y5TjhiYOq6ea35qWntdNDdVuSGOvUAy DSg4fXifdvohi8wti2il9kGPu+ylF5qzr70CQFD+/DJklVlhbtZTThVFCTKdk6PY ENvlvbmCKSz3i9i624Agro1X9LcdBThv/p6dsnHKNHejSZnbdvjl7OnA1J0CQBW3 TPJ8zv+Ls2vwTZ2DRrCaL3DS9EObDyasfgP36dH3fUuRX9KbKCPwOstdUgDghX/y qAPpPu6W1iNc6VRCvCECQQCQp0XaiXCyzWSWYDJCKMX4KFb/1mW6moXI1g8bi+5x fs0scurgHa2GunZU1M9FrbXx8rMdn4Eiz6XxpVcPmy0l -----END RSA PRIVATE KEY----- </PrivateKey> <CertificateChain> <NumberOfCertificates>2</NumberOfCertificates> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICtjCCAh+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDAeFw0xNjAxMDQx MjQwNTNaFw0zNTEyMzAxMjQwNTNaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD YWxpZm9ybmlhMRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJv aWQxKTAnBgNVBAMMIEFuZHJvaWQgU29mdHdhcmUgQXR0ZXN0YXRpb24gS2V5MIGf MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1 qEIEir6LR752/q7yXPKbKvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX 4YVBeuVKvClqOm21wAQIO2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmd XX0jYvKcXgLocQIDAQABo2YwZDAdBgNVHQ4EFgQU1AwQG/jNY7n3OVK1DhNcpteZ k4YwHwYDVR0jBBgwFoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wEgYDVR0TAQH/BAgw BgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAni1IX4xn M9waha2Z11Aj6hTsQ7DhnerCI0YecrUZ3GAi5KVoMWwLVcTmnKItnzpPk2sxixZ4 Fg2Iy9mLzICdhPDCJ+NrOPH90ecXcjFZNX2W88V/q52PlmEmT7K+gbsNSQQiis6f 9/VCLiVE+iEHElqDtVWtGIL4QBSbnCBjBH8= -----END CERTIFICATE----- </Certificate> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICpzCCAhCgAwIBAgIJAP+U2d2fB8gMMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW aWV3MRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQwHhcN MTYwMTA0MTIzMTA4WhcNMzUxMjMwMTIzMTA4WjBjMQswCQYDVQQGEwJVUzETMBEG A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMGA1UE CgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMIGfMA0GCSqGSIb3DQEB AQUAA4GNADCBiQKBgQCia63rbi5EYe/VDoLmt5TRdSMfd5tjkWP/96r/C3JHTsAs Q+wzfNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmgMdsGUmX4RFlXYfC78hdL t0GAZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm+Vfkl5YLCazOkjWFmwID AQABo2MwYTAdBgNVHQ4EFgQUKfrxrMxN0kyWQCd1trDpMuUH/i4wHwYDVR0jBBgw FoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAT3LzNlmNDsG5dFsxWfbwjSVJMJ6j HBwp0kUtILlNX2S06IDHeHqcOd6os/W/L3BfRxBcxebrTQaZYdKumgf/93y4q+uc DyQHXrF/unlx/U1bnt8Uqf7f7XzAiF343ZtkMlbVNZriE/mPzsF83O+kqrJVw4Op Lvtc9mL1J1IXvmM= -----END CERTIFICATE----- </Certificate> </CertificateChain> </Key> </Keybox> <Keybox DeviceID="dev1"> <Key algorithm="ecdsa"> <PrivateKey format="pem"> -----BEGIN EC PRIVATE KEY----- MHcCAQEEICHghkMqFRmEWc82OlD8FMnarfk19SfC39ceTW28QuVEoAoGCCqGSM49 AwEHoUQDQgAE6555+EJjWazLKpFMiYbMcK2QZpOCqXMmE/6sy/ghJ0whdJdKKv6l uU1/ZtTgZRBmNbxTt6CjpnFYPts+Ea4QFA== -----END EC PRIVATE KEY----- </PrivateKey> <CertificateChain> <NumberOfCertificates>2</NumberOfCertificates> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICeDCCAh6gAwIBAgICEAEwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMRMw EQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYD VQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQxMzAxBgNVBAMMKkFu ZHJvaWQgS2V5c3RvcmUgU29mdHdhcmUgQXR0ZXN0YXRpb24gUm9vdDAeFw0xNjAx MTEwMDQ2MDlaFw0yNjAxMDgwMDQ2MDlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE CAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdB bmRyb2lkMTswOQYDVQQDDDJBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVz dGF0aW9uIEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOue efhCY1msyyqRTImGzHCtkGaTgqlzJhP+rMv4ISdMIXSXSir+pblNf2bU4GUQZjW8 U7ego6ZxWD7bPhGuEBSjZjBkMB0GA1UdDgQWBBQ//KzWGrE6noEguNUlHMVlux6R qTAfBgNVHSMEGDAWgBTIrel3TEXDo88NFhDkeUM6IVowzzASBgNVHRMBAf8ECDAG AQH/AgEAMA4GA1UdDwEB/wQEAwIChDAKBggqhkjOPQQDAgNIADBFAiBLipt77oK8 wDOHri/AiZi03cONqycqRZ9pDMfDktQPjgIhAO7aAV229DLp1IQ7YkyUBO86fMy9 Xvsiu+f+uXc/WT/7 -----END CERTIFICATE----- </Certificate> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICizCCAjKgAwIBAgIJAKIFntEOQ1tXMAoGCCqGSM49BAMCMIGYMQswCQYDVQQG EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmll dzEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMTMwMQYD VQQDDCpBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVzdGF0aW9uIFJvb3Qw HhcNMTYwMTExMDA0MzUwWhcNMzYwMTA2MDA0MzUwWjCBmDELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEzMDEGA1UEAwwq QW5kcm9pZCBLZXlzdG9yZSBTb2Z0d2FyZSBBdHRlc3RhdGlvbiBSb290MFkwEwYH KoZIzj0CAQYIKoZIzj0DAQcDQgAE7l1ex+HA220Dpn7mthvsTWpdamguD/9/SQ59 dx9EIm29sa/6FsvHrcV30lacqrewLVQBXT5DKyqO107sSHVBpKNjMGEwHQYDVR0O BBYEFMit6XdMRcOjzw0WEOR5QzohWjDPMB8GA1UdIwQYMBaAFMit6XdMRcOjzw0W EOR5QzohWjDPMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMAoGCCqG SM49BAMCA0cAMEQCIDUho++LNEYenNVg8x1YiSBq3KNlQfYNns6KGYxmSGB7AiBN C/NR2TB8fVvaNTQdqEcbY6WFZTytTySn502vQX3xvw== -----END CERTIFICATE----- </Certificate> </CertificateChain> </Key> </Keybox> </AndroidAttestation> trusty/keymaster/set_attestation_key/set_attestation_key.cpp 0 → 100644 +357 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <errno.h> #include <getopt.h> #include <libxml/xmlreader.h> #include <openssl/pem.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/uio.h> #include <unistd.h> #include <string> using std::string; #include <trusty_keymaster/ipc/trusty_keymaster_ipc.h> static const char* _sopts = "h"; static const struct option _lopts[] = { {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}, }; static const char* usage = "Usage: %s [options] xml-file\n" "\n" "options:\n" " -h, --help prints this message and exit\n" "\n"; static void print_usage_and_exit(const char* prog, int code) { fprintf(stderr, usage, prog); exit(code); } static void parse_options(int argc, char** argv) { int c; int oidx = 0; while (1) { c = getopt_long(argc, argv, _sopts, _lopts, &oidx); if (c == -1) { break; /* done */ } switch (c) { case 'h': print_usage_and_exit(argv[0], EXIT_SUCCESS); break; default: print_usage_and_exit(argv[0], EXIT_FAILURE); } } } struct SetAttestationKeyRequest : public keymaster::KeymasterMessage { explicit SetAttestationKeyRequest(int32_t ver = keymaster::MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} size_t SerializedSize() const override { return sizeof(uint32_t) + key_data.SerializedSize(); } uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { buf = keymaster::append_uint32_to_buf(buf, end, algorithm); return key_data.Serialize(buf, end); } bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { return keymaster::copy_uint32_from_buf(buf_ptr, end, &algorithm) && key_data.Deserialize(buf_ptr, end); } keymaster_algorithm_t algorithm; keymaster::Buffer key_data; }; struct KeymasterNoResponse : public keymaster::KeymasterResponse { explicit KeymasterNoResponse(int32_t ver = keymaster::MAX_MESSAGE_VERSION) : keymaster::KeymasterResponse(ver) {} size_t NonErrorSerializedSize() const override { return 0; } uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; } bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; } }; struct SetAttestationKeyResponse : public KeymasterNoResponse {}; struct ClearAttestationCertChainRequest : public keymaster::KeymasterMessage { explicit ClearAttestationCertChainRequest(int32_t ver = keymaster::MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} size_t SerializedSize() const override { return sizeof(uint32_t); } uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { return keymaster::append_uint32_to_buf(buf, end, algorithm); } bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { return keymaster::copy_uint32_from_buf(buf_ptr, end, &algorithm); } keymaster_algorithm_t algorithm; }; struct ClearAttestationCertChainResponse : public KeymasterNoResponse {}; static int set_attestation_key_or_cert_bin(uint32_t cmd, keymaster_algorithm_t algorithm, const void* key_data, size_t key_data_size) { int ret; SetAttestationKeyRequest req; req.algorithm = algorithm; req.key_data.Reinitialize(key_data, key_data_size); SetAttestationKeyResponse rsp; ret = trusty_keymaster_send(cmd, req, &rsp); if (ret) { fprintf(stderr, "trusty_keymaster_send cmd 0x%x failed %d\n", cmd, ret); return ret; } return 0; } static int set_attestation_key_or_cert_pem(uint32_t cmd, keymaster_algorithm_t algorithm, const xmlChar* pemkey) { int ret; int sslret; /* Convert from pem to binary */ BIO* bio = BIO_new_mem_buf(pemkey, xmlStrlen(pemkey)); if (!bio) { fprintf(stderr, "BIO_new_mem_buf failed\n"); ERR_print_errors_fp(stderr); return -1; } char* key_name; char* key_header; uint8_t* key; long keylen; sslret = PEM_read_bio(bio, &key_name, &key_header, &key, &keylen); BIO_free(bio); if (!sslret) { fprintf(stderr, "PEM_read_bio failed\n"); ERR_print_errors_fp(stderr); return -1; } /* Send key in binary format to trusty */ ret = set_attestation_key_or_cert_bin(cmd, algorithm, key, keylen); OPENSSL_free(key_name); OPENSSL_free(key_header); OPENSSL_free(key); return ret; } static int set_attestation_key_or_cert_iecs(uint32_t cmd, keymaster_algorithm_t algorithm, const xmlChar* key_base64) { int ret; int sslret; /* Remove all whitespace. EVP_DecodeBase64 does not support whitespace. */ string key_base64_str((const char*)key_base64); key_base64_str.erase(remove_if(key_base64_str.begin(), key_base64_str.end(), isspace), key_base64_str.end()); /* Convert from base64 to binary */ uint8_t* key; size_t keylen; size_t key_base64_len = key_base64_str.length(); sslret = EVP_DecodedLength(&keylen, key_base64_len); if (!sslret) { fprintf(stderr, "invalid input length, %zu\n", key_base64_len); return -1; } key = (uint8_t*)malloc(keylen); if (!key) { fprintf(stderr, "failed to allocate key, size %zu\n", key_base64_len); return -1; } sslret = EVP_DecodeBase64(key, &keylen, keylen, (const uint8_t*)key_base64_str.data(), key_base64_len); if (!sslret) { fprintf(stderr, "EVP_DecodeBase64 failed\n"); ERR_print_errors_fp(stderr); free(key); return -1; } /* Send key in binary format to trusty */ ret = set_attestation_key_or_cert_bin(cmd, algorithm, key, keylen); free(key); return ret; } static int str_to_algorithm(keymaster_algorithm_t* algorithm, const xmlChar* algorithm_str) { if (xmlStrEqual(algorithm_str, BAD_CAST "rsa")) { *algorithm = KM_ALGORITHM_RSA; } else if (xmlStrEqual(algorithm_str, BAD_CAST "ecdsa")) { *algorithm = KM_ALGORITHM_EC; } else { printf("unsupported algorithm: %s\n", algorithm_str); return -1; } return 0; } static int set_attestation_key_or_cert(uint32_t cmd, const xmlChar* algorithm_str, const xmlChar* format, const xmlChar* str) { int ret; keymaster_algorithm_t algorithm; ret = str_to_algorithm(&algorithm, algorithm_str); if (ret) { return ret; } if (xmlStrEqual(format, BAD_CAST "pem")) { ret = set_attestation_key_or_cert_pem(cmd, algorithm, str); } else if (xmlStrEqual(format, BAD_CAST "iecs")) { ret = set_attestation_key_or_cert_iecs(cmd, algorithm, str); } else { printf("unsupported key/cert format: %s\n", format); return -1; } return ret; } static int clear_cert_chain(const xmlChar* algorithm_str) { int ret; ClearAttestationCertChainRequest req; ClearAttestationCertChainResponse rsp; ret = str_to_algorithm(&req.algorithm, algorithm_str); if (ret) { return ret; } ret = trusty_keymaster_send(KM_CLEAR_ATTESTATION_CERT_CHAIN, req, &rsp); if (ret) { fprintf(stderr, "%s: trusty_keymaster_send failed %d\n", __func__, ret); return ret; } return 0; } static int process_xml(xmlTextReaderPtr xml) { int ret; const xmlChar* algorithm = NULL; const xmlChar* element = NULL; const xmlChar* element_format = NULL; while ((ret = xmlTextReaderRead(xml)) == 1) { int nodetype = xmlTextReaderNodeType(xml); const xmlChar *name, *value; name = xmlTextReaderConstName(xml); switch (nodetype) { case XML_READER_TYPE_ELEMENT: element = name; element_format = xmlTextReaderGetAttribute(xml, BAD_CAST "format"); if (xmlStrEqual(name, BAD_CAST "Key")) { algorithm = xmlTextReaderGetAttribute(xml, BAD_CAST "algorithm"); } else if (xmlStrEqual(name, BAD_CAST "CertificateChain")) { ret = clear_cert_chain(algorithm); if (ret) { fprintf(stderr, "%s, algorithm %s: Clear cert chain cmd failed, %d\n", element, algorithm, ret); return ret; } printf("%s, algorithm %s: Clear cert chain cmd done\n", element, algorithm); } break; case XML_READER_TYPE_TEXT: value = xmlTextReaderConstValue(xml); uint32_t cmd; if (xmlStrEqual(element, BAD_CAST "PrivateKey")) { cmd = KM_SET_ATTESTATION_KEY; } else if (xmlStrEqual(element, BAD_CAST "WrappedPrivateKey")) { cmd = KM_SET_WRAPPED_ATTESTATION_KEY; } else if (xmlStrEqual(element, BAD_CAST "Certificate")) { cmd = KM_APPEND_ATTESTATION_CERT_CHAIN; } else { break; } ret = set_attestation_key_or_cert(cmd, algorithm, element_format, value); if (ret) { fprintf(stderr, "%s, algorithm %s, format %s: Cmd 0x%x failed, %d\n", element, algorithm, element_format, cmd, ret); return ret; } printf("%s, algorithm %s, format %s: Cmd 0x%x done\n", element, algorithm, element_format, cmd); break; case XML_READER_TYPE_END_ELEMENT: element = NULL; break; } } return ret; } static int parse_xml_file(const char* filename) { int ret; xmlTextReaderPtr xml = xmlReaderForFile(filename, NULL, 0); if (!xml) { fprintf(stderr, "failed to open %s\n", filename); return -1; } ret = process_xml(xml); xmlFreeTextReader(xml); if (ret != 0) { fprintf(stderr, "Failed to parse or process %s\n", filename); return -1; } return 0; } int main(int argc, char** argv) { int ret = 0; parse_options(argc, argv); if (optind + 1 != argc) { print_usage_and_exit(argv[0], EXIT_FAILURE); } ret = trusty_keymaster_connect(); if (ret) { fprintf(stderr, "trusty_keymaster_connect failed %d\n", ret); } else { ret = parse_xml_file(argv[optind]); trusty_keymaster_disconnect(); } return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } trusty/trusty-test.mk +2 −0 Original line number Diff line number Diff line Loading @@ -14,3 +14,5 @@ PRODUCT_PACKAGES += \ spiproxyd \ trusty_keymaster_set_attestation_key \ keymaster_soft_attestation_keys.xml \ No newline at end of file Loading
trusty/keymaster/Android.bp +33 −0 Original line number Diff line number Diff line Loading @@ -75,3 +75,36 @@ cc_binary { vintf_fragments: ["4.0/android.hardware.keymaster@4.0-service.trusty.xml"], } prebuilt_etc { name: "keymaster_soft_attestation_keys.xml", vendor: true, src: "set_attestation_key/keymaster_soft_attestation_keys.xml", } cc_binary { name: "trusty_keymaster_set_attestation_key", vendor: true, srcs: [ "set_attestation_key/set_attestation_key.cpp", "ipc/trusty_keymaster_ipc.cpp", ], local_include_dirs: ["include"], shared_libs: [ "libc", "libcrypto", "liblog", "libtrusty", "libhardware", "libkeymaster_messages", "libxml2", ], cflags: [ "-Wall", "-Werror", ], }
trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h +13 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,19 @@ enum keymaster_command : uint32_t { KM_DELETE_ALL_KEYS = (23 << KEYMASTER_REQ_SHIFT), KM_DESTROY_ATTESTATION_IDS = (24 << KEYMASTER_REQ_SHIFT), KM_IMPORT_WRAPPED_KEY = (25 << KEYMASTER_REQ_SHIFT), // Bootloader/provisioning calls. KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT), KM_SET_ATTESTATION_KEY = (0x2000 << KEYMASTER_REQ_SHIFT), KM_APPEND_ATTESTATION_CERT_CHAIN = (0x3000 << KEYMASTER_REQ_SHIFT), KM_ATAP_GET_CA_REQUEST = (0x4000 << KEYMASTER_REQ_SHIFT), KM_ATAP_SET_CA_RESPONSE_BEGIN = (0x5000 << KEYMASTER_REQ_SHIFT), KM_ATAP_SET_CA_RESPONSE_UPDATE = (0x6000 << KEYMASTER_REQ_SHIFT), KM_ATAP_SET_CA_RESPONSE_FINISH = (0x7000 << KEYMASTER_REQ_SHIFT), KM_ATAP_READ_UUID = (0x8000 << KEYMASTER_REQ_SHIFT), KM_SET_PRODUCT_ID = (0x9000 << KEYMASTER_REQ_SHIFT), KM_CLEAR_ATTESTATION_CERT_CHAIN = (0xa000 << KEYMASTER_REQ_SHIFT), KM_SET_WRAPPED_ATTESTATION_KEY = (0xb000 << KEYMASTER_REQ_SHIFT), }; #ifdef __ANDROID__ Loading
trusty/keymaster/set_attestation_key/keymaster_soft_attestation_keys.xml 0 → 100644 +116 −0 Original line number Diff line number Diff line <?xml version="1.0"?> <AndroidAttestation> <NumberOfKeyboxes>10</NumberOfKeyboxes> <Keybox DeviceID="dev1"> <Key algorithm="rsa"> <PrivateKey format="pem"> -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1qEIEir6LR752/q7yXPKb KvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX4YVBeuVKvClqOm21wAQI O2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmdXX0jYvKcXgLocQIDAQAB AoGBAL6GCwuZqAKm+xpZQ4p7txUGWwmjbcbpysxr88AsNNfXnpTGYGQo2Ix7f2V3 wc3qZAdKvo5yht8fCBHclygmCGjeldMu/Ja20IT/JxpfYN78xwPno45uKbqaPF/C woB2tqiWrx0014gozpvdsfNPnJQEQweBKY4gExZyW728mTpBAkEA4cbZJ2RsCRbs NoJtWUmDdAwh8bB0xKGlmGfGaXlchdPcRkxbkp6Uv7NODcxQFLEPEzQat/3V9gQU 0qMmytQcxQJBANpIWZd4XNVjD7D9jFJU+Y5TjhiYOq6ea35qWntdNDdVuSGOvUAy DSg4fXifdvohi8wti2il9kGPu+ylF5qzr70CQFD+/DJklVlhbtZTThVFCTKdk6PY ENvlvbmCKSz3i9i624Agro1X9LcdBThv/p6dsnHKNHejSZnbdvjl7OnA1J0CQBW3 TPJ8zv+Ls2vwTZ2DRrCaL3DS9EObDyasfgP36dH3fUuRX9KbKCPwOstdUgDghX/y qAPpPu6W1iNc6VRCvCECQQCQp0XaiXCyzWSWYDJCKMX4KFb/1mW6moXI1g8bi+5x fs0scurgHa2GunZU1M9FrbXx8rMdn4Eiz6XxpVcPmy0l -----END RSA PRIVATE KEY----- </PrivateKey> <CertificateChain> <NumberOfCertificates>2</NumberOfCertificates> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICtjCCAh+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDAeFw0xNjAxMDQx MjQwNTNaFw0zNTEyMzAxMjQwNTNaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD YWxpZm9ybmlhMRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJv aWQxKTAnBgNVBAMMIEFuZHJvaWQgU29mdHdhcmUgQXR0ZXN0YXRpb24gS2V5MIGf MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1 qEIEir6LR752/q7yXPKbKvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX 4YVBeuVKvClqOm21wAQIO2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmd XX0jYvKcXgLocQIDAQABo2YwZDAdBgNVHQ4EFgQU1AwQG/jNY7n3OVK1DhNcpteZ k4YwHwYDVR0jBBgwFoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wEgYDVR0TAQH/BAgw BgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAni1IX4xn M9waha2Z11Aj6hTsQ7DhnerCI0YecrUZ3GAi5KVoMWwLVcTmnKItnzpPk2sxixZ4 Fg2Iy9mLzICdhPDCJ+NrOPH90ecXcjFZNX2W88V/q52PlmEmT7K+gbsNSQQiis6f 9/VCLiVE+iEHElqDtVWtGIL4QBSbnCBjBH8= -----END CERTIFICATE----- </Certificate> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICpzCCAhCgAwIBAgIJAP+U2d2fB8gMMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW aWV3MRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQwHhcN MTYwMTA0MTIzMTA4WhcNMzUxMjMwMTIzMTA4WjBjMQswCQYDVQQGEwJVUzETMBEG A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMGA1UE CgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMIGfMA0GCSqGSIb3DQEB AQUAA4GNADCBiQKBgQCia63rbi5EYe/VDoLmt5TRdSMfd5tjkWP/96r/C3JHTsAs Q+wzfNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmgMdsGUmX4RFlXYfC78hdL t0GAZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm+Vfkl5YLCazOkjWFmwID AQABo2MwYTAdBgNVHQ4EFgQUKfrxrMxN0kyWQCd1trDpMuUH/i4wHwYDVR0jBBgw FoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAT3LzNlmNDsG5dFsxWfbwjSVJMJ6j HBwp0kUtILlNX2S06IDHeHqcOd6os/W/L3BfRxBcxebrTQaZYdKumgf/93y4q+uc DyQHXrF/unlx/U1bnt8Uqf7f7XzAiF343ZtkMlbVNZriE/mPzsF83O+kqrJVw4Op Lvtc9mL1J1IXvmM= -----END CERTIFICATE----- </Certificate> </CertificateChain> </Key> </Keybox> <Keybox DeviceID="dev1"> <Key algorithm="ecdsa"> <PrivateKey format="pem"> -----BEGIN EC PRIVATE KEY----- MHcCAQEEICHghkMqFRmEWc82OlD8FMnarfk19SfC39ceTW28QuVEoAoGCCqGSM49 AwEHoUQDQgAE6555+EJjWazLKpFMiYbMcK2QZpOCqXMmE/6sy/ghJ0whdJdKKv6l uU1/ZtTgZRBmNbxTt6CjpnFYPts+Ea4QFA== -----END EC PRIVATE KEY----- </PrivateKey> <CertificateChain> <NumberOfCertificates>2</NumberOfCertificates> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICeDCCAh6gAwIBAgICEAEwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMRMw EQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYD VQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQxMzAxBgNVBAMMKkFu ZHJvaWQgS2V5c3RvcmUgU29mdHdhcmUgQXR0ZXN0YXRpb24gUm9vdDAeFw0xNjAx MTEwMDQ2MDlaFw0yNjAxMDgwMDQ2MDlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE CAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdB bmRyb2lkMTswOQYDVQQDDDJBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVz dGF0aW9uIEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOue efhCY1msyyqRTImGzHCtkGaTgqlzJhP+rMv4ISdMIXSXSir+pblNf2bU4GUQZjW8 U7ego6ZxWD7bPhGuEBSjZjBkMB0GA1UdDgQWBBQ//KzWGrE6noEguNUlHMVlux6R qTAfBgNVHSMEGDAWgBTIrel3TEXDo88NFhDkeUM6IVowzzASBgNVHRMBAf8ECDAG AQH/AgEAMA4GA1UdDwEB/wQEAwIChDAKBggqhkjOPQQDAgNIADBFAiBLipt77oK8 wDOHri/AiZi03cONqycqRZ9pDMfDktQPjgIhAO7aAV229DLp1IQ7YkyUBO86fMy9 Xvsiu+f+uXc/WT/7 -----END CERTIFICATE----- </Certificate> <Certificate format="pem"> -----BEGIN CERTIFICATE----- MIICizCCAjKgAwIBAgIJAKIFntEOQ1tXMAoGCCqGSM49BAMCMIGYMQswCQYDVQQG EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmll dzEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMTMwMQYD VQQDDCpBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVzdGF0aW9uIFJvb3Qw HhcNMTYwMTExMDA0MzUwWhcNMzYwMTA2MDA0MzUwWjCBmDELMAkGA1UEBhMCVVMx EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEzMDEGA1UEAwwq QW5kcm9pZCBLZXlzdG9yZSBTb2Z0d2FyZSBBdHRlc3RhdGlvbiBSb290MFkwEwYH KoZIzj0CAQYIKoZIzj0DAQcDQgAE7l1ex+HA220Dpn7mthvsTWpdamguD/9/SQ59 dx9EIm29sa/6FsvHrcV30lacqrewLVQBXT5DKyqO107sSHVBpKNjMGEwHQYDVR0O BBYEFMit6XdMRcOjzw0WEOR5QzohWjDPMB8GA1UdIwQYMBaAFMit6XdMRcOjzw0W EOR5QzohWjDPMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMAoGCCqG SM49BAMCA0cAMEQCIDUho++LNEYenNVg8x1YiSBq3KNlQfYNns6KGYxmSGB7AiBN C/NR2TB8fVvaNTQdqEcbY6WFZTytTySn502vQX3xvw== -----END CERTIFICATE----- </Certificate> </CertificateChain> </Key> </Keybox> </AndroidAttestation>
trusty/keymaster/set_attestation_key/set_attestation_key.cpp 0 → 100644 +357 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <errno.h> #include <getopt.h> #include <libxml/xmlreader.h> #include <openssl/pem.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/uio.h> #include <unistd.h> #include <string> using std::string; #include <trusty_keymaster/ipc/trusty_keymaster_ipc.h> static const char* _sopts = "h"; static const struct option _lopts[] = { {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}, }; static const char* usage = "Usage: %s [options] xml-file\n" "\n" "options:\n" " -h, --help prints this message and exit\n" "\n"; static void print_usage_and_exit(const char* prog, int code) { fprintf(stderr, usage, prog); exit(code); } static void parse_options(int argc, char** argv) { int c; int oidx = 0; while (1) { c = getopt_long(argc, argv, _sopts, _lopts, &oidx); if (c == -1) { break; /* done */ } switch (c) { case 'h': print_usage_and_exit(argv[0], EXIT_SUCCESS); break; default: print_usage_and_exit(argv[0], EXIT_FAILURE); } } } struct SetAttestationKeyRequest : public keymaster::KeymasterMessage { explicit SetAttestationKeyRequest(int32_t ver = keymaster::MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} size_t SerializedSize() const override { return sizeof(uint32_t) + key_data.SerializedSize(); } uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { buf = keymaster::append_uint32_to_buf(buf, end, algorithm); return key_data.Serialize(buf, end); } bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { return keymaster::copy_uint32_from_buf(buf_ptr, end, &algorithm) && key_data.Deserialize(buf_ptr, end); } keymaster_algorithm_t algorithm; keymaster::Buffer key_data; }; struct KeymasterNoResponse : public keymaster::KeymasterResponse { explicit KeymasterNoResponse(int32_t ver = keymaster::MAX_MESSAGE_VERSION) : keymaster::KeymasterResponse(ver) {} size_t NonErrorSerializedSize() const override { return 0; } uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; } bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; } }; struct SetAttestationKeyResponse : public KeymasterNoResponse {}; struct ClearAttestationCertChainRequest : public keymaster::KeymasterMessage { explicit ClearAttestationCertChainRequest(int32_t ver = keymaster::MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} size_t SerializedSize() const override { return sizeof(uint32_t); } uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { return keymaster::append_uint32_to_buf(buf, end, algorithm); } bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { return keymaster::copy_uint32_from_buf(buf_ptr, end, &algorithm); } keymaster_algorithm_t algorithm; }; struct ClearAttestationCertChainResponse : public KeymasterNoResponse {}; static int set_attestation_key_or_cert_bin(uint32_t cmd, keymaster_algorithm_t algorithm, const void* key_data, size_t key_data_size) { int ret; SetAttestationKeyRequest req; req.algorithm = algorithm; req.key_data.Reinitialize(key_data, key_data_size); SetAttestationKeyResponse rsp; ret = trusty_keymaster_send(cmd, req, &rsp); if (ret) { fprintf(stderr, "trusty_keymaster_send cmd 0x%x failed %d\n", cmd, ret); return ret; } return 0; } static int set_attestation_key_or_cert_pem(uint32_t cmd, keymaster_algorithm_t algorithm, const xmlChar* pemkey) { int ret; int sslret; /* Convert from pem to binary */ BIO* bio = BIO_new_mem_buf(pemkey, xmlStrlen(pemkey)); if (!bio) { fprintf(stderr, "BIO_new_mem_buf failed\n"); ERR_print_errors_fp(stderr); return -1; } char* key_name; char* key_header; uint8_t* key; long keylen; sslret = PEM_read_bio(bio, &key_name, &key_header, &key, &keylen); BIO_free(bio); if (!sslret) { fprintf(stderr, "PEM_read_bio failed\n"); ERR_print_errors_fp(stderr); return -1; } /* Send key in binary format to trusty */ ret = set_attestation_key_or_cert_bin(cmd, algorithm, key, keylen); OPENSSL_free(key_name); OPENSSL_free(key_header); OPENSSL_free(key); return ret; } static int set_attestation_key_or_cert_iecs(uint32_t cmd, keymaster_algorithm_t algorithm, const xmlChar* key_base64) { int ret; int sslret; /* Remove all whitespace. EVP_DecodeBase64 does not support whitespace. */ string key_base64_str((const char*)key_base64); key_base64_str.erase(remove_if(key_base64_str.begin(), key_base64_str.end(), isspace), key_base64_str.end()); /* Convert from base64 to binary */ uint8_t* key; size_t keylen; size_t key_base64_len = key_base64_str.length(); sslret = EVP_DecodedLength(&keylen, key_base64_len); if (!sslret) { fprintf(stderr, "invalid input length, %zu\n", key_base64_len); return -1; } key = (uint8_t*)malloc(keylen); if (!key) { fprintf(stderr, "failed to allocate key, size %zu\n", key_base64_len); return -1; } sslret = EVP_DecodeBase64(key, &keylen, keylen, (const uint8_t*)key_base64_str.data(), key_base64_len); if (!sslret) { fprintf(stderr, "EVP_DecodeBase64 failed\n"); ERR_print_errors_fp(stderr); free(key); return -1; } /* Send key in binary format to trusty */ ret = set_attestation_key_or_cert_bin(cmd, algorithm, key, keylen); free(key); return ret; } static int str_to_algorithm(keymaster_algorithm_t* algorithm, const xmlChar* algorithm_str) { if (xmlStrEqual(algorithm_str, BAD_CAST "rsa")) { *algorithm = KM_ALGORITHM_RSA; } else if (xmlStrEqual(algorithm_str, BAD_CAST "ecdsa")) { *algorithm = KM_ALGORITHM_EC; } else { printf("unsupported algorithm: %s\n", algorithm_str); return -1; } return 0; } static int set_attestation_key_or_cert(uint32_t cmd, const xmlChar* algorithm_str, const xmlChar* format, const xmlChar* str) { int ret; keymaster_algorithm_t algorithm; ret = str_to_algorithm(&algorithm, algorithm_str); if (ret) { return ret; } if (xmlStrEqual(format, BAD_CAST "pem")) { ret = set_attestation_key_or_cert_pem(cmd, algorithm, str); } else if (xmlStrEqual(format, BAD_CAST "iecs")) { ret = set_attestation_key_or_cert_iecs(cmd, algorithm, str); } else { printf("unsupported key/cert format: %s\n", format); return -1; } return ret; } static int clear_cert_chain(const xmlChar* algorithm_str) { int ret; ClearAttestationCertChainRequest req; ClearAttestationCertChainResponse rsp; ret = str_to_algorithm(&req.algorithm, algorithm_str); if (ret) { return ret; } ret = trusty_keymaster_send(KM_CLEAR_ATTESTATION_CERT_CHAIN, req, &rsp); if (ret) { fprintf(stderr, "%s: trusty_keymaster_send failed %d\n", __func__, ret); return ret; } return 0; } static int process_xml(xmlTextReaderPtr xml) { int ret; const xmlChar* algorithm = NULL; const xmlChar* element = NULL; const xmlChar* element_format = NULL; while ((ret = xmlTextReaderRead(xml)) == 1) { int nodetype = xmlTextReaderNodeType(xml); const xmlChar *name, *value; name = xmlTextReaderConstName(xml); switch (nodetype) { case XML_READER_TYPE_ELEMENT: element = name; element_format = xmlTextReaderGetAttribute(xml, BAD_CAST "format"); if (xmlStrEqual(name, BAD_CAST "Key")) { algorithm = xmlTextReaderGetAttribute(xml, BAD_CAST "algorithm"); } else if (xmlStrEqual(name, BAD_CAST "CertificateChain")) { ret = clear_cert_chain(algorithm); if (ret) { fprintf(stderr, "%s, algorithm %s: Clear cert chain cmd failed, %d\n", element, algorithm, ret); return ret; } printf("%s, algorithm %s: Clear cert chain cmd done\n", element, algorithm); } break; case XML_READER_TYPE_TEXT: value = xmlTextReaderConstValue(xml); uint32_t cmd; if (xmlStrEqual(element, BAD_CAST "PrivateKey")) { cmd = KM_SET_ATTESTATION_KEY; } else if (xmlStrEqual(element, BAD_CAST "WrappedPrivateKey")) { cmd = KM_SET_WRAPPED_ATTESTATION_KEY; } else if (xmlStrEqual(element, BAD_CAST "Certificate")) { cmd = KM_APPEND_ATTESTATION_CERT_CHAIN; } else { break; } ret = set_attestation_key_or_cert(cmd, algorithm, element_format, value); if (ret) { fprintf(stderr, "%s, algorithm %s, format %s: Cmd 0x%x failed, %d\n", element, algorithm, element_format, cmd, ret); return ret; } printf("%s, algorithm %s, format %s: Cmd 0x%x done\n", element, algorithm, element_format, cmd); break; case XML_READER_TYPE_END_ELEMENT: element = NULL; break; } } return ret; } static int parse_xml_file(const char* filename) { int ret; xmlTextReaderPtr xml = xmlReaderForFile(filename, NULL, 0); if (!xml) { fprintf(stderr, "failed to open %s\n", filename); return -1; } ret = process_xml(xml); xmlFreeTextReader(xml); if (ret != 0) { fprintf(stderr, "Failed to parse or process %s\n", filename); return -1; } return 0; } int main(int argc, char** argv) { int ret = 0; parse_options(argc, argv); if (optind + 1 != argc) { print_usage_and_exit(argv[0], EXIT_FAILURE); } ret = trusty_keymaster_connect(); if (ret) { fprintf(stderr, "trusty_keymaster_connect failed %d\n", ret); } else { ret = parse_xml_file(argv[optind]); trusty_keymaster_disconnect(); } return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }
trusty/trusty-test.mk +2 −0 Original line number Diff line number Diff line Loading @@ -14,3 +14,5 @@ PRODUCT_PACKAGES += \ spiproxyd \ trusty_keymaster_set_attestation_key \ keymaster_soft_attestation_keys.xml \ No newline at end of file