/* * Copyright 2024 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef __GSC_UTILS_BOOT_PARAM_CBOR_BOOT_PARAM_H #define __GSC_UTILS_BOOT_PARAM_CBOR_BOOT_PARAM_H #include "cbor_basic.h" #include "boot_param_types.h" #ifdef __cplusplus extern "C" { #endif /* Boot mode decisions. * Boot mode == "Not configured" is not allowed */ #define BOOT_MODE_NORMAL 1 #define BOOT_MODE_DEBUG 2 #define BOOT_MODE_RECOVERY 3 /* Configuration descriptor - see go/gsc-dice */ #define CFG_DESCR_LABEL_COMP_NAME CBOR_NINT32(-70002) #define CFG_DESCR_LABEL_RESETTABLE CBOR_NINT32(-70004) #define CFG_DESCR_LABEL_SEC_VER CBOR_NINT32(-70005) #define CFG_DESCR_LABEL_APROV_STATUS CBOR_NINT32(-71000) #define CFG_DESCR_LABEL_VBOOT_STATUS CBOR_NINT32(-71001) #define CFG_DESCR_LABEL_AP_FW_VERSION CBOR_NINT32(-71002) #define CFG_DESCR_COMP_NAME_VALUE_LEN 10 /* "CrOS AP FW" */ #define CFG_DESCR_COMP_NAME_LEN (1 + CFG_DESCR_COMP_NAME_VALUE_LEN) #define CFG_DESCR_COMP_NAME \ { \ CBOR_HDR1(CBOR_MAJOR_TSTR, CFG_DESCR_COMP_NAME_VALUE_LEN), \ 'C', 'r', 'O', 'S', ' ', 'A', 'P', ' ', 'F', 'W' \ } struct cfg_descr_s { /* Map header: 6 entries */ uint8_t map_hdr; /* 1. Comp name: nint(-70002, 4bytes) => tstr("CrOS AP FW") */ uint8_t comp_name_label[CBOR_NINT32_LEN]; uint8_t comp_name[CFG_DESCR_COMP_NAME_LEN]; /* 2. Resettable: nint(-70004, 4bytes) => null */ uint8_t resettable_label[CBOR_NINT32_LEN]; uint8_t resettable; /* 3. Sec ver: nint(-70005, 4bytes) => uint(Security ver, 4bytes) */ uint8_t sec_ver_label[CBOR_NINT32_LEN]; struct cbor_uint32_s sec_ver; /* 4. APROV status: nint(-71000, 4bytes) => uint(APROV_sts, 4bytes) */ uint8_t aprov_status_label[CBOR_NINT32_LEN]; struct cbor_uint32_s aprov_status; /* 5. Vboot status: nint(-71001, 4bytes) => bstr(PCR0, 32bytes) */ uint8_t vboot_status_label[CBOR_NINT32_LEN]; struct cbor_bstr32_s vboot_status; /* 6. AP FW version: nint(-71002, 4bytes) => bstr(PCR10, 32bytes) */ uint8_t ap_fw_version_label[CBOR_NINT32_LEN]; struct cbor_bstr32_s ap_fw_version; }; #define CFG_DESCR_LEN sizeof(struct cfg_descr_s) struct cfg_descr_bstr_s { uint8_t bstr_hdr[2]; /* bstr(sizeof(struct cfg_descr_s), 1byte) */ struct cfg_descr_s data; }; #define CFG_DESCR_BSTR_HDR CBOR_BSTR_HDR8(CFG_DESCR_LEN) /* COSE keys - see go/gsc-dice */ #define COSE_KEY_LABEL_KTY CBOR_UINT0(1) #define COSE_KEY_LABEL_ALG CBOR_UINT0(3) #define COSE_KEY_LABEL_KEY_OPS CBOR_UINT0(4) #define COSE_KEY_LABEL_CRV CBOR_NINT0(-1) #define COSE_KEY_LABEL_X CBOR_NINT0(-2) #define COSE_KEY_LABEL_Y CBOR_NINT0(-3) /* Configuration descriptor per go/gsc-dice */ struct cose_key_ecdsa_s { /* Map header: 6 entries */ uint8_t map_hdr; /* 1. Key type: uint(1, 0bytes) => uint(2, 0bytes) */ uint8_t kty_label; uint8_t kty; /* 2. Algorithm: uint(3, 0bytes) => nint(-1, 0bytes) */ uint8_t alg_label; uint8_t alg; /* 3. Key ops: uint(4, 0bytes) => array(1) { uint(2, 0bytes) } */ uint8_t key_ops_label; uint8_t key_ops_array_hdr; uint8_t key_ops; /* 4. Curve: nint(-1, 0bytes) => uint(1, 0bytes) */ uint8_t crv_label; uint8_t crv; /* 5. X: nint(-2, 0bytes) => bstr(X, 32bytes) */ uint8_t x_label; struct cbor_bstr32_s x; /* 6. X: nint(-3, 0bytes) => bstr(Y, 32bytes) */ uint8_t y_label; struct cbor_bstr32_s y; }; #define COSE_KEY_ECDSA_LEN sizeof(struct cose_key_ecdsa_s) struct cose_key_ecdsa_bstr_s { uint8_t bstr_hdr[2]; /* bstr(sizeof(struct cose_key_ecdsa_s), 1byte) */ struct cose_key_ecdsa_s data; }; #define COSE_KEY_ECDSA_BSTR_HDR CBOR_BSTR_HDR8(COSE_KEY_ECDSA_LEN) /* CWT claims - see go/gsc-dice * Size of TSTR containing an {UDS,CDI}_ID: (24 =< DICE_ID_HEX_LEN < 255) * => 1 byte size encoding */ #define DICE_ID_TSTR_LEN (2 + DICE_ID_HEX_BYTES) #define CWT_LABEL_ISS CBOR_UINT0(1) #define CWT_LABEL_SUB CBOR_UINT0(2) #define CWT_LABEL_CODE_HASH CBOR_NINT32(-4670545) #define CWT_LABEL_CFG_HASH CBOR_NINT32(-4670547) #define CWT_LABEL_CFG_DESCR CBOR_NINT32(-4670548) #define CWT_LABEL_AUTH_HASH CBOR_NINT32(-4670549) #define CWT_LABEL_MODE CBOR_NINT32(-4670551) #define CWT_LABEL_SUBJECT_PK CBOR_NINT32(-4670552) #define CWT_LABEL_KEY_USAGE CBOR_NINT32(-4670553) #define CWT_LABEL_PROFILE_NAME CBOR_NINT32(-4670554) #define CWT_PROFILE_NAME_VALUE_LEN 10 /* "android.16" */ #define CWT_PROFILE_NAME_LEN (1 + CWT_PROFILE_NAME_VALUE_LEN) #define CWT_PROFILE_NAME \ { \ CBOR_HDR1(CBOR_MAJOR_TSTR, CWT_PROFILE_NAME_VALUE_LEN), \ 'a', 'n', 'd', 'r', 'o', 'i', 'd', '.', '1', '6' \ } struct cwt_claims_s { /* Map header: 10 entries */ uint8_t map_hdr; /* 1. ISS: uint(1, 0bytes) => tstr(hex(UDS_ID)) */ uint8_t iss_label; struct cbor_tstr40_s iss; /* 2. SUB: uint(2, 0bytes) => tstr(hex(CDI_ID)) */ uint8_t sub_label; struct cbor_tstr40_s sub; /* 3. Code Hash: nint(-4670545, 4bytes) => bstr(32bytes) */ uint8_t code_hash_label[CBOR_NINT32_LEN]; struct cbor_bstr32_s code_hash; /* 4. Cfg Hash: nint(-4670547, 4bytes) => bstr(32bytes) */ uint8_t cfg_hash_label[CBOR_NINT32_LEN]; struct cbor_bstr32_s cfg_hash; /* 5. Cfg Descr: nint(-4670548, 4bytes) => bstr(struct cfg_descr_s) */ uint8_t cfg_descr_label[CBOR_NINT32_LEN]; struct cfg_descr_bstr_s cfg_descr; /* 6. Auth Hash: nint(-4670549, 4bytes) => bstr(32bytes) */ uint8_t auth_hash_label[CBOR_NINT32_LEN]; struct cbor_bstr32_s auth_hash; /* 7. Mode: nint(-4670551, 4bytes) => bstr(1byte) */ uint8_t mode_label[CBOR_NINT32_LEN]; struct cbor_bstr1_s mode; /* 8. Subject PK: nint(-4670552, 4bytes) => bstr(COSE_Key) */ uint8_t subject_pk_label[CBOR_NINT32_LEN]; struct cose_key_ecdsa_bstr_s subject_pk; /* 9. Key Usage: nint(-4670553, 4bytes) => bstr(1byte) */ uint8_t key_usage_label[CBOR_NINT32_LEN]; struct cbor_bstr1_s key_usage; /* 10. Profile name: nint(-4670554, 4bytes) => tstr("android.16") */ uint8_t profile_name_label[CBOR_NINT32_LEN]; uint8_t profile_name[CWT_PROFILE_NAME_LEN]; }; #define CWT_CLAIMS_LEN sizeof(struct cwt_claims_s) struct cwt_claims_bstr_s { uint8_t bstr_hdr[3]; /* bstr(sizeof(struct cose_key_ecdsa_s), 2bytes) */ struct cwt_claims_s data; }; #define CWT_CLAIMS_BSTR_HDR CBOR_BSTR_HDR16(CWT_CLAIMS_LEN) /* Protected COSE header parameters - see go/gsc-dice */ #define COSE_PARAM_LABEL_ALG CBOR_UINT0(1) struct cose_param_bstr_s { /* BSTR of size 3 - see the rest of the struct */ uint8_t bstr_hdr; /* Map header: 1 element */ uint8_t map_hdr; /* 1. Alg: uint(1, 0bytes) => nint(-7, 0bytes) */ uint8_t alg_label; uint8_t alg; }; #define COSE_PARAM_BSTR \ { \ /* BSTR of size 3 - see the rest of the struct */ \ CBOR_HDR1(CBOR_MAJOR_BSTR, 3), \ /* Map header: 1 elem */ \ CBOR_HDR1(CBOR_MAJOR_MAP, 1), \ /* 1. Alg: uint(1) => nint(-7) */ \ COSE_PARAM_LABEL_ALG, \ CBOR_NINT0(-7) /* ECDSA w/ SHA-256 */ \ } /* Sig structure for CDI certificate - see go/gsc-dice */ #define CDI_SIG_STRUCT_CONTEXT_VALUE_LEN 10 /* "Signature1" */ #define CDI_SIG_STRUCT_CONTEXT_LEN (1 + CDI_SIG_STRUCT_CONTEXT_VALUE_LEN) #define CDI_SIG_STRUCT_CONTEXT \ { \ CBOR_HDR1(CBOR_MAJOR_TSTR, CDI_SIG_STRUCT_CONTEXT_VALUE_LEN), \ 'S', 'i', 'g', 'n', 'a', 't', 'u', 'r', 'e', '1' \ } struct cdi_sig_struct_hdr_s { /* Array header: 4 elements */ uint8_t array_hdr; /* 1. Context: tstr("Signature1") */ uint8_t context[CDI_SIG_STRUCT_CONTEXT_LEN]; /* 2. Body protected: bstr(COSE param) */ struct cose_param_bstr_s body_protected; /* 3. External AAD: bstr(0 bytes) */ uint8_t external_aad; /* 4. Payload - not fixed, contained in cdi_sig_struct_t */ }; #define CDI_SIG_STRUCT_LEN \ (sizeof(struct cdi_sig_struct_hdr_s) + sizeof(struct cwt_claims_bstr_s)) /* CDI certificate = COSE_Sign1 structure - see go/gsc-dice */ /* Header of the certificate that includes protected & unprotected * parameters, but not payload (CWT claims) and signature. * This header is actually fixed (no variable fields). * We need it to be able to prepend either it or Sig_structure header to * payload: the former to return as a part of AndroidDiceHandover, * the latter to calculate certificate signature. */ struct cdi_cert_hdr_s { /* Array header: 4 elements */ uint8_t array_hdr; /* 1. Protected: bstr(COSE param) */ struct cose_param_bstr_s protected; /* 2. Unprotected: empty map */ uint8_t unprotected; /* 3. Payload: bstr(CWT claims) - not fixed, struct cwt_claims_bstr_s */ /* 4. Signature: bstr(64 bytes) - not fixed, struct cbor_bstr64_s */ }; #define CDI_CERT_LEN \ (sizeof(struct cdi_cert_hdr_s) + \ sizeof(struct cwt_claims_bstr_s) + \ sizeof(struct cbor_bstr64_s)) /* DICE cert chain. In our case, CBOR array consisting of exactly 2 entries * DiceCertChain = [ * COSE_Key, ; UDS pub key * COSE_Sign1, ; CDI DICE cert * ] */ /* Header of DICE cert chain that includes UDS pubkey, but not CDI DICE cert. * This header contains variable fields (UDS key). * We need it to be able to prepend either it + cert header or Sig_structure * header to CWT claims: the former to return as a part of * AndroidDiceHandover, the latter to calculate certificate signature. */ struct dice_cert_chain_hdr_s { /* Array header: 2 elements */ uint8_t array_hdr; /* 1. UDS pub key: COSE_Key */ struct cose_key_ecdsa_s uds_pub_key; /* 2. CDI DICE cert: - not included, * consists of hdr=cdi_cert_hdr_s, payload=cwt_claims_bstr_s, * sig=cbor_bstr64_s */ }; /* Dice Handover struct. In our case, CBOR map with exactly 3 entries: * AndroidDiceHandover = { * 1 : bstr .size 32, ; CDI_Attest * 2 : bstr .size 32, ; CDI_Seal * 3 : DiceCertChain, ; DICE chain - see above * } */ #define DICE_HANDOVER_LABEL_CDI_ATTEST CBOR_UINT0(1) #define DICE_HANDOVER_LABEL_CDI_SEAL CBOR_UINT0(2) #define DICE_HANDOVER_LABEL_DICE_CHAIN CBOR_UINT0(3) /* Header of the DICE handover structure that contains the CDIs, but not the * DICE chain. This header contains variable fields (CDIs). We need it to be * able to prepend either it + DICE chain header + cert header or * Sig_structure header to CWT claims: the former to return as a part of * AndroidDiceHandover, the latter to calculate certificate signature. */ struct dice_handover_hdr_s { /* Map header: 3 elements */ uint8_t map_hdr; /* 1. CDI_Attest: uint(1, 0bytes) => bstr(32bytes) */ uint8_t cdi_attest_label; struct cbor_bstr32_s cdi_attest; /* 2. CDI_Seal: uint(2, 0bytes) => bstr(32bytes) */ uint8_t cdi_seal_label; struct cbor_bstr32_s cdi_seal; /* 3. DICE chain: uint(3, 0bytes) => DICE cert chain */ uint8_t dice_chain_label; /* DICE cert chain is not included */ }; /* GSC Boot Parameters for TEE. * GSCBootParam = { * 1 : bstr .size 64, ; EarlyEntropy * 2 : bstr .size 32, ; SessionKeySeed * 3 : bstr .size 32, ; AuthTokenKeySeed * } */ struct gsc_boot_param_s { /* Map header: 3 entries */ uint8_t map_hdr; /* 1. EarlyEntropy: uint(1, 0bytes) => bstr(entropy, 64bytes) */ uint8_t early_entropy_label; struct cbor_bstr64_s early_entropy; /* 2. SessionKeySeed: uint(2, 0bytes) => bstr(entropy, 32bytes) */ uint8_t session_key_seed_label; struct cbor_bstr32_s session_key_seed; /* 3. AuthTokenKeySeed: uint(3, 0bytes) => bstr(entropy, 32bytes) */ uint8_t auth_token_key_seed_label; struct cbor_bstr32_s auth_token_key_seed; }; #ifdef __cplusplus } /* extern "C" */ #endif #endif /* __GSC_UTILS_BOOT_PARAM_CBOR_BOOT_PARAM_H */