/* * (C) Copyright 2022-2025 * Allwinner Technology Co., Ltd. * * ouyangkun * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #define GEN_WITH_OS 1 #define FINGER_PRIN_MAGIC "vendor_boot.fingerprint" static int __finger_print_searcher(const AvbDescriptor *dh, size_t dest_len, void *args) { switch (be64_to_cpu(dh->tag)) { case AVB_DESCRIPTOR_TAG_PROPERTY: { const AvbPropertyDescriptor *pdh = (const AvbPropertyDescriptor *)dh; const uint8_t *p = (const uint8_t *)dh; const char *name = (char *)(p + 32); const char *value = (char *)(p + sizeof(AvbPropertyDescriptor) + be64_to_cpu(pdh->key_num_bytes) + 1 /*siezof('0')*/); //sunxi_dump((void*)dh, dest_len); // printf("name:%p value:%p namelast:%p", // (void*)name,value,name + be64_to_cpu(pdh->key_num_bytes) - strlen("fingerprint") // ); if (strcmp(name + be64_to_cpu(pdh->key_num_bytes) - strlen(FINGER_PRIN_MAGIC), FINGER_PRIN_MAGIC) == 0) { strcpy(args, value); //printf("get %s\n",(char*)args); return 1; } } default: return 0; } } int sunxi_walk_avb_descriptor(const uint8_t *image_data, size_t image_size, int(call_back)(const AvbDescriptor *descriptor, size_t dest_len, void *args), void *call_back_arg); static int __get_finger_print(char *out_buf) { uint8_t *vb_meta_data; size_t vb_len; //uint8_t finger_print[64]; if (sunxi_avb_read_vbmeta_data(&vb_meta_data, &vb_len) == 0) { if (sunxi_walk_avb_descriptor(vb_meta_data, vb_len, __finger_print_searcher, out_buf) > 0) { //strcpy(out_buf, (char *)finger_print); return 0; } } return -1; } //const char csr[]={ //"hIKpZWJyYW5kZmdvb2dsZWVtb2RlbGdQaXhlbCA2ZmRldmljZWZvcmlvbGVncHJvZHVjdGZvcmlvbGVodmJfc3RhdGVmb3Jhbmdlam9zX3ZlcnNpb25mMTMwMDAwbG1hbnVmYWN0dXJlcmZHb29nbGVwYm9vdGxvYWRlcl9zdGF0ZWh1bmxvY2tlZHJzeXN0ZW1fcGF0Y2hfbGV2ZWwaAAMV4KBQXMG8+LLov47bvQ0U8e3nloRDoQEDoQVMJwEBon7ESYLioDuzWQE+FEKdZZx+Wf7862CoWHCENzFBr557mz8aUbOJQ1Q7+/ORQthAEuAfZWwwqR7BtO4MItNDUrm+XqC1wlGZvejLmqoolEYjdOb/ZuSvmt0vJR+w9o4ef2+lCwQjNc1FjoQarA2Xj+c+UTKHav8WPQ3zVMCFfUp1YsiTTFakhu6lipTidrxT1HicE0Y8i0A1xGrxw0GGv52PiAwYOOMlgkcG92OASdlXassbq21C2+EKef9nTjHwY3EbkYyi2D4WfrrXeOfwkap+is1K4y84jlwr75VNJmDXAOqw6lRVALLsjBJxKO3sFhi6Md89OJoFZCa07h3+U0q2I6O3vnfhn3WXE8/9aQK9FT4oaH/IOdZyC/2uUbJZzDPDuPkWSn8A8H9bGwlqleexwIZGTMFzH001nm3hFfVL+t+yXTTfbTgigYNEoQE4GKIEWCDQrsEVyirPc65rzMvRlh1l6LHd10oaN7lDOpfVmd+YCCCjAQEgBCFYIMkS8o+9w9iUXs/egFUs8OSluuDBbxD7Cg/ovLP/I3Nc9oRAoPZYIGT+j4ZxERFPaWnRQlH99R06tFBctTjoqo2fjVAILjdO" //}; char *uploaded_csr; void base64_csr_generate(char *out); int key_extraction_output_generate(char *out, size_t out_size) { char fp_buf[128]; __maybe_unused char base64_csr[4096]; char tmp_csr[4096]; char *active_csr; int tmp_csr_len; int ret; //cache if (uploaded_csr) { strcpy(out, uploaded_csr); return 0; } memset(tmp_csr, 0, sizeof(tmp_csr)); uploaded_csr = malloc(4096); //get finger print if (__get_finger_print(fp_buf)) { pr_err("get fingerprint fail"); return -1; } pr_err("get fingerprint %s\n", fp_buf); //csr may from android or generate in place ret = sunxi_secure_object_read("kRkpCsr", tmp_csr, 4096, &tmp_csr_len); if (ret < 0) { #if SUNXI_RKP_FROM_UBOOT printf("read csr from android fail, use fall back\n"); memset(base64_csr, 0, sizeof(base64_csr)); base64_csr_generate(base64_csr); active_csr = base64_csr; #else printf("read csr from android fail\n"); return -1; #endif } else { active_csr = tmp_csr; } strncpy(out, "{\"build_fingerprint\":\"", out_size - 1); strncat(out, fp_buf, out_size - strlen(out) - 1); strncat(out, "\",\"csr\":\"", out_size - strlen(out) - 1); strncat(out, active_csr, out_size - strlen(out) - 1); strncat(out, "\",\"name\":\"default\" }", out_size - strlen(out) - 1); //"{\"build_fingerprint\":\"fp_buf\",\"csr\":\"active_csr\",\"name\":\"default\" }" //save csr cache strcpy(uploaded_csr, out); return 0; } #if SUNXI_RKP_FROM_UBOOT #define CHAR_BIT 8 #define _GCC_STDINT_H #include #include "mbedtls/hkdf.h" #include "mbedtls/ecdh.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/ecp.h" #include "mbedtls/error.h" #include "mbedtls/gcm.h" #include "mbedtls/base64.h" extern struct ecc_key_t dk; #if 1 // crypto base struct ecc_key_t { uint8_t private[32]; uint8_t qx[32]; uint8_t qy[32]; int isX25519; }; #pragma pack(push) #pragma pack(1) struct device_info_set_param { uint32_t type; char info[16]; //len is not important, left space in buffer will be used }; struct rkp_protected_gen_param { uint8_t mac_key[32]; uint8_t mac_tag[32]; uint8_t challenge[32]; uint32_t challenge_size; uint32_t out_size; //len is not important, left space in buffer will be used uint8_t out_buffer[256]; }; #pragma pack(pop) enum DEVICE_INFO_TYPE_E { //string DEVICE_ID_BRAND, DEVICE_ID_DEVICE, DEVICE_ID_PRODUCT, DEVICE_ID_SERIAL, DEVICE_ID_MANUFACTURER, DEVICE_ID_MODEL, DEVICE_ID_COUNT, //int DEVICE_INFO_OS_VER = 32, DEVICE_INFO_OS_PATCH, DEVICE_INFO_BOOT_PATCH, DEVICE_INFO_VENDOR_PATCH, }; enum RKP_SUMCMD_E { RKP_SET_INFO = 1, RKP_GEN_PROTECTED_DATA_PAYLOAD = 2, RKP_GEN_DEVICE_INFO = 3, }; int smc_tee_rkp_op(int sub_cmd, void *input, size_t input_size, void *output); static void __prepare_device_info(void) { uint32_t tmp; struct device_info_set_param info; memset(&info, 0, sizeof(info)); info.type = DEVICE_ID_BRAND; strcpy(info.info, "Allwinner"); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); memset(&info, 0, sizeof(info)); info.type = DEVICE_ID_MODEL; strcpy(info.info, "DUMMY"); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); memset(&info, 0, sizeof(info)); info.type = DEVICE_ID_PRODUCT; strcpy(info.info, "DUMMY"); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); memset(&info, 0, sizeof(info)); info.type = DEVICE_ID_DEVICE; strcpy(info.info, "DUMMY"); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); memset(&info, 0, sizeof(info)); info.type = DEVICE_ID_MANUFACTURER; strcpy(info.info, "allwinner"); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); memset(&info, 0, sizeof(info)); info.type = DEVICE_INFO_OS_VER; tmp = 130000; memcpy(info.info, &tmp, 4); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); memset(&info, 0, sizeof(info)); info.type = DEVICE_INFO_OS_PATCH; tmp = 0; memcpy(info.info, &tmp, 4); smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); info.type = DEVICE_INFO_VENDOR_PATCH; smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); info.type = DEVICE_INFO_OS_PATCH; smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); info.type = DEVICE_INFO_BOOT_PATCH; smc_tee_rkp_op(RKP_SET_INFO, &info, sizeof(info), NULL); } static void __prepare_verify_boot_data(void) { uint8_t hash[32]; sunxi_set_verify_boot_number(SUNXI_VB_INFO_LOCK, 1); sunxi_set_verify_boot_number(SUNXI_VB_INFO_BOOTSTATE, KM_VERIFIED_BOOT_VERIFIED); memset(hash, 0, 32); sunxi_set_verify_boot_blob(SUNXI_VB_INFO_HASH, hash, 32); sunxi_keymaster_verify_boot_params_install(); } static int myrand(void *rng_state, unsigned char *output, size_t len) { u8 tmp_buf[32]; u8 *p = output; u8 tmp_len; if (rng_state != NULL) rng_state = NULL; while (len) { tmp_len = len > 32 ? 32 : len; sunxi_trng_gen(tmp_buf, 32); memcpy(p, tmp_buf, tmp_len); p += 32; len -= tmp_len; } return 0; } static int ecc_sign(uint8_t *input, uint8_t *random, const struct ecc_curve_param_t *ecc_param, uint8_t *private, struct ecc_signature_t *signature) { sunxi_ecc_sign(input, random, &p256_param, private, signature); return 0; } static int __hash(uint8_t *input, size_t input_len, uint8_t *output) { sunxi_sha_calc(output, 32, input, input_len); return 0; } static void __rsa_padding(u8 *dst_buf, u8 *src_buf, u32 data_len, u32 group_len) { int i = 0; memset(dst_buf, 0, group_len); for (i = group_len - data_len; i < group_len; i++) { dst_buf[i] = src_buf[group_len - 1 - i]; } } static int sign(uint8_t *input, size_t input_size, uint8_t *private, uint8_t *output) { struct ecc_signature_t sig; uint8_t hash[32]; uint8_t le_input[32]; uint8_t random[32]; __hash(input, input_size, hash); myrand(NULL, random, 32); //pc treat input(hash) as big-enden __rsa_padding(le_input, hash, 32, 32); ecc_sign(le_input, random, &p256_param, private, &sig); __rsa_padding(output, sig.r, 32, 32); __rsa_padding(output + 32, sig.s, 32, 32); return 0; } static int hmac(uint8_t *input, uint8_t *key, uint8_t *output, size_t size) { mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), key, 32, input, size, output); return 0; } static int x25519_pair_gen(struct ecc_key_t *key) { mbedtls_ecdh_context ctx_cli; mbedtls_ecdh_init(&ctx_cli); mbedtls_ecp_group_load(&ctx_cli.grp, MBEDTLS_ECP_DP_CURVE25519); mbedtls_ecdh_gen_public(&ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q, myrand, NULL); mbedtls_mpi_write_binary_le(&ctx_cli.d, key->private, 32); mbedtls_mpi_write_binary_le(&ctx_cli.Q.X, key->qx, 32); key->isX25519 = 1; return 0; } static int __aes_gcm(uint8_t *aes_key, uint8_t *iv, uint8_t *in, uint8_t *out, size_t input_len, uint8_t *aad, size_t aad_len) { mbedtls_gcm_context gcm_ctx; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; mbedtls_gcm_init(&gcm_ctx); mbedtls_gcm_setkey(&gcm_ctx, cipher, aes_key, 256); mbedtls_gcm_crypt_and_tag(&gcm_ctx, MBEDTLS_GCM_ENCRYPT, input_len, iv, 12, aad, aad_len, in, out, 16, &out[input_len]); return 0; } static inline int DiceKdf(size_t length, const uint8_t *ikm, size_t ikm_size, const uint8_t *salt, size_t salt_size, const uint8_t *info, size_t info_size, uint8_t *output) { ALLOC_CACHE_ALIGN_BUFFER(u8, prk_key, ALIGN(64, CACHE_LINE_SIZE)); u8 prk[64]; memset(prk_key, 0, 64); memset(prk, 0, 64); sunxi_sha_calc(prk_key, 32, (void *)salt, salt_size); hmac((void *)ikm, prk_key, prk, 32); hmac((void *)info, prk, output, 32); return 0; } static const uint8_t kAsymSalt[] = { 0x63, 0xB6, 0xA0, 0x4D, 0x2C, 0x07, 0x7F, 0xC1, 0x0F, 0x63, 0x9F, 0x21, 0xDA, 0x79, 0x38, 0x44, 0x35, 0x6C, 0xC2, 0xB0, 0xB4, 0x41, 0xB3, 0xA7, 0x71, 0x24, 0x03, 0x5C, 0x03, 0xF8, 0xE1, 0xBE, 0x60, 0x35, 0xD3, 0x1F, 0x28, 0x28, 0x21, 0xA7, 0x45, 0x0A, 0x02, 0x22, 0x2A, 0xB1, 0xB3, 0xCF, 0xF1, 0x67, 0x9B, 0x05, 0xAB, 0x1C, 0xA5, 0xD1, 0xAF, 0xFB, 0x78, 0x9C, 0xCD, 0x2B, 0x0B, 0x3B }; static const size_t kAsymSaltSize = 64; int private_gen(uint8_t *input, size_t input_len, uint8_t *private) { ALLOC_CACHE_ALIGN_BUFFER(u8, tmp_salt, ALIGN(64, CACHE_LINE_SIZE)); u8 info[] = "key Pair"; memcpy(tmp_salt, kAsymSalt, 64); DiceKdf(32, input, input_len, tmp_salt, kAsymSaltSize, info, 8, private); return 0; } #endif #if 1 // keys struct ecc_key_t google = { .private = {0},// not used .qx = { 0xbe, 0x85, 0xe7, 0x46, 0xc4, 0xa3, 0x42, 0x5a, 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c, 0x58, 0x7e, 0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f, 0x72, 0x60, }, //x25519 have qx only .qy = {0}, .isX25519 = 1 }; struct ecc_key_t dk = { .private = { 0 }, .qx = { 1 }, .qy = { 2 } }; struct ecc_key_t ephemeral = { .private = { 0 }, .qx = { 0 }, .qy = { 0 } }; uint8_t google_eek_id[32] = { 0xD0, 0xAE, 0xC1, 0x15, 0xCA, 0x2A, 0xCF, 0x73, 0xAE, 0x6B, 0xCC, 0xCB, 0xD1, 0x96, 0x1D, 0x65, 0xE8, 0xB1, 0xDD, 0xD7, 0x4A, 0x1A, 0x37, 0xB9, 0x43, 0x3A, 0x97, 0xD5, 0x99, 0xDF, 0x98, 0x08 }; uint8_t ephemeral_mac_key[32]; #endif int fill_context(struct CborOut *cout); int fill_context(struct CborOut *cout) { // Context = [ // AlgorithmID : 3 // AES-GCM 256 // PartyUInfo : [ // identity : bstr "client" // nonce : bstr .size 0, // other : bstr // Ephemeral_pub // ], // PartyVInfo : [ // identity : bstr "server", // nonce : bstr .size 0, // other : bstr // EEK pubkey // ], // SuppPubInfo : [ // 256, // Output key length // protected : bstr .size 0 // ] // ] int before = CborOutSize(cout); uint8_t *p; CborWriteArray(4, cout); //algo id CborWriteUint(3, cout); //u info CborWriteArray(3, cout); CborWriteBstr(strlen("client"), (uint8_t *)"client", cout); CborWriteBstr(0, cout->buffer, cout); //u->ephemeral_pub #if 0 p = CborAllocBstr(64, cout); memcpy(p, ephemeral.qx, 32); memcpy(p+32, ephemeral.qy, 32); #else p = CborAllocBstr(32, cout); memcpy(p, ephemeral.qx, 32); #endif //i info CborWriteArray(3, cout); CborWriteBstr(strlen("server"), (uint8_t *)"server", cout); CborWriteBstr(0, cout->buffer, cout); //i->eek pub #if 0 p = CborAllocBstr(64, cout); memcpy(p, google.qx, 32); memcpy(p+32, google.qy, 32); #else p = CborAllocBstr(32, cout); memcpy(p, google.qx, 32); #endif //pub info CborWriteArray(2, cout); CborWriteUint(256, cout); CborWriteBstr(0, cout->buffer, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_deviceinfo(struct CborOut *cout) { // DeviceInfo = { // "brand" : tstr, // "manufacturer" : tstr, // "product" : tstr, // "model" : tstr, // "device" : tstr, // "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values // "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values // "vbmeta_digest": bstr, // Taken from the AVB values // ? "os_version" : tstr, // Same as // // android.os.Build.VERSION.release // // Not optional for TEE. // "system_patch_level" : uint, // YYYYMMDD // "boot_patch_level" : uint, // YYYYMMDD // "vendor_patch_level" : uint, // YYYYMMDD // "version" : 2, // The CDDL schema version. // "security_level" : "tee" / "strongbox", // "fused": 1 / 0, // 1 if secure boot is enforced for the processor that the IRPC // // implementation is contained in. 0 otherwise. // } int before = CborOutSize(cout); #if GEN_WITH_OS uint8_t buf[4096]; struct rkp_protected_gen_param param; smc_tee_rkp_op(RKP_GEN_DEVICE_INFO, ¶m, sizeof(param), buf); struct rkp_protected_gen_param *generated = (struct rkp_protected_gen_param *)buf; #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(generated->out_buffer, generated->out_size); #endif //cbor write API do not support attach a complete cbor //object, we got to do some hanking here. modifying cout //directory instead of throungh APIs if (cout->buffer_size >= cout->cursor + generated->out_size) { memcpy(&cout->buffer[cout->cursor], generated->out_buffer, generated->out_size); cout->cursor += generated->out_size; } #else uint8_t empty_digest[32] = { 0 }; CborWriteMap(15, cout); //brand(str) CborWriteTstr("brand", cout); CborWriteTstr("Allwinner", cout); //fused(uint) CborWriteTstr("fused", cout); CborWriteUint(0, cout); //model(str) CborWriteTstr("model", cout); CborWriteTstr("DUMMY", cout); //device(str) CborWriteTstr("device", cout); CborWriteTstr("DUMMY", cout); //product(str) CborWriteTstr("product", cout); CborWriteTstr("DUMMY", cout); //version(uint) CborWriteTstr("version", cout); CborWriteUint(2, cout); //vb_state(str) CborWriteTstr("vb_state", cout); CborWriteTstr("green", cout); //os_version(str) CborWriteTstr("os_version", cout); CborWriteTstr("130000", cout); //manufacturer(str) CborWriteTstr("manufacturer", cout); CborWriteTstr("allwinner", cout); //vbmeta_digest(bytes) CborWriteTstr("vbmeta_digest", cout); CborWriteBstr(32, empty_digest, cout); //security_level(str) CborWriteTstr("security_level", cout); CborWriteTstr("tee", cout); //boot_patch_level(uint) CborWriteTstr("boot_patch_level", cout); CborWriteUint(0, cout); //bootloader_state(str) CborWriteTstr("bootloader_state", cout); CborWriteTstr("locked", cout); //system_patch_level(uint) CborWriteTstr("system_patch_level", cout); CborWriteUint(0, cout); //vendor_patch_level(uint) CborWriteTstr("vendor_patch_level", cout); CborWriteUint(0, cout); #if 0 //compare uint8_t tmp_plain_text2[4096]; struct rkp_protected_gen_param param1; smc_tee_rkp_op(RKP_GEN_DEVICE_INFO, ¶m1, sizeof(param1), tmp_plain_text2); struct rkp_protected_gen_param *generated1 = (struct rkp_protected_gen_param *)tmp_plain_text2; printf("\n%s:\n", __func__); sunxi_dump(generated1->out_buffer, generated1->out_size); printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif #endif #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_p256_pubkey(struct CborOut *cout, uint8_t *px, uint8_t *py, int isDh) { // PubKeyEcdhP256 = { // COSE_Key // 1 : 2, // Key type : EC2 // -1 : 1, // Curve : P256 // -2 : bstr // Sender X coordinate // -3 : bstr // Sender Y coordinate // } // // PubKeyECDSA256 = { // COSE_Key // 1 : 2, // Key type : EC2 // 3 : AlgorithmES256, // Algorithm : ECDSA w/ SHA-256 // -1 : 1, // Curve: P256 // -2 : bstr, // X coordinate // -3 : bstr // Y coordinate // } int before = CborOutSize(cout); CborWriteMap(4 + (isDh ? 0 : 1), cout); //key type CborWriteUint(1, cout); CborWriteUint(2, cout); //algorithm if (!isDh) { // AlgorithmES256 = -7 CborWriteUint(3, cout); CborWriteInt(-7, cout); } //curve CborWriteInt(-1, cout); CborWriteUint(1, cout); //x CborWriteInt(-2, cout); CborWriteBstr(32, px, cout); //y CborWriteInt(-3, cout); CborWriteBstr(32, py, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_x25519_pubkey(struct CborOut *cout, struct ecc_key_t *key, int isDh) { // PubKeyX25519 = { // COSE_Key // 1 : 1, // Key type : Octet Key Pair // -1 : 4, // Curve : X25519 // -2 : bstr // Sender X25519 public key // } // // PubKeyEd25519 = { // COSE_Key // 1 : 1, // Key type : octet key pair // 3 : AlgorithmEdDSA, // Algorithm : EdDSA // -1 : 6, // Curve : Ed25519 // -2 : bstr // X coordinate, little-endian // } int before = CborOutSize(cout); CborWriteMap(3 + (isDh ? 0 : 1), cout); //key type CborWriteUint(1, cout); CborWriteUint(1, cout); //curve CborWriteInt(-1, cout); CborWriteUint(4, cout); //x CborWriteInt(-2, cout); CborWriteBstr(32, key->qx, cout); //algorithm if (!isDh) { // AlgorithmEdDSA = -8 CborWriteUint(3, cout); CborWriteInt(-8, cout); } #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_pub_key(struct CborOut *cout, struct ecc_key_t *key, int isDh) { if (key->isX25519) { return fill_x25519_pubkey(cout, key, isDh); } else { return fill_p256_pubkey(cout, key->qx, key->qy, isDh); } } int fill_protected_algo(struct CborOut *cout) { int before = CborOutSize(cout); uint8_t tmp_pro[4096]; struct CborOut protected; CborOutInit(tmp_pro, 4096, &protected); CborWriteMap(1, &protected); CborWriteInt(1, &protected); CborWriteInt(-7, &protected); CborWriteBstr(CborOutSize(&protected), tmp_pro, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_cose_sign_struct(struct CborOut *cout, uint8_t *payload, size_t payload_len, uint8_t *aad, size_t aad_len) { int before = CborOutSize(cout); CborWriteArray(4, cout); CborWriteTstr("Signature1", cout); fill_protected_algo(cout); CborWriteBstr(aad_len, aad, cout); CborWriteBstr(payload_len, payload, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int cose_sign(uint8_t *payload, size_t payload_len, uint8_t *aad, size_t aad_len, uint8_t *private, uint8_t *signature) { uint8_t tmp_sign[4096]; struct CborOut csign; fill_cose_sign_struct(&csign, payload, payload_len, aad, aad_len); sign(tmp_sign, CborOutSize(&csign), private, signature); return 0; } int gen_signed_mac_signature(uint8_t *signature, uint8_t *challenge, uint8_t *mac_tag) { // SignedMac_structure = [ // COSE Sig_structure // "Signature1", // bstr .cbor { // Protected params // 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm // }, // bstr .cbor SignedMacAad, // bstr .size 32 // MAC key // ] // SignedMacAad = [ // challenge : bstr .size (32..64), // Size between 32 - 64 // // bytes inclusive // VerifiedDeviceInfo, // tag: bstr // This is the tag from COSE_Mac0 of // // KeysToCertify, to tie the key set to // // the signature. // ] // VerifiedDeviceInfo = DeviceInfo // See DeviceInfo.aidl uint8_t tmp_aad[4096]; struct CborOut aad; //aad CborOutInit(tmp_aad, 4096, &aad); CborWriteArray(3, &aad); CborWriteBstr(16, challenge, &aad); //CborWriteBstr(CborOutSize(&info), info.buffer, &aad); fill_deviceinfo(&aad); CborWriteBstr(32, mac_tag, &aad); ALLOC_CACHE_ALIGN_BUFFER(u8, tmp_mac_struct, 4096); struct CborOut mac_struct; CborOutInit(tmp_mac_struct, 4096, &mac_struct); fill_cose_sign_struct(&mac_struct, ephemeral_mac_key, 32, tmp_aad, CborOutSize(&aad)); sign(tmp_mac_struct, CborOutSize(&mac_struct), dk.private, signature); return 0; } int fill_signed_mac(struct CborOut *cout, uint8_t *challenge, uint8_t *mac_tag) { // SignedMac = [ // COSE_Sign1 // bstr .cbor { // Protected params // 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm // }, // {}, // Unprotected params // bstr .size 32, // Payload: MAC key // bstr // PureEd25519(KM_priv, bstr .cbor SignedMac_structure) / // // ECDSA(KM_priv, bstr .cbor SignedMac_structure) // ] int before = CborOutSize(cout); CborWriteArray(4, cout); //protected fill_protected_algo(cout); //unprotected CborWriteMap(0, cout); //mac key CborWriteBstr(32, ephemeral_mac_key, cout); // signature uint8_t *fill; fill = CborAllocBstr(64, cout); gen_signed_mac_signature(fill, challenge, mac_tag); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_bcc_payload(struct CborOut *cout) { // BccPayload = { // CWT [RFC8392] // 1 : tstr, // Issuer // 2 : tstr, // Subject // -4670552 : bstr .cbor PubKeyEd25519 / // bstr .cbor PubKeyECDSA256, // Subject Public Key // -4670553 : bstr // Key Usage // // // NOTE: All of the following fields may be omitted for a "Degenerate BCC", as // // described by IRemotelyProvisionedComponent.aidl. // -4670545 : bstr, // Code Hash // ? -4670546 : bstr, // Code Descriptor // ? -4670547 : bstr, // Configuration Hash // -4670548 : bstr .cbor { // Configuration Descriptor // ? -70002 : tstr, // Component name // ? -70003 : int, // Firmware version // ? -70004 : null, // Resettable // }, // -4670549 : bstr, // Authority Hash // ? -4670550 : bstr, // Authority Descriptor // -4670551 : bstr, // Mode // } int before = CborOutSize(cout); const uint8_t mode[1] = { 0x01 }; struct CborOut tmp; uint8_t tmp_buffer[4096]; CborWriteMap(8, cout); //issuer CborWriteUint(1, cout); CborWriteTstr("DEVICE_KEY", cout); //subject CborWriteUint(2, cout); CborWriteTstr("DEVICE_KEY", cout); //pub CborOutInit(tmp_buffer, 4096, &tmp); fill_p256_pubkey(&tmp, dk.qx, dk.qy, 0); CborWriteInt(-4670552, cout); CborWriteBstr(CborOutSize(&tmp), tmp_buffer, cout); //key usage CborWriteInt(-4670553, cout); CborWriteBstr(1, (uint8_t *)" ", cout); //code hash CborWriteInt(-4670545, cout); CborWriteBstr(32, dk.qx, cout); //configuration descriptor CborOutInit(tmp_buffer, 4096, &tmp); CborWriteMap(2, &tmp); CborWriteInt(-70002, &tmp); CborWriteTstr("TEE", &tmp); CborWriteInt(-70003, &tmp); CborWriteUint(0, &tmp); CborWriteInt(-4670548, cout); CborWriteBstr(CborOutSize(&tmp), tmp_buffer, cout); //authority hash CborWriteInt(-4670549, cout); CborWriteBstr(32, dk.qx, cout); //mode CborWriteInt(-4670551, cout); CborWriteBstr(1, mode, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_bcc_entry_input(struct CborOut *cout) { // BccEntryInput = [ // context: "Signature1", // protected: bstr .cbor { // 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm // }, // external_aad: bstr .size 0, // payload: bstr .cbor BccPayload // ] int before = CborOutSize(cout); CborWriteArray(4, cout); //context CborWriteTstr("Signature1", cout); //protected fill_protected_algo(cout); //external_aad CborWriteBstr(0, dk.qx, cout); //payload fill_bcc_payload(cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_bcc_entry(struct CborOut *cout) { // BccEntry = [ // COSE_Sign1 (untagged) // protected : bstr .cbor { // 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm // }, // unprotected: {}, // payload: bstr .cbor BccPayload, // signature: bstr // PureEd25519(SigningKey, bstr .cbor BccEntryInput) / // // ECDSA(SigningKey, bstr .cbor BccEntryInput) // // See RFC 8032 for details of how to encode the signature value for Ed25519. // ] int before = CborOutSize(cout); uint8_t tmp_entry_input[4096], *psign; struct CborOut entry_input; CborOutInit(tmp_entry_input, 4096, &entry_input); uint8_t payload_buf[1024]; struct CborOut payload; CborOutInit(payload_buf, 1024, &payload); fill_bcc_payload(&payload); CborWriteArray(4, cout); //protected fill_protected_algo(cout); //unprotected CborWriteMap(0, cout); //payload CborWriteBstr(CborOutSize(&payload), payload_buf, cout); //signature psign = CborAllocBstr(64, cout); ALLOC_CACHE_ALIGN_BUFFER(u8, tmp_sign_struct, 4096); struct CborOut mac_struct; CborOutInit(tmp_sign_struct, 4096, &mac_struct); fill_cose_sign_struct(&mac_struct, payload_buf, CborOutSize(&payload), payload_buf /*0 len, any thing*/, 0); sign(tmp_sign_struct, CborOutSize(&mac_struct), dk.private, psign); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_bcc(struct CborOut *cout) { // Bcc = [ // PubKeyEd25519 / PubKeyECDSA256, // DK_pub // + BccEntry, // Root -> leaf (KM_pub) // ] int before = CborOutSize(cout); CborWriteArray(2, cout); fill_p256_pubkey(cout, dk.qx, dk.qy, 0); fill_bcc_entry(cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_protected_data_payload_plaintext(struct CborOut *cout, uint8_t *challenge, uint8_t *mac_tag) { // ProtectedDataPayload [ // SignedMac, // Bcc, // ? AdditionalDKSignatures, // ] int before = CborOutSize(cout); CborWriteArray(2, cout); fill_signed_mac(cout, challenge, mac_tag); fill_bcc(cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_recipients(struct CborOut *cout) { // recipients : [ // [ // COSE_Recipient // protected : bstr .cbor { // 1 : -25 // Algorithm : ECDH-ES + HKDF-256 // }, // unprotected : { // -1 : PubKeyX25519 / PubKeyEcdhP256 // Ephemeral_pub // 4 : bstr, // KID : EEK ID // }, // ciphertext : nil // ] int before = CborOutSize(cout); uint8_t protected[] = { 0xA1, 0x01, 0x38, 0x18 }; CborWriteArray(1, cout); CborWriteArray(3, cout); //protected CborWriteBstr(sizeof(protected), protected, cout); //unprotected CborWriteMap(2, cout); //eek in unprotected CborWriteUint(4, cout); CborWriteBstr(sizeof(google_eek_id), google_eek_id, cout); //pubkey in unprotected CborWriteInt(-1, cout); fill_pub_key(cout, &ephemeral, 1); //ciphertext CborWriteNull(cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } void protected_data_encrypted(uint8_t *iv, uint8_t *in, size_t input_len, uint8_t *out); int fill_protected_data(struct CborOut *cout, uint8_t *mac_key, uint8_t *challenge, uint8_t *mac_tag) { int before = CborOutSize(cout); uint8_t protected[] = { 0xA1, 0x01, 0x03 }; uint8_t iv[32] = { 0 }; uint8_t *cipher; CborWriteArray(4, cout); //protected (constant) CborWriteBstr(sizeof(protected), protected, cout); //unprotected CborWriteMap(1, cout); CborWriteUint(5, cout); myrand(NULL, iv, 12); CborWriteBstr(12, iv, cout); #if 0 //compare uint8_t tmp_plain_text1[4096]; struct CborOut plain_text1; CborOutInit(tmp_plain_text1, 4096, &plain_text1); fill_protected_data_payload_plaintext(&plain_text1, challenge, mac_tag); sunxi_dump(tmp_plain_text1, CborOutSize(&plain_text1)); uint8_t tmp_plain_text2[4096]; struct rkp_protected_gen_param param1; memcpy(param1.challenge, challenge, 16); param1.challenge_size = 16; memcpy(param1.mac_key, ephemeral_mac_key, 32); memcpy(param1.mac_tag, mac_tag, 32); smc_tee_rkp_op(RKP_GEN_PROTECTED_DATA_PAYLOAD, ¶m1, sizeof(param1), tmp_plain_text2); struct rkp_protected_gen_param *generated1 = (struct rkp_protected_gen_param *)tmp_plain_text2; sunxi_dump(generated1->out_buffer, generated1->out_size); #endif //protectedData ciphertext #if GEN_WITH_OS uint8_t tmp_plain_text[4096]; struct rkp_protected_gen_param param; memcpy(param.challenge, challenge, 16); param.challenge_size = 16; memcpy(param.mac_key, ephemeral_mac_key, 32); memcpy(param.mac_tag, mac_tag, 32); smc_tee_rkp_op(RKP_GEN_PROTECTED_DATA_PAYLOAD, ¶m, sizeof(param), tmp_plain_text); struct rkp_protected_gen_param *generated = (struct rkp_protected_gen_param *)tmp_plain_text; cipher = CborAllocBstr(generated->out_size + 16 /*aes gcm tag*/, cout); protected_data_encrypted(iv, generated->out_buffer, generated->out_size, cipher); #else uint8_t tmp_plain_text[4096]; struct CborOut plain_text; CborOutInit(tmp_plain_text, 4096, &plain_text); fill_protected_data_payload_plaintext(&plain_text, challenge, mac_tag); cipher = CborAllocBstr(CborOutSize(&plain_text) + 16 /*aes gcm tag*/, cout); protected_data_encrypted(iv, tmp_plain_text, CborOutSize(&plain_text), cipher); #endif //recipients fill_recipients(cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int fill_maced_keys_to_sign(struct CborOut *cout, uint8_t *mac_tag) { int before = CborOutSize(cout); CborWriteArray(4, cout); CborWriteBstr(0, (uint8_t *)" ", cout); CborWriteMap(0, cout); CborWriteNull(cout); CborWriteBstr(32, mac_tag, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } void mpi_dump(mbedtls_mpi *d) { uint8_t dmp[32]; mbedtls_mpi_write_binary(d, dmp, 32); sunxi_dump(dmp, 32); } int fill_enc_ahead(struct CborOut *cout) { // cppbor::Array() // Enc strucure as AAD // .add("Encrypt") // Context // .add(protectedParams) // Protected -- { 1: 3 } // .add(aad) // External AAD -- {} // .encode(), int before = CborOutSize(cout); uint8_t tmp_buf[64]; struct CborOut co; CborOutInit(tmp_buf, 64, &co); CborWriteMap(1, &co); CborWriteUint(1, &co); CborWriteUint(3, &co); CborWriteArray(3, cout); CborWriteTstr("Encrypt", cout); CborWriteBstr(CborOutSize(&co), tmp_buf, cout); CborWriteBstr(0, tmp_buf, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } static void __check_and_dump(uint8_t *expected, uint8_t *actual, size_t size, const char *prefix) { int ret = memcmp(expected, actual, size); printf("%s: %s\n", prefix, ret == 0 ? "pass" : "failed"); if (ret) { printf("expected:\n"); sunxi_dump(expected, size); printf("actual:\n"); sunxi_dump(actual, size); } } uint8_t test_ephemeral_priv[32] = { 0x2f, 0xc5, 0x35, 0xdb, 0x1b, 0x11, 0xe3, 0xa3, 0xe5, 0xa0, 0x01, 0x78, 0x3c, 0xf9, 0x05, 0x32, 0x98, 0x4b, 0x05, 0xf6, 0xd1, 0x26, 0x69, 0x51, 0x71, 0x3a, 0x4b, 0x18, 0x65, 0x88, 0x8d, 0x8b, }; uint8_t test_ephemeral_pub[32] = { 0x98, 0xc4, 0x84, 0xfa, 0x66, 0x54, 0x35, 0x79, 0xde, 0x48, 0x18, 0xf5, 0x0a, 0x56, 0x01, 0xab, 0xed, 0x04, 0x30, 0x47, 0x3d, 0xd6, 0xfe, 0xa0, 0x4a, 0x73, 0x13, 0x00, 0xa4, 0x2c, 0x70, 0x4b, }; static void __share_secret_gen(uint8_t *sharesecret) { mbedtls_ecdh_context ctx_cli; mbedtls_ecdh_init(&ctx_cli); mbedtls_ecp_group_load(&ctx_cli.grp, MBEDTLS_ECP_DP_CURVE25519); mbedtls_ecdh_gen_public(&ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q, myrand, NULL); mbedtls_mpi_read_binary_le(&ctx_cli.d, ephemeral.private, 32); mbedtls_mpi_read_binary_le(&ctx_cli.Q.X, ephemeral.qx, 32); mbedtls_ecp_copy(&ctx_cli.Qp, &ctx_cli.Q); mbedtls_mpi_read_binary_le(&ctx_cli.Qp.X, google.qx, 32); mbedtls_ecdh_compute_shared(&ctx_cli.grp, &ctx_cli.z, &ctx_cli.Qp, &ctx_cli.d, NULL, NULL); mbedtls_mpi_write_binary_le(&ctx_cli.z, sharesecret, 32); } static void __aes_key_hkdf(uint8_t *aes_key, uint8_t *sharesecret) { uint8_t ctx_buf[4096]; struct CborOut ctx; CborOutInit(ctx_buf, 4096, &ctx); fill_context(&ctx); mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, sharesecret, 32, ctx_buf, CborOutSize(&ctx), aes_key, 256 / 8); } static void __payload_gcm_encrypt(uint8_t *aes_key, uint8_t *iv, uint8_t *payload_plaintext, uint8_t *out, size_t plaintext_len) { uint8_t aad_buf[4096]; struct CborOut aad; CborOutInit(aad_buf, 4096, &aad); fill_enc_ahead(&aad); __aes_gcm(aes_key, iv, payload_plaintext, out, plaintext_len, aad_buf, CborOutSize(&aad)); } void protected_data_encrypted(uint8_t *iv, uint8_t *in, size_t input_len, uint8_t *out) { uint8_t sharesecret[32] = { 0 }; uint8_t aes_key[32]; __share_secret_gen(sharesecret); __aes_key_hkdf(aes_key, sharesecret); #if DEBUG_DUMP printf("session key:\n"); sunxi_dump(aes_key, 32); #endif __payload_gcm_encrypt(aes_key, iv, in, out, input_len); } static void __aes_test(void) { // uint8_t google_25519_pub[32] = { // 0xbe, 0x85, 0xe7, 0x46, 0xc4, 0xa3, 0x42, 0x5a, // 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c, // 0x58, 0x7e, 0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, // 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f, 0x72, 0x60, // }; uint8_t sharesecret[32] = { 0 }; test_ephemeral_priv[0] &= 248; test_ephemeral_priv[31] &= 127; test_ephemeral_priv[31] |= 64; memcpy(ephemeral.private, test_ephemeral_priv, 32); memcpy(ephemeral.qx, test_ephemeral_pub, 32); __share_secret_gen(sharesecret); uint8_t expected_raw_share[] = { 0x7c, 0x61, 0xdf, 0x0c, 0x67, 0xe3, 0x14, 0x7b, 0x65, 0xe5, 0x9d, 0xb1, 0x43, 0x08, 0x9e, 0x4e, 0x36, 0xe4, 0x8d, 0xdd, 0xc9, 0xfd, 0x4a, 0x85, 0xdd, 0x16, 0x5d, 0x35, 0x8c, 0xba, 0x95, 0x62, }; __check_and_dump(expected_raw_share, sharesecret, 32, "raw share"); uint8_t aes_key[32]; __aes_key_hkdf(aes_key, sharesecret); uint8_t expected_aes_key[] = { 0xc5, 0x09, 0x62, 0xa3, 0x2a, 0xfc, 0x6d, 0x9a, 0x93, 0xf5, 0x91, 0x8a, 0x60, 0x1c, 0x78, 0x3d, 0x57, 0x3e, 0x18, 0x8e, 0xfc, 0xd5, 0x7b, 0x12, 0x7c, 0xd8, 0x4f, 0x46, 0xfc, 0x9b, 0xd2, 0x26, }; __check_and_dump(expected_aes_key, aes_key, 32, "aes key"); uint8_t out[1024]; uint8_t in[] = { 0x82, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x20, 0x2f, 0xc5, 0x35, 0xdb, 0x1b, 0x11, 0xe3, 0xa3, 0xe5, 0xa0, 0x01, 0x78, 0x3c, 0xf9, 0x05, 0x32, 0x98, 0x4b, 0x05, 0xf6, 0xd1, 0x26, 0x69, 0x51, 0x71, 0x3a, 0x4b, 0x18, 0x65, 0x88, 0x8d, 0x8b, 0x58, 0x40, 0x00, 0x25, 0x4d, 0xae, 0x83, 0xec, 0x66, 0x78, 0x2f, 0xd7, 0x1c, 0x0f, 0x69, 0xf5, 0x9b, 0x09, 0x13, 0xed, 0x9a, 0xdb, 0xb0, 0x7d, 0x97, 0xf7, 0xb6, 0x1c, 0x52, 0xce, 0xfa, 0x79, 0x1f, 0xd8, 0x6f, 0x02, 0x85, 0x06, 0x38, 0xdd, 0x93, 0xf5, 0x48, 0x14, 0x3c, 0x1c, 0x62, 0xbe, 0x87, 0xbd, 0xb6, 0xc8, 0x53, 0x25, 0x54, 0xe4, 0x6a, 0xe6, 0xe1, 0xad, 0xb4, 0xbb, 0x38, 0x12, 0xee, 0x08, 0x82, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0xa9, 0x37, 0x78, 0x63, 0xfc, 0xf4, 0x46, 0xf9, 0x85, 0x6b, 0x27, 0x65, 0xba, 0x5e, 0x4d, 0x30, 0x29, 0xf0, 0xd4, 0x72, 0xb7, 0x04, 0xcb, 0x2d, 0x5f, 0x76, 0xa8, 0x13, 0x75, 0x3a, 0xeb, 0x9b, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x4c, 0xa4, 0x01, 0x66, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x02, 0x67, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x2c, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0xa9, 0x37, 0x78, 0x63, 0xfc, 0xf4, 0x46, 0xf9, 0x85, 0x6b, 0x27, 0x65, 0xba, 0x5e, 0x4d, 0x30, 0x29, 0xf0, 0xd4, 0x72, 0xb7, 0x04, 0xcb, 0x2d, 0x5f, 0x76, 0xa8, 0x13, 0x75, 0x3a, 0xeb, 0x9b, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x99, 0x32, 0x25, 0x32, 0x85, 0xa3, 0x35, 0x0d, 0xf0, 0x1e, 0x54, 0x47, 0x44, 0xba, 0x9a, 0xa5, 0x13, 0xc4, 0x35, 0xfe, 0x2f, 0x84, 0x79, 0x78, 0x61, 0x35, 0x14, 0x5c, 0x78, 0xc3, 0x40, 0xae, 0x51, 0x07, 0x94, 0x8b, 0xd1, 0xed, 0xce, 0xf9, 0x94, 0xa7, 0x0e, 0xe8, 0xfe, 0x7d, 0x28, 0x01, 0x67, 0x90, 0xe2, 0x25, 0xfb, 0x9f, 0x40, 0xe5, 0xe0, 0x39, 0xd9, 0xc9, 0xbb, 0x6b, 0xf6, 0x00, }; uint8_t iv[32] = { 0x98, 0xc4, 0x84, 0xfa, 0x66, 0x54, 0x35, 0x79, 0xde, 0x48, 0x18, 0xf5, }; uint8_t expected_ciphertext[] = { 0x22, 0x88, 0x7b, 0xba, 0xba, 0x36, 0x8e, 0xd3, 0xf9, 0x4b, 0x92, 0x6e, 0xc4, 0x8f, 0xd3, 0x4f, 0xe5, 0x7a, 0xe3, 0xa1, 0x5f, 0xfd, 0x4d, 0x06, 0x0a, 0x3f, 0x03, 0xc9, 0x92, 0xef, 0x4e, 0x1e, 0x04, 0x94, 0x39, 0xef, 0xfc, 0x62, 0x5f, 0x47, 0xb9, 0x79, 0xc3, 0x0e, 0xd0, 0x0e, 0x88, 0x31, 0x78, 0x31, 0x86, 0x8c, 0xe7, 0x43, 0x89, 0x65, 0x67, 0x06, 0xdb, 0x06, 0xa4, 0x15, 0x80, 0x9c, 0x91, 0x13, 0x21, 0xf8, 0xaf, 0xc2, 0x49, 0xb1, 0xf8, 0x58, 0x03, 0x5e, 0x11, 0x9d, 0xd1, 0x9d, 0x13, 0x95, 0x7e, 0xd9, 0xe3, 0x9e, 0x6c, 0xaf, 0x7a, 0x61, 0x76, 0x0e, 0x99, 0x6b, 0x16, 0xf7, 0x08, 0xf9, 0xa6, 0x37, 0x47, 0x4c, 0xc2, 0xd7, 0xe7, 0x0c, 0xc4, 0xbc, 0xc3, 0x7f, 0x66, 0x28, 0xfd, 0x2e, 0x66, 0xe3, 0x2b, 0x36, 0x75, 0x68, 0x5b, 0xcb, 0x7e, 0xa6, 0x9d, 0xf9, 0x80, 0xe5, 0xd3, 0xe3, 0x52, 0x62, 0x35, 0x2e, 0xdc, 0xa6, 0x64, 0x4a, 0xbc, 0x09, 0x7d, 0xc7, 0xb7, 0xb2, 0x9c, 0xdd, 0xe9, 0xa6, 0xfb, 0x49, 0xed, 0xf2, 0x50, 0xe9, 0x2c, 0xd8, 0x19, 0x8d, 0x60, 0x9a, 0x8c, 0xca, 0xe3, 0x0a, 0x44, 0x9f, 0x33, 0xdf, 0x12, 0x94, 0x16, 0x73, 0x41, 0x05, 0x4c, 0xc1, 0xc8, 0x74, 0x24, 0x9e, 0xd3, 0x1f, 0x7a, 0xb3, 0x78, 0x5d, 0xaf, 0x8d, 0xd2, 0xc4, 0x16, 0xe9, 0x9a, 0x6c, 0xae, 0x7b, 0xcb, 0x43, 0xdd, 0x0a, 0x67, 0x2c, 0xc7, 0x4d, 0xad, 0x4a, 0x61, 0x31, 0x7f, 0x61, 0x2b, 0xc0, 0x1a, 0x21, 0xa2, 0x5e, 0x3a, 0x44, 0x96, 0xf1, 0x70, 0x65, 0xae, 0xf0, 0x56, 0x8b, 0xe2, 0x82, 0xf4, 0xd9, 0x5e, 0xfc, 0x46, 0xe7, 0x51, 0x9a, 0x78, 0x2b, 0x03, 0x6e, 0x08, 0x46, 0xc1, 0xd8, 0xd5, 0xdd, 0x17, 0xdf, 0x9a, 0x4e, 0x2d, 0xce, 0xc6, 0x58, 0x7b, 0xe3, 0x74, 0xa2, 0xa7, 0x46, 0xf2, 0x8e, 0xee, 0xe6, 0xec, 0x2b, 0x10, 0x21, 0x44, 0x4a, 0x73, 0x1c, 0x3f, 0xb4, 0xbc, 0xe1, 0xc2, 0xcc, 0xcb, 0xac, 0xe5, 0x15, 0x2b, 0x42, 0xa6, 0xf5, 0x89, 0xaf, 0xd2, 0xea, 0xfb, 0x5e, 0x6b, 0x82, 0xe0, 0xe5, 0x04, 0xf4, 0x6a, 0xb6, 0x4c, 0x9b, 0x50, 0x8e, 0xe0, 0xe4, 0x00, 0xe1, 0xee, 0x03, 0xfb, 0x35, 0xd6, 0xc6, 0x50, 0x3e, 0x33, 0xaa, }; //__payload_gcm_encrypt(aes_key,iv,in,out,sizeof(in)); protected_data_encrypted(iv, in, sizeof(in), out); __check_and_dump(expected_ciphertext, out, sizeof(expected_ciphertext), "cipher text"); } static void __recipent_test(void) { uint8_t tmp_buf[1024]; struct CborOut co; memcpy(ephemeral.qx, test_ephemeral_pub, sizeof(test_ephemeral_pub)); memcpy(ephemeral.private, test_ephemeral_pub, sizeof(test_ephemeral_pub)); ephemeral.isX25519 = 1; memset(tmp_buf, 0, 1024); CborOutInit(tmp_buf, 1024, &co); fill_recipients(&co); uint8_t expected[] = { 0x81, 0x83, 0x44, 0xa1, 0x01, 0x38, 0x18, 0xa2, 0x04, 0x58, 0x20, 0xd0, 0xae, 0xc1, 0x15, 0xca, 0x2a, 0xcf, 0x73, 0xae, 0x6b, 0xcc, 0xcb, 0xd1, 0x96, 0x1d, 0x65, 0xe8, 0xb1, 0xdd, 0xd7, 0x4a, 0x1a, 0x37, 0xb9, 0x43, 0x3a, 0x97, 0xd5, 0x99, 0xdf, 0x98, 0x08, 0x20, 0xa3, 0x01, 0x01, 0x20, 0x04, 0x21, 0x58, 0x20, 0x98, 0xc4, 0x84, 0xfa, 0x66, 0x54, 0x35, 0x79, 0xde, 0x48, 0x18, 0xf5, 0x0a, 0x56, 0x01, 0xab, 0xed, 0x04, 0x30, 0x47, 0x3d, 0xd6, 0xfe, 0xa0, 0x4a, 0x73, 0x13, 0x00, 0xa4, 0x2c, 0x70, 0x4b, 0xf6, }; __check_and_dump(expected, tmp_buf, sizeof(expected), "recipent"); } int fill_maced_public_key_mac_struct(struct CborOut *cout) { // MAC_structure = [ // context : "MAC0", // protected : bstr .cbor { 1 : 5 }, // external_aad : bstr .size 0, // payload : bstr .cbor PublicKey (no public key at CSR, [ 0x80(0 len array) ]) // ] int before = CborOutSize(cout); CborWriteArray(4, cout); CborWriteTstr("MAC0", cout); uint8_t tmp_buf[64]; struct CborOut co; CborOutInit(tmp_buf, 64, &co); CborWriteMap(1, &co); CborWriteUint(1, &co); CborWriteUint(5, &co); CborWriteBstr(CborOutSize(&co), tmp_buf, cout); CborWriteBstr(0, tmp_buf, cout); tmp_buf[0] = 0x80; CborWriteBstr(1, tmp_buf, cout); #if DEBUG_DUMP printf("\n%s:\n", __func__); sunxi_dump(cout->buffer + before, CborOutSize(cout) - before); #endif return CborOutSize(cout) - before; } int __mac_tag_generate(uint8_t *mac_key, uint8_t *mac_tag) { uint8_t buf[1024]; struct CborOut cout; CborOutInit(buf, 1024, &cout); fill_maced_public_key_mac_struct(&cout); hmac(buf, mac_key, mac_tag, CborOutSize(&cout)); return 0; } static void __mac_test(void) { uint8_t test_mac_key[] = { 0x2f, 0xc5, 0x35, 0xdb, 0x1b, 0x11, 0xe3, 0xa3, 0xe5, 0xa0, 0x01, 0x78, 0x3c, 0xf9, 0x05, 0x32, 0x98, 0x4b, 0x05, 0xf6, 0xd1, 0x26, 0x69, 0x51, 0x71, 0x3a, 0x4b, 0x18, 0x65, 0x88, 0x8d, 0x8b, }; uint8_t mac_tag[32]; __mac_tag_generate(test_mac_key, mac_tag); uint8_t mac_pub_buf[1024]; struct CborOut mac_pub; CborOutInit(mac_pub_buf, 1024, &mac_pub); fill_maced_keys_to_sign(&mac_pub, mac_tag); uint8_t expected[] = { 0x84, 0x40, 0xa0, 0xf6, 0x58, 0x20, 0x83, 0x86, 0x0d, 0x78, 0xfc, 0xa3, 0x01, 0x68, 0x1d, 0x38, 0xd9, 0x7f, 0xed, 0xf4, 0xf4, 0x78, 0x2f, 0x4e, 0x46, 0x14, 0xa3, 0x2b, 0xb4, 0x5c, 0x0e, 0xf1, 0x4f, 0x4f, 0x66, 0x88, 0x80, 0xa2, }; __check_and_dump(expected, mac_pub_buf, sizeof(expected), "mac test"); } int csr_generate(uint8_t *out, size_t *len) { uint8_t challenge[16]; uint8_t mac_tag[32]; //ephemeral key generate x25519_pair_gen(&ephemeral); //mac key generate hmac(ephemeral.private, ephemeral.qx, ephemeral_mac_key, 32); //challenge myrand(NULL, challenge, 16); //mac tag generate __mac_tag_generate(ephemeral_mac_key, mac_tag); struct CborOut cout; CborOutInit(out, *len, &cout); CborWriteArray(4, &cout); CborWriteArray(2, &cout); fill_deviceinfo(&cout); //an empty map CborWriteMap(0, &cout); //challenge CborWriteBstr(16, challenge, &cout); //protected data fill_protected_data(&cout, ephemeral_mac_key, challenge, mac_tag); fill_maced_keys_to_sign(&cout, mac_tag); *len = CborOutSize(&cout); return 0; } void csr_gen_self_test(void) { __aes_test(); __mac_test(); __recipent_test(); } void base64_csr_generate(char *out) { uint8_t tmp_csr[4096]; size_t olen = 4096, base64_len; uint8_t pri_gen_input[32]; struct ecc_pubkey_t pubkey; //dk gen sunxi_trng_gen(pri_gen_input, 32); private_gen(pri_gen_input, 32, dk.private); sunxi_ecc_pub_gen(dk.private, &pubkey, &p256_param); __rsa_padding(dk.qx, pubkey.qx, 32, 32); __rsa_padding(dk.qy, pubkey.qy, 32, 32); dk.isX25519 = 0; __prepare_device_info(); __prepare_verify_boot_data(); csr_generate(tmp_csr, &olen); #ifdef DEBUG_DUMP printf("generated csr:\n"); sunxi_dump(tmp_csr, ALIGN(olen, 16)); #endif mbedtls_base64_encode((void *)out, 4096, &base64_len, tmp_csr, olen); } int do_rkp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { #if 1 memset((void *)0x40000000, 0, 8192); key_extraction_output_generate((void *)0x40000000, 8192); printf("\n\n"); puts((char *)0x40000000); printf("\n\n"); #else uint8_t pri_gen_input[32]; struct ecc_pubkey_t pubkey; //dk gen sunxi_trng_gen(pri_gen_input, 32); private_gen(pri_gen_input, 32, dk.private); sunxi_ecc_pub_gen(dk.private, &pubkey, &p256_param); __rsa_padding(dk.qx, pubkey.qx, 32, 32); __rsa_padding(dk.qy, pubkey.qy, 32, 32); dk.isX25519 = 0; //csr gen //csr_generate((void*)0x40000000, &olen); #endif csr_gen_self_test(); return 0; } U_BOOT_CMD(sunxi_rkp, 6, 1, do_rkp, "sunxi rkp", ""); #endif