sdk-hwV1.3/lichee/brandy-2.0/u-boot-2018/board/sunxi/sunxi_rkp.c

1514 lines
47 KiB
C

/*
* (C) Copyright 2022-2025
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
*
* ouyangkun <ouyangkun@allwinnertech.com>
* SPDX-License-Identifier: GPL-2.0+
*/
#include <command.h>
#include <sunxi_board.h>
#include <sunxi_avb.h>
#include <asm/arch/ce.h>
#include <securestorage.h>
#include <sunxi_verify_boot_info.h>
#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 <dice/cbor_writer.h>
#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, &param, 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, &param1, 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, &param1, 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, &param, 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