diff --git a/include/os_endorsement.h b/include/os_endorsement.h index efcbea66..79b102dc 100644 --- a/include/os_endorsement.h +++ b/include/os_endorsement.h @@ -1,35 +1,247 @@ -#pragma once +/** + * @file + * @brief + */ + +#ifndef OS_ENDORSEMENT_H_ +#define OS_ENDORSEMENT_H_ + +/********************* + * INCLUDES + *********************/ #include "bolos_target.h" #include "decorators.h" +#include "os_types.h" +#include "lcx_sha256.h" + +/********************* + * DEFINES + *********************/ + +#define ENDORSEMENT_HASH_LENGTH CX_SHA256_SIZE +#define ENDORSEMENT_METADATA_LENGTH 8 +#define ENDORSEMENT_PUBLIC_KEY_LENGTH 65 +#define ENDORSEMENT_APP_SECRET_LENGTH 64 +#define ENDORSEMENT_MAX_ASN1_LENGTH 72 +#define ENDORSEMENT_SIGNATURE_MAX_LENGTH ENDORSEMENT_MAX_ASN1_LENGTH + +/********************** + * TYPEDEFS + **********************/ + +typedef enum { + ENDORSEMENT_SLOT_1 = 1, + ENDORSEMENT_SLOT_2 +} ENDORSEMENT_slot_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * @brief Get sha256 hash of currently running application. + * + * @param[out] out_hash Pointer where application hash is copied. Writing is performed only if + * not-NULL. Hash has a fixed size of ENDORSEMENT_HASH_LENGTH. + * + * @return bolos_err_t + * @retval 0x5503 Pin is not validated + * @retval 0x5116 Internal error + * @retval 0x522F Internal error + * @retval 0x0000 Success + */ +SYSCALL bolos_err_t ENDORSEMENT_get_code_hash(uint8_t *out_hash); + +/** + * @brief Compute endorsement public key from given slot + * + * @param[in] slot Index of the slot from which the public key is read + * @param[out] out_public_key Pointer where public key is written. (Size + * ENDORSEMENT_PUBLIC_KEY_LENGTH) + * @param[out] out_public_key_length Point where public key length is written. + * + * @retval 0x5218: Endorsement not set or corrupted + * @retval 0x4209: \p slot is invalid + * @retval 0x4103: No private key is loaded in slot + * @retval 0x5415: Error during public key structure init + * @retval 0x5416: Error during public key computation + * @retval 0x0000: Success + */ +SYSCALL bolos_err_t ENDORSEMENT_get_public_key(ENDORSEMENT_slot_t slot, + uint8_t *out_public_key, + uint8_t *out_public_key_length); + +/** + * @brief Get certificate public key from given slot + * + * @param[in] slot Index of the slot from which the certificate public key is to be read. + * @param[out] out_buffer Pointer where certificate content is written. Writing is performed only if + * not NULL. + * @param[out] out_length Pointer where certificate length is written. Writing is performed only if + * not NULL. + * + * @return bolos_err_t + * @retval 0x5219: Endorsement not set or corrupted + * @retval 0x420A: \p endorsement_slot is invalid + * @retval 0x4104: \p endorsement_slot is not set + * @retval 0x0000: Success + */ +SYSCALL bolos_err_t ENDORSEMENT_get_public_key_certificate(ENDORSEMENT_slot_t endorsement_slot, + uint8_t *out_buffer, + uint8_t *out_length); + +/** + * @brief Compute secret from current app code hash and slot1 secret field + * + * @param[out] out_secret Pointer where resulting secret is written. App secret has a fixed length + * of ENDORSEMENT_APP_SECRET_LENGTH. + * + * @return bolos_err_t + * @retval 0x521A Endorsement not set or corrupted + * @retval 0x4105 No private key set in slot 1 + * @retval 0x534A Error during hmac computation + * @retval 0x0000 Success + */ +SYSCALL bolos_err_t ENDORSEMENT_key1_get_app_secret(uint8_t *out_secret); + +/** + * @brief Perform hash and sign on input data and calling app code hash. + * + * Hash input data, update the hash with current calling app code hash, then sign it with keys from + * endorsement slot 1. + * + * @param[in] data Data to be hashed + * @param[in] dataLength Length of \p data + * @param[out] out_signature Pointer where resulting signature is written (size + * ENDORSEMENT_HASH_LENGTH) + * @param[out] out_signature_length If non-NULL, pointer where resulting signature length is + * written. + * + * @return bolos_err_t + * @retval 0x521B Endorsement not set or corrupted + * @retval 0x5503 Pin is not validated + * @retval 0x5116 Internal error + * @retval 0x522F Internal error + * @retval 0x4106 No private key is set in slot 1 + * @retval 0xFFFFFFxx Cryptography-related error + * @retval 0x0000 Success + */ +SYSCALL bolos_err_t ENDORSEMENT_key1_sign_data(uint8_t *data, + uint32_t data_length, + uint8_t *out_signature, + uint32_t *out_signature_length); + +/** + * @brief Hash input data, then sign the hash with slot1 key. App code hash is not + * included when computing hash. + * + * @param[in] data Data to be hashed and signed + * @param[in] data_length Length of \p data + * @param[out] out_signature Pointer where resulting signature is written. + * @param[out] out_signature_length If non-NULL, pointer where resulting signature length is + * written. + * + * @return bolos_err_t + * @retval 0x522E Invalid endorsement structure + * @retval 0x4117 No private key is loaded in slot 1 + * @retval 0xFFFFFFxx Cryptography-related error + * @retval 0x0000 Success + */ +SYSCALL bolos_err_t ENDORSEMENT_key1_sign_without_code_hash(uint8_t *data, + uint32_t data_length, + uint8_t *out_signature, + uint32_t *out_signature_length); + +/** + * @brief Perform hashing and signature on input data and slot 2 derived keys. + * @note Internal implementation of `ENDORSEMENT_key2_derive_sign_data` syscall + * + * @param[in] data Input data to be hashed and signed + * @param[in] data_length Length of \p data + * @param[out] out_signature Pointer where resulting signature is written (size + * ENDORSEMENT_SIGNATURE_MAX_LENGTH). + * @param[out] out_signature_length If non-NULL, pointer where resulting signature length is + * written. + * + * @return bolos_err_t + * @retval 0x521C Endorsement not set or corrupted + * @retval 0x5503 Pin is not validated + * @retval 0x5116 Internal error + * @retval 0x522F Internal error + * @retval 0x4107 No private key is loaded in slot 2 + * @retval 0x5716 Cryptographic operation failed + * @retval 0x0000 Success + */ +SYSCALL bolos_err_t ENDORSEMENT_key2_derive_sign_data(uint8_t *data, + uint32_t data_length, + uint8_t *out_signature, + uint32_t *out_signature_length); + +/** + * @brief Get metadata from given slot + * @note Internal implementation of `os_endorsement_get_metadata` syscall + * + * @param slot Index of slot from which metadata is read + * @param[in] out_buffer Pointer where metadata are written (size ENDORSEMENT_METADTA_LENGTH) + * @param[out] out_length Pointer where metadata length is written + * + * @return + * @retval 0x5222 Endorsement not set or corrupted + * @retval 0x4225 Invalid \p slot paramater + */ +SYSCALL bolos_err_t ENDORSEMENT_get_metadata(ENDORSEMENT_slot_t slot, + uint8_t *out_metadata, + uint8_t *out_metadata_length); + +// Deprecated function prototypes + +__attribute__((__deprecated__("Please use `ENDORSEMENT_get_code_hash` instead."))) +SYSCALL unsigned int +os_endorsement_get_code_hash(unsigned char *buffer PLENGTH(32)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_get_public_key` instead."))) +SYSCALL unsigned int +os_endorsement_get_public_key(unsigned char index, + unsigned char *buffer PLENGTH(65), + unsigned char *length PLENGTH(1)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_get_public_key_certificate` instead."))) +SYSCALL unsigned int +os_endorsement_get_public_key_certificate(unsigned char index, + unsigned char *buffer + PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH), + unsigned char *length PLENGTH(1)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_key1_get_app_secret` instead."))) +SYSCALL unsigned int +os_endorsement_key1_get_app_secret(unsigned char *buffer PLENGTH(64)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_key1_sign_data` instead."))) +SYSCALL unsigned int +os_endorsement_key1_sign_data(unsigned char *src PLENGTH(srcLength), + unsigned int srcLength, + unsigned char *signature PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_key1_sign_without_code_hash` instead."))) +SYSCALL unsigned int +os_endorsement_key1_sign_without_code_hash(unsigned char *src PLENGTH(srcLength), + unsigned int srcLength, + unsigned char *signature + PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_key2_derive_sign_data` instead."))) +SYSCALL unsigned int +os_endorsement_key2_derive_sign_data(unsigned char *src PLENGTH(srcLength), + unsigned int srcLength, + unsigned char *signature PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); + +__attribute__((__deprecated__("Please use `ENDORSEMENT_get_metadata` instead."))) +SYSCALL unsigned int +os_endorsement_get_metadata(unsigned char index, unsigned char *buffer PLENGTH(8)); + +/********************** + * MACROS + **********************/ -/* ----------------------------------------------------------------------- */ -/* - ENDORSEMENT FEATURE - */ -/* ----------------------------------------------------------------------- */ - -#define ENDORSEMENT_MAX_ASN1_LENGTH (1 + 1 + 2 * (1 + 1 + 33)) - -SYSCALL unsigned int os_endorsement_get_code_hash(unsigned char *buffer PLENGTH(32)); -SYSCALL unsigned int os_endorsement_get_public_key(unsigned char index, - unsigned char *buffer PLENGTH(65), - unsigned char *length PLENGTH(1)); -SYSCALL unsigned int os_endorsement_get_public_key_certificate( - unsigned char index, - unsigned char *buffer PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH), - unsigned char *length PLENGTH(1)); -SYSCALL unsigned int os_endorsement_key1_get_app_secret(unsigned char *buffer PLENGTH(64)); -SYSCALL unsigned int os_endorsement_key1_sign_data(unsigned char *src PLENGTH(srcLength), - unsigned int srcLength, - unsigned char *signature - PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); -SYSCALL unsigned int os_endorsement_key1_sign_without_code_hash( - unsigned char *src PLENGTH(srcLength), - unsigned int srcLength, - unsigned char *signature PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); -SYSCALL unsigned int os_endorsement_key2_derive_sign_data(unsigned char *src PLENGTH(srcLength), - unsigned int srcLength, - unsigned char *signature - PLENGTH(ENDORSEMENT_MAX_ASN1_LENGTH)); - -SYSCALL unsigned int os_endorsement_get_metadata(unsigned char index, - unsigned char *buffer PLENGTH(8)); +#endif // OS_ENDORSEMENT_H_ diff --git a/src/retrocompatibility_endorsement.c b/src/retrocompatibility_endorsement.c new file mode 100644 index 00000000..12d43b59 --- /dev/null +++ b/src/retrocompatibility_endorsement.c @@ -0,0 +1,163 @@ +/** + * @file + * @brief + */ + +/********************* + * INCLUDES + *********************/ + +#include +#include "exceptions.h" +#include "os_types.h" +#include "os_endorsement.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * STATIC FONCTIONS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +/** + * @brief Retrocompatibility version of `os_endorsement_get_code_hash`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_get_code_hash instead. + */ +unsigned int os_endorsement_get_code_hash(unsigned char *buffer PLENGTH(32)) +{ + bolos_err_t error = ENDORSEMENT_get_code_hash((uint8_t *) buffer); + + if (error) { + THROW(error); + } + + return ENDORSEMENT_HASH_LENGTH; +} + +/** + * @brief Retrocompatibility version of `os_endorsement_get_public_key`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_get_public_key instead. + */ +unsigned int os_endorsement_get_public_key(unsigned char index, + unsigned char *buffer, + unsigned char *length) +{ + return ENDORSEMENT_get_public_key((ENDORSEMENT_slot_t) index, buffer, length); +} + +/** + * @brief Retrocompatibility version of `os_endorsement_get_public_key_certificate`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_get_public_key_certificate instead. + */ +unsigned int os_endorsement_get_public_key_certificate(unsigned char index, + unsigned char *buffer, + unsigned char *length) +{ + return ENDORSEMENT_get_public_key_certificate(index, buffer, length); +} + +/** + * @brief Retrocompatibility version of `os_endorsement_key1_get_app_secret`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_key1_get_app_secret instead. + */ +unsigned int os_endorsement_key1_get_app_secret(unsigned char *buffer) +{ + bolos_err_t error = ENDORSEMENT_key1_get_app_secret(buffer); + + if (error) { + THROW(error); + } + + return ENDORSEMENT_APP_SECRET_LENGTH; +} + +/** + * @brief Retrocompatibility version of `os_endorsement_key1_get_app_secret`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_key1_get_app_secret instead. + */ +unsigned int os_endorsement_key1_sign_data(unsigned char *src, + unsigned int srcLength, + unsigned char *signature) +{ + uint32_t out_signature_length = 0; + bolos_err_t error + = ENDORSEMENT_key1_sign_data(src, srcLength, signature, &out_signature_length); + + if (error) { + THROW(error); + } + + return out_signature_length; +} + +/** + * @brief Retrocompatibility version of `os_endorsement_key1_sign_without_code_hash`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_key1_sign_without_code_hash instead. + */ +unsigned int os_endorsement_key1_sign_without_code_hash(unsigned char *src, + unsigned int srcLength, + unsigned char *signature) +{ + uint32_t out_signature_length = 0; + bolos_err_t error + = ENDORSEMENT_key1_sign_without_code_hash(src, srcLength, signature, &out_signature_length); + + if (error) { + THROW(error); + } + + return out_signature_length; +} + +/** + * @brief Retrocompatibility version of `os_endorsement_key2_derive_sign_data`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_key2_derive_sign_data instead. + */ +unsigned int os_endorsement_key2_derive_sign_data(unsigned char *src, + unsigned int srcLength, + unsigned char *signature) +{ + uint32_t out_signature_length = 0; + bolos_err_t error + = ENDORSEMENT_key2_derive_sign_data(src, srcLength, signature, &out_signature_length); + + if (error) { + THROW(error); + } + + return out_signature_length; +} + +/** + * @brief Retrocompatibility version of `os_endorsement_get_metadata`. + * @warning Deprecated function. Please use \ref ENDORSEMENT_get_metadata instead. + */ +unsigned int os_endorsement_get_metadata(unsigned char index, unsigned char *buffer) +{ + uint8_t out_metadata_length = 0; + bolos_err_t error + = ENDORSEMENT_get_metadata((ENDORSEMENT_slot_t) index, buffer, &out_metadata_length); + + if (error) { + THROW(error); + } + + return out_metadata_length; +} diff --git a/src/syscalls.c b/src/syscalls.c index 69ac0819..970a752a 100644 --- a/src/syscalls.c +++ b/src/syscalls.c @@ -35,6 +35,7 @@ #endif // HAVE_VSS #include "os_seed.h" #include "ox_crc.h" +#include "os_endorsement.h" #include unsigned int SVC_Call(unsigned int syscall_id, void *parameters); @@ -1413,79 +1414,94 @@ bolos_err_t os_pki_get_info(uint8_t *key_usage, } #endif // HAVE_LEDGER_PKI -unsigned int os_endorsement_get_code_hash(unsigned char *buffer) +bolos_err_t ENDORSEMENT_get_code_hash(uint8_t *out_hash) { - unsigned int parameters[2]; - parameters[0] = (unsigned int) buffer; - parameters[1] = 0; + unsigned int parameters[1]; + parameters[0] = (unsigned int) out_hash; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_code_hash_ID, parameters); } -unsigned int os_endorsement_get_public_key(unsigned char index, - unsigned char *buffer, - unsigned char *length) +bolos_err_t ENDORSEMENT_get_public_key(ENDORSEMENT_slot_t slot, + uint8_t *out_public_key, + uint8_t *out_public_key_length) { unsigned int parameters[3]; - parameters[0] = (unsigned int) index; - parameters[1] = (unsigned int) buffer; - parameters[2] = (unsigned int) length; + parameters[0] = (unsigned int) slot; + parameters[1] = (unsigned int) out_public_key; + parameters[2] = (unsigned int) out_public_key_length; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_public_key_ID, parameters); } -unsigned int os_endorsement_get_public_key_certificate(unsigned char index, - unsigned char *buffer, - unsigned char *length) +bolos_err_t ENDORSEMENT_get_public_key_certificate(ENDORSEMENT_slot_t endorsement_slot, + uint8_t *out_buffer, + uint8_t *out_length) { unsigned int parameters[3]; - parameters[0] = (unsigned int) index; - parameters[1] = (unsigned int) buffer; - parameters[2] = (unsigned int) length; + parameters[0] = (unsigned int) endorsement_slot; + parameters[1] = (unsigned int) out_buffer; + parameters[2] = (unsigned int) out_length; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_public_key_certificate_ID, parameters); } -unsigned int os_endorsement_key1_get_app_secret(unsigned char *buffer) +bolos_err_t ENDORSEMENT_key1_get_app_secret(uint8_t *out_secret) { - unsigned int parameters[2]; - parameters[0] = (unsigned int) buffer; - parameters[1] = 0; + unsigned int parameters[1]; + parameters[0] = (unsigned int) out_secret; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_get_app_secret_ID, parameters); } -unsigned int os_endorsement_key1_sign_data(unsigned char *src, - unsigned int srcLength, - unsigned char *signature) +bolos_err_t ENDORSEMENT_key1_sign_data(uint8_t *data, + uint32_t data_length, + uint8_t *out_signature, + uint32_t *out_signature_length) { - unsigned int parameters[3]; - parameters[0] = (unsigned int) src; - parameters[1] = (unsigned int) srcLength; - parameters[2] = (unsigned int) signature; + unsigned int parameters[4]; + parameters[0] = (unsigned int) data; + parameters[1] = data_length; + parameters[2] = (unsigned int) out_signature; + parameters[3] = (unsigned int) out_signature_length; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_sign_data_ID, parameters); } -unsigned int os_endorsement_key1_sign_without_code_hash(unsigned char *src, - unsigned int srcLength, - unsigned char *signature) +bolos_err_t ENDORSEMENT_key1_sign_without_code_hash(uint8_t *data, + uint32_t data_length, + uint8_t *out_signature, + uint32_t *out_signature_length) { - unsigned int parameters[3]; - parameters[0] = (unsigned int) src; - parameters[1] = (unsigned int) srcLength; - parameters[2] = (unsigned int) signature; + unsigned int parameters[4]; + parameters[0] = (unsigned int) data; + parameters[1] = data_length; + parameters[2] = (unsigned int) out_signature; + parameters[3] = (unsigned int) out_signature_length; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key1_sign_without_code_hash_ID, parameters); } -unsigned int os_endorsement_key2_derive_sign_data(unsigned char *src, - unsigned int srcLength, - unsigned char *signature) +bolos_err_t ENDORSEMENT_key2_derive_sign_data(uint8_t *data, + uint32_t data_length, + uint8_t *out_signature, + uint32_t *out_signature_length) { - unsigned int parameters[3]; - parameters[0] = (unsigned int) src; - parameters[1] = (unsigned int) srcLength; - parameters[2] = (unsigned int) signature; + unsigned int parameters[4]; + parameters[0] = (unsigned int) data; + parameters[1] = (unsigned int) data_length; + parameters[2] = (unsigned int) out_signature; + parameters[3] = (unsigned int) out_signature_length; return (unsigned int) SVC_Call(SYSCALL_os_endorsement_key2_derive_sign_data_ID, parameters); } +bolos_err_t ENDORSEMENT_get_metadata(ENDORSEMENT_slot_t slot, + uint8_t *out_metadata, + uint8_t *out_metadata_length) +{ + unsigned int parameters[3]; + parameters[0] = (unsigned int) slot; + parameters[1] = (unsigned int) out_metadata; + parameters[2] = (unsigned int) out_metadata_length; + return (bolos_err_t) SVC_Call(SYSCALL_os_endorsement_get_metadata_ID, parameters); +} + void os_perso_set_pin(unsigned int identity, const unsigned char *pin, unsigned int length, @@ -2173,14 +2189,6 @@ bolos_bool_t os_aem_is_pin_validated(void) } #endif // HAVE_AEM_PIN -unsigned int os_endorsement_get_metadata(unsigned char index, unsigned char *buffer) -{ - unsigned int parameters[2]; - parameters[0] = (unsigned int) index; - parameters[1] = (unsigned int) buffer; - return (unsigned int) SVC_Call(SYSCALL_os_endorsement_get_metadata_ID, parameters); -} - #if defined(HAVE_LANGUAGE_PACK) void list_language_packs(UX_LOC_LANGUAGE_PACK_INFO *packs) {