From 3d2615cd5b00fd08604115cd23df53da327db751 Mon Sep 17 00:00:00 2001 From: Junyeon Lee Date: Tue, 14 Mar 2017 13:43:52 +0900 Subject: [PATCH] s5j/sss: add static library and header files This commit adds driver and header files for SSS released at Dec 30, 2016. Change-Id: I69dcc5045528aee1b27069e5250393da703104d8 Signed-off-by: Junyeon Lee --- os/arch/arm/src/s5j/Make.defs | 4 + os/arch/arm/src/s5j/soc/sss/isp_define.h | 89 ++++++++++++ .../arm/src/s5j/soc/sss/isp_driver_aes_securekey.h | 30 ++++ .../src/s5j/soc/sss/isp_driver_dh_encryptedkey.h | 20 +++ .../arm/src/s5j/soc/sss/isp_driver_dh_securekey.h | 41 ++++++ .../src/s5j/soc/sss/isp_driver_ecdh_encryptedkey.h | 17 +++ .../src/s5j/soc/sss/isp_driver_ecdh_securekey.h | 18 +++ .../s5j/soc/sss/isp_driver_ecdsa_encryptedkey.h | 27 ++++ .../src/s5j/soc/sss/isp_driver_ecdsa_securekey.h | 26 ++++ .../arm/src/s5j/soc/sss/isp_driver_encryptedkey.h | 20 +++ os/arch/arm/src/s5j/soc/sss/isp_driver_error.h | 160 +++++++++++++++++++++ os/arch/arm/src/s5j/soc/sss/isp_driver_flash.h | 26 ++++ os/arch/arm/src/s5j/soc/sss/isp_driver_hash.h | 22 +++ .../src/s5j/soc/sss/isp_driver_hmac_securekey.h | 20 +++ os/arch/arm/src/s5j/soc/sss/isp_driver_rng.h | 18 +++ .../arm/src/s5j/soc/sss/isp_driver_rsa_securekey.h | 29 ++++ .../src/s5j/soc/sss/isp_driver_secure_storage.h | 56 ++++++++ .../s5j/soc/sss/isp_driver_secure_storage_cert.h | 17 +++ .../s5j/soc/sss/isp_driver_secure_storage_data.h | 19 +++ .../soc/sss/isp_driver_secure_storage_factorykey.h | 23 +++ .../s5j/soc/sss/isp_driver_secure_storage_key.h | 21 +++ os/arch/arm/src/s5j/soc/sss/isp_driver_system.h | 20 +++ os/arch/arm/src/s5j/soc/sss/isp_oid.h | 75 ++++++++++ os/arch/arm/src/s5j/soc/sss/isp_sss_map.h | 39 +++++ os/arch/arm/src/s5j/soc/sss/isp_type.h | 70 +++++++++ os/arch/arm/src/s5j/soc/sss/isp_util.h | 41 ++++++ os/arch/arm/src/s5j/soc/sss/libispdriver.a | Bin 0 -> 278550 bytes os/arch/arm/src/s5j/soc/sss/mb_cmd_aes.h | 77 ++++++++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_aes_securekey.h | 77 ++++++++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_dh.h | 32 +++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_dh_securekey.h | 79 ++++++++++ .../arm/src/s5j/soc/sss/mb_cmd_ecdh_securekey.h | 26 ++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_ecdsa.h | 43 ++++++ .../arm/src/s5j/soc/sss/mb_cmd_ecdsa_securekey.h | 43 ++++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_hash.h | 52 +++++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac.h | 27 ++++ .../arm/src/s5j/soc/sss/mb_cmd_hmac_securekey.h | 32 +++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_rng.h | 24 ++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa.h | 38 +++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa_securekey.h | 72 ++++++++++ .../src/s5j/soc/sss/mb_cmd_secure_storage_cert.h | 40 ++++++ .../src/s5j/soc/sss/mb_cmd_secure_storage_data.h | 41 ++++++ .../s5j/soc/sss/mb_cmd_secure_storage_factorykey.h | 46 ++++++ .../src/s5j/soc/sss/mb_cmd_secure_storage_key.h | 46 ++++++ os/arch/arm/src/s5j/soc/sss/mb_cmd_system.h | 25 ++++ 45 files changed, 1768 insertions(+) create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_define.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_aes_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_dh_encryptedkey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_dh_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_encryptedkey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_encryptedkey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_encryptedkey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_error.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_flash.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_hash.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_hmac_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_rng.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_rsa_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_cert.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_data.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_factorykey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_key.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_driver_system.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_oid.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_sss_map.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_type.h create mode 100644 os/arch/arm/src/s5j/soc/sss/isp_util.h create mode 100644 os/arch/arm/src/s5j/soc/sss/libispdriver.a create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_aes.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_aes_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_dh.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_dh_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_ecdh_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_ecdsa.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_ecdsa_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_hash.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_rng.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa_securekey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_cert.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_data.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_factorykey.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_key.h create mode 100644 os/arch/arm/src/s5j/soc/sss/mb_cmd_system.h diff --git a/os/arch/arm/src/s5j/Make.defs b/os/arch/arm/src/s5j/Make.defs index 96b8e6c..e195035 100644 --- a/os/arch/arm/src/s5j/Make.defs +++ b/os/arch/arm/src/s5j/Make.defs @@ -212,6 +212,10 @@ ifeq ($(CONFIG_S5J_DMA),y) CHIP_CSRCS += s5j_dma.c endif +ifeq ($(CONFIG_S5J_SSS),y) +EXTRA_LIBS += chip/soc/sss/libispdriver.a +endif + EXTRA_LIBS += chip/soc/wireless/libwifidriver.a EXTRA_LIBS += chip/soc/wireless/libwifistack.a EXTRA_LIBS += chip/soc/wireless/libwifiapi.a diff --git a/os/arch/arm/src/s5j/soc/sss/isp_define.h b/os/arch/arm/src/s5j/soc/sss/isp_define.h new file mode 100644 index 0000000..3799f2c --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_define.h @@ -0,0 +1,89 @@ +/*! + * @file isp_define.h + * @brief Headerfile : definitions for ISP + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + * @version v0.90 : 2016.9.03 2nd. release version + * + */ + +#ifndef ISP_DEFINE_H +#define ISP_DEFINE_H_ + +//! ********** Constant Variables ********** +#define MAX_KEY_WSIZE 17 +#define MAX_SIGNATURE_WSIZE 17 + +//! ********** Index Variables ********** + +// Hash Function + +#define SHA1 (0x1) +#define SHA2 (0x2) +#define SHA3 (0x3) + +#define HASH160 (0x1) +#define HASH224 (0x2) +#define HASH256 (0x3) +#define HASH384 (0x4) +#define HASH512 (0x5) +#define HMAC (0x1) + +#define SHA1_160 (((SHA1<<4)|(HASH160))<<8) //0x00001100 +#define SHA2_224 (((SHA2<<4)|(HASH224))<<8) //0x00002200 +#define SHA2_256 (((SHA2<<4)|(HASH256))<<8) //0x00002300 +#define SHA2_384 (((SHA2<<4)|(HASH384))<<8) //0x00002400 +#define SHA2_512 (((SHA2<<4)|(HASH512))<<8) //0x00002500 +#define SHA3_224 (((SHA3<<4)|(HASH224))<<8) //0x00003200 +#define SHA3_256 (((SHA3<<4)|(HASH256))<<8) //0x00003300 +#define SHA3_384 (((SHA3<<4)|(HASH384))<<8) //0x00003400 +#define SHA3_512 (((SHA3<<4)|(HASH512))<<8) //0x00003500 + + +#define HMAC_SHA1_160 ((((SHA1<<4)|(HASH160))<<8) | (HMAC)<<16) //0x00011100 +#define HMAC_SHA2_256 ((((SHA2<<4)|(HASH256))<<8) | (HMAC)<<16) //0x00012300 +#define HMAC_SHA2_384 ((((SHA2<<4)|(HASH384))<<8) | (HMAC)<<16) //0x00012400 +#define HMAC_SHA2_512 ((((SHA2<<4)|(HASH512))<<8) | (HMAC)<<16) //0x00012500 + + +// ECC Algorithm ID +#define ECDSA (0x1) +#define ECDH (0x2) +#define PKGEN (0x3) + +// ECC Curve ID +#define ECC192 (0x1) +#define ECC224 (0x2) +#define ECC256 (0x3) +#define ECC384 (0x4) +#define ECC521 (0x5) + +#define ECDSA_192 ((ECDSA<<4)|(ECC192)) //0x11 +#define ECDSA_224 ((ECDSA<<4)|(ECC224)) //0x12 +#define ECDSA_256 ((ECDSA<<4)|(ECC256)) //0x13 +#define ECDSA_384 ((ECDSA<<4)|(ECC384)) //0x14 +#define ECDSA_521 ((ECDSA<<4)|(ECC521)) //0x15 + +#define ECDH_192 ((ECDH<<4)|(ECC192)) //0x21 +#define ECDH_224 ((ECDH<<4)|(ECC224)) //0x22 +#define ECDH_256 ((ECDH<<4)|(ECC256)) //0x23 +#define ECDH_384 ((ECDH<<4)|(ECC384)) //0x24 +#define ECDH_521 ((ECDH<<4)|(ECC521)) //0x25 + + +#define GET_ECC_CURVE(OID) ((OID )&0x07) +#define GET_ECC_ALG(OID) ((OID>> 4)&0x0F) + +#define GET_HASH_SIZE(OID) ((OID>> 8)&0x07) +#define GET_HASH_ALG(OID) ((OID>>12)&0x0F) + +#define Is_HMAC_ALG(OID) ((OID>>16)&0x0F) + +#define Is_ECC_BP(OID) (OID&0x40) + +#define RSP_FAIL (0xF1) +#define RSP_SUCCESS (0xA1) + + +#endif /*ISP_DEFINE_H_*/ + diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_aes_securekey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_aes_securekey.h new file mode 100644 index 0000000..e8854e7 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_aes_securekey.h @@ -0,0 +1,30 @@ +/*! + * @file isp_driver_aes_securekey.h + * @brief Headerfile : isp driver for aes securekey + * @author jinsu.hyun + * @version v0.10 : 2016.7.25 Init + * @version v0.20 : 2016.7.29 support securekey + * @version v0.50 : 2016.8.13 Init. release version + * @version v0.90 : 2016.9.03 2nd. release version + */ + +#ifndef ISP_DRIVER_AES_SECUREKEY_H_ +#define ISP_DRIVER_AES_SECUREKEY_H_ + +#include "mb_cmd_aes_securekey.h" + +// security api + +int isp_aes_generate_key_securekey(unsigned int key_byte_len, unsigned int key_index); + +int isp_aes_encrypt_securekey(struct sAES_PARAM *aes_param, unsigned int index); +int isp_aes_decrypt_securekey(struct sAES_PARAM *aes_param, unsigned int index); + +int isp_aes_ecb_securekey(struct sAES_PARAM *aes_param, unsigned int enc, unsigned int key_index); +int isp_aes_cbc_securekey(struct sAES_PARAM *aes_param, unsigned int enc, unsigned int key_index); +int isp_aes_ctr_securekey(struct sAES_PARAM *aes_param, unsigned int enc, unsigned int key_index); +int isp_aes_xts_securekey(struct sAES_PARAM *aes_param, unsigned int enc, unsigned int key_index); +int isp_aes_ccm_securekey(struct sAES_PARAM *aes_param, unsigned int enc, unsigned int key_index); +int isp_aes_gcm_securekey(struct sAES_PARAM *aes_param, unsigned int enc, unsigned int key_index); + +#endif /* ISP_DRIVER_AES_SECUREKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_dh_encryptedkey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_dh_encryptedkey.h new file mode 100644 index 0000000..0163190 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_dh_encryptedkey.h @@ -0,0 +1,20 @@ +/*! + * @file isp_driver_dh_encryptedkey.h + * @brief Headerfile : isp driver for dh encryptedkey + * @author jinsu.hyun + * @version v0.00 : 2017.01.19 Init. release version + */ + +#ifndef _ISP_DRIVER_DH_ENCRYPTEDKEY_H_ +#define _ISP_DRIVER_DH_ENCRYPTEDKEY_H_ + +#include "mb_cmd_dh_securekey.h" + +int isp_dh_generate_param_encryptedkey(struct sDH_PARAM *o_dh_param, unsigned char *encryptedkey); +int isp_dh_generate_keypair_userparam_encryptedkey(struct sDH_PARAM *i_dh_param, unsigned char *encryptedkey); +int isp_dh_generate_keypair_encryptedparam(struct sDH_PARAM *o_dh_param, unsigned char *encryptedkey); +int isp_dh_get_pubkey_encryptedparam(struct sDH_PARAM *o_dh_param, unsigned char *encryptedkey); +int isp_dh_compute_shared_secret_encryptedkey(unsigned char *shared_secret, unsigned int* shared_secret_byte_len, struct sDH_PARAM dh_publickey, unsigned char *encryptedkey); + + +#endif /* _ISP_DRIVER_DH_ENCRYPTEDKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_dh_securekey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_dh_securekey.h new file mode 100644 index 0000000..7f4164f --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_dh_securekey.h @@ -0,0 +1,41 @@ +/*! + * @file isp_driver_dh_securekey.h + * @brief Headerfile : isp driver for dh securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_DH_SECUREKEY_H_ +#define ISP_DRIVER_DH_SECUREKEY_H_ + +#include "mb_cmd_dh_securekey.h" + + +int isp_dh_generate_param_securekey(struct sDH_PARAM *o_dh_param, unsigned int dh_param_index); +/* + * input fixed dh_param p + * output random generator g & key pair + */ + +int isp_dh_generate_keypair_secureparam(struct sDH_PARAM *o_dh_param, unsigned int key_index); +/* + * output dh_param p, g, pukey + */ + +//added +int isp_dh_generate_keypair_userparam_securestorage(struct sDH_PARAM *i_dh_param, unsigned int dh_param_index); +/* + * input dh_param p, g & output dh_param pukey + */ + + +int isp_dh_get_pubkey_securestorage(struct sDH_PARAM *o_dh_param, unsigned int key_index); +/* + * get public key from existing key pair from secure storage + */ + +int isp_dh_compute_shared_secret_securekey(unsigned char *shared_secret, unsigned int* shared_secret_byte_len, struct sDH_PARAM dh_publickey, unsigned int key_index); + + + +#endif /* ISP_DRIVER_DH_SECUREKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_encryptedkey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_encryptedkey.h new file mode 100644 index 0000000..e7ad72b --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_encryptedkey.h @@ -0,0 +1,17 @@ +/*! + * @file isp_driver_ecdh_encryptedkey.h + * @brief Headerfile : isp driver for ecdh encryptedkey + * @author jinsu.hyun + * @version v0.00 : 2017.01.19 Init. release version + */ + +#ifndef _ISP_DRIVER_ECDH_ENCRYPTEDKEY_H_ +#define _ISP_DRIVER_ECDH_ENCRYPTEDKEY_H_ + +#include "mb_cmd_ecdh_securekey.h" + +// ====================================== +// Function +// ====================================== +int isp_compute_ecdh_encryptedkey(unsigned char* shared_secret, unsigned int *shared_secret_byte_len, struct sECC_KEY ecc_publickey, unsigned char *encryptedkey); +#endif /* _ISP_DRIVER_ECDH_ENCRYPTEDKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_securekey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_securekey.h new file mode 100644 index 0000000..31ed6ad --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdh_securekey.h @@ -0,0 +1,18 @@ +/*! + * @file isp_driver_ecdh_securekey.h + * @brief Headerfile : isp driver for ecdh securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_ECDH_SECUREKEY_H_ +#define ISP_DRIVER_ECDH_SECUREKEY_H_ + +#include "mb_cmd_ecdh_securekey.h" + +// ====================================== +// Function +// ====================================== +int isp_compute_ecdh_securekey(unsigned char* shared_secret, unsigned int *shared_secret_byte_len, struct sECC_KEY ecc_publickey, unsigned int key_index); + +#endif /* ISP_DRIVER_ECDH_SECUREKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_encryptedkey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_encryptedkey.h new file mode 100644 index 0000000..af7ef0f --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_encryptedkey.h @@ -0,0 +1,27 @@ +/*! + * @file isp_driver_ecdsa_encryptedkey.h + * @brief Headerfile : isp driver for ecdsa encryptedkey + * @author jinsu.hyun + * @version v0.00 : 2017.01.19 Init. release version + */ + +#ifndef _ISP_DRIVER_ECDSA_ENCRYPTEDKEY_H_ +#define _ISP_DRIVER_ECDSA_ENCRYPTEDKEY_H_ + +#include "mb_cmd_ecdsa_securekey.h" + +// ====================================== +// Function +// ====================================== + + +int isp_ecdsa_sign_encryptedkey(struct sECC_SIGN * signature, unsigned char * msg, unsigned int msg_byte_len, unsigned char *encryptedkey); +int isp_ecdsa_verify_encryptedkey(struct sECC_SIGN * signature, unsigned char * msg, unsigned int msg_byte_len, unsigned char *encryptedkey); + +int isp_ecdsa_sign_md_encryptedkey(struct sECC_SIGN * signature, unsigned char * msg_digest, unsigned int msg_digest_byte_len, unsigned char *encryptedkey); +int isp_ecdsa_verify_md_encryptedkey(struct sECC_SIGN * signature, unsigned char * msg_digest, unsigned int msg_digest_byte_len, unsigned char *encryptedkey); + +int isp_ecdsa_generate_key_encryptedkey(unsigned int object_id, unsigned char *encryptedkey); +int isp_ecdsa_get_publickey_encryptedkey(struct sECC_KEY *ecc_publickey, unsigned int object_id, unsigned char *encryptedkey); + +#endif /* _ISP_DRIVER_ECDSA_ENCRYPTEDKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_securekey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_securekey.h new file mode 100644 index 0000000..90801a9 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_ecdsa_securekey.h @@ -0,0 +1,26 @@ +/*! + * @file isp_driver_ecdsa_securekey.h + * @brief Headerfile : isp driver for ecdsa securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + * @version v0.60 : 2016.12.23 Support sign/verify with msg_disgest + */ + +#ifndef ISP_DRIVER_ECDSA_SECUREKEY_H_ +#define ISP_DRIVER_ECDSA_SECUREKEY_H_ + +#include "mb_cmd_ecdsa_securekey.h" + +// ====================================== +// Function +// ====================================== +int isp_ecdsa_sign_securekey(struct sECC_SIGN * signature, unsigned char * msg, unsigned int msg_byte_len, unsigned int key_index); +int isp_ecdsa_verify_securekey(struct sECC_SIGN * signature, unsigned char * msg, unsigned int msg_byte_len, unsigned int key_index); + +int isp_ecdsa_sign_md_securekey(struct sECC_SIGN * signature, unsigned char * msg_digest, unsigned int msg_digest_byte_len, unsigned int key_index); +int isp_ecdsa_verify_md_securekey(struct sECC_SIGN * signature, unsigned char * msg_digest, unsigned int msg_digest_byte_len, unsigned int key_index); + +int isp_ecdsa_generate_key_securekey(unsigned int key_index, unsigned int object_id); +int isp_ecdsa_get_publickey_securekey(struct sECC_KEY *ecc_publickey, unsigned int key_index, unsigned int object_id); + +#endif /* ISP_DRIVER_ECDSA_SECUREKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_encryptedkey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_encryptedkey.h new file mode 100644 index 0000000..262e6b1 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_encryptedkey.h @@ -0,0 +1,20 @@ +/*! + * @file isp_driver_encryptedkey.h + * @brief Headerfile : isp driver for setting encryptedkey + * @author jinsu.hyun + * @version v0.00 : 2017.01.19 Init. release version + */ + +#ifndef _ISP_DRIVER_ENCRYPTEDKEY_H_ +#define _ISP_DRIVER_ENCRYPTEDKEY_H_ + + +// ====================================== +// Function +// ====================================== + +int isp_set_encryptedkey(unsigned char *key, unsigned int key_byte_len, unsigned int key_type, unsigned char *encryptedkey); +int isp_get_encryptedkey(unsigned int *object_id, unsigned int key_type, unsigned char *encryptedkey); +int isp_set_genkey_encryptedkey(unsigned int key_type, unsigned char *encryptedkey); + +#endif /* _ISP_DRIVER_ENCRYPTEDKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_error.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_error.h new file mode 100644 index 0000000..b6f6ec3 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_error.h @@ -0,0 +1,160 @@ +/*! + * @file isp_driver_error.h + * @brief Headerfile : isp driver for error messages + * @author jinsu.hyun + * @version v0.01 : 2015.7.7 + * @version v0.10 : 2016.7.15 pre-beta release + * @version v0.50 : 2016.8.13 Init. release version + * @version v1.00 : 2016.9.27 release version v1.0 + */ + + +#ifndef ISP_DRIVER_ERROR_H_ +#define ISP_DRIVER_ERROR_H_ + +// AES +#define ERROR_AES_INVALID_BLOCK_LEN (0x000133D1) +#define ERROR_AES_INVALID_RSP_BLOCK_LEN (0x000233D1) +#define ERROR_AES_INVALID_MSG_LEN (0x000333D1) +#define ERROR_AES_INVALID_MODE (0x000433D1) +#define ERROR_AES_INVALID_KEY_LEN (0x000533D1) +#define ERROR_AES_INVALID_AAD_LEN (0x000633D1) +#define ERROR_AES_INVALID_IV_LEN (0x000733D1) +#define ERROR_AES_INVALID_INDEX (0x000833D1) +#define ERROR_AES_INVALID_TAG_LEN (0x000933D1) + +// Hash +#define ERROR_HASH_INVALID_MODE (0x000131D1) +#define ERROR_HASH_INVALID_BLOCK_LEN (0x000231D1) +#define ERROR_HASH_INVALID_MSG_LEN (0x000331D1) + +// HMAC +#define ERROR_HMAC_INVALID_MODE (0x000132D1) +#define ERROR_HMAC_INVALID_KEY_LEN (0x000232D1) +#define ERROR_HMAC_INVALID_BLOCK_LEN (0x000332D1) +#define ERROR_HMAC_INVALID_INDEX (0x000432D1) +#define ERROR_HMAC_INVALID_RSP_BLOCK_LEN (0x000532D1) + +// DH +#define ERROR_DH_INVALID_PRIME_LEN (0x000125D1) +#define ERROR_DH_INVALID_PUBKEY_LEN (0x000225D1) +#define ERROR_DH_INVALID_GENERATOR_LEN (0x000325D1) +#define ERROR_DH_INVALID_PRIME (0x000425D1) +#define ERROR_DH_INVALID_PUBKEY (0x000525D1) +#define ERROR_DH_INVALID_GENERATOR (0x000625D1) + + +// ECDSA +#define ERROR_ECDSA_INVALID_MSG_LEN (0x000111D1) +#define ERROR_ECDSA_INVALID_SIGNATURE_LEN (0x000311D1) +#define ERROR_ECDH_INVALID_PUBKEY_LEN (0x000411D1) +#define ERROR_ECDH_INVALID_PUBKEY (0x000511D1) + +// RSA +#define ERROR_RSA_INVALID_CIPHER_LEN (0x000151D1) +#define ERROR_RSA_INVALID_MSG_LEN (0x000251D1) +#define ERROR_RSA_INVALID_SIGN_LEN (0x000351D1) +#define ERROR_RSA_INVALID_PUKEY (0x000551D1) +#define ERROR_RSA_INVALID_PAD_SELECTION (0x000451D1) + + +// RNG +#define ERROR_RNG_INVALID_RANDOM_REQUEST (0x000161D1) + +// Common +#define ERROR_SSKeyID_InputID_MISSMATCH (0x000171D1) +#define ERROR_INVALID_OID (0x000271D1) + +// Secure Storage +#define ERROR_SSTORAGE_INVALID_SLOT_INDEX (0x00F1A1D1) +#define ERROR_SSTORAGE_INVALID_DATA_LEN (0x00F2A1D1) +#define ERROR_SSTORAGE_INVALID_TYPE (0x00F3A1D1) +#define ERROR_SSTORAGE_DATA_INVALID_DATA_LEN (0x0002A1D1) +#define ERROR_SSTORAGE_CERT_INVALID_DATA_LEN (0x0003A2D1) +#define ERROR_SSTORAGE_KEY_INVALID_DATA_LEN (0x0004A3D1) +#define ERROR_SSTORAGE_KEY_INVALID_KEY_LEN (0x0005A3D1) +#define ERROR_SSTORAGE_KEY_INVALID_KEY_TYPE (0x0006A3D1) +#define ERROR_SSTORAGE_FACTORYKEY_PBKEY_INVALID_DATA_LEN (0x0007A2D1) +#define ERROR_SSTORAGE_QSPI_WRITE (0x0008A2D1) +#define ERROR_SSTORAGE_SFS_FOPEN (0x0009A2D1) +#define ERROR_SSTORAGE_SFS_FSEEK (0x000AA2D1) +#define ERROR_SSTORAGE_SFS_FREAD (0x000BA2D1) +#define ERROR_SSTORAGE_SFS_FWRITE (0x000CA2D1) +// System Function +#define ERROR_SYSTEM_INVALID_DATA_LEN (0x000201D1) +#define ERROR_SYSTEM_MAILBOX_BUSY (0x000100D1) + + + +// Error from FW +#define FW_ERROR_ISP_INVALID_FUNCID00 (0x801000F1) +#define FW_ERROR_ISP_INVALID_FUNCID01 (0x801100F1) +#define FW_ERROR_ISP_INVALID_FUNCID02 (0x801200F1) +#define FW_ERROR_ISP_INVALID_FUNCID03 (0x801300F1) +#define FW_ERROR_ISP_INVALID_DATASIZE (0x801400F1) +#define FW_ERROR_ISP_FW_BODYSIZE (0x801500F1) +#define FW_ERROR_ISP_FW_ROLLBACK_CNT (0x801600F1) +#define FW_ERROR_ISP_FW_INVALID_PUBLICKEY (0x801700F1) +#define FW_ERROR_ISP_RESTORE_INTEGRITY_FAIL (0x801800F1) +#define FW_ERROR_ISP_IP_BUSY (0x801900F1) +#define FW_ERROR_ISP_SRAM_CMD_NOT_SUPPORTED (0x801A00F1) + +#define FW_ERROR_INVALID_FUNCTION (0x000100f1) +#define FW_ERROR_FW_VERIFY (0x001400f1) +#define FW_ERROR_RESTORE_FAIL (0x001800f1) +#define FW_ERROR_IP_BUSY (0x001900f1) +#define FW_ERROR_INVALID_OID (0x003000f1) +#define FW_ERROR_INVALID_INPUT (0x003400f1) +#define FW_ERROR_INPUT_SETTING (0x004000f1) +#define FW_ERROR_PRNG (0x005000f1) +#define FW_FAIL_INVALID_SIGNATURE (0x006000f1) +#define FW_FAIL_INFINITY_POINT (0x006100f1) +#define FW_FAIL_NOT_ON_ECC_CURVE (0x006200f1) + +// SRAM error +#define FW_ERROR_INVALID_EXEC_ORDER (0x80AF00F1) +#define FW_ERROR_OVER_VALID_RSA_MSGLEN (0x803500F1) +#define FW_ERROR_INVALID_RSA_MODLEN (0x803600F1) +#define FW_ERROR_Input_Public_is_not_odd (0x803700F1) +#define FW_ERROR_OVER_VALID_RSA_Saltlen (0x803800F1) +#define FW_ERROR_NO_PUKEY (0x803900F1) +#define FW_FAIL_OVER_MR_TRIALS (0x805600F1) +#define FW_FAIL_OVER_DH_RETRIALS (0x805600F1) +#define FW_FAIL_OVER_ECC_RETRIALS (0x805600F1) +#define FW_FAIL_NO_OUTPUT_KEY (0x805700F1) +#define FW_FAIL_OVER_GEN_RETRIALS (0x805800F1) +#define FW_ERROR_INVALID_RSASIGNATURE_0xBC (0x806400F1) +#define FW_ERROR_INVALID_RSASIGNATURE_lsb (0x806500F1) +#define FW_ERROR_INVALID_RSANONZERO_PS (0x806600F1) +#define FW_ERROR_INVALID_RSADB_SPLITTER (0x806700F1) +#define FW_ERROR_INVALID_SIGNATURE_BLEN (0x806800F1) +#define FW_ERROR_INVALID_CIPHER (0x806900F1) +#define FW_ERROR_INVALID_SEQUENCE (0x80ff00F1) +#define FW_ERROR_DER2INT_PARSE (0x80fe00F1) +#define FW_ERROR_AES_INVALID_KEYSEL (0x80D000F1) +#define FW_ERROR_AES_INVALID_KEY_LEN (0x80D100F1) +#define FW_ERROR_AES_INVALID_DIR_MODE (0x80D200F1) +#define FW_ERROR_AES_INVLIAD_SWAP (0x80D300F1) +#define FW_ERROR_AES_INVALID_MODE (0x80D400F1) +#define FW_ERROR_AES_INVALID_TAG (0x80D500F1) +#define FW_ERROR_AES_INVALID_BLOCK_LEN (0x80D600F1) +#define FW_ERROR_AES_KM_BUSY (0x80D700F1) +#define FW_ERROR_AES_KM_INIT (0x80D800F1) +#define FW_ERROR_SSTORAGE_DATA_INVALID_SLOT_INDEX (0x80E100F1) +#define FW_ERROR_SSTORAGE_CERT_INVALID_SLOT_INDEX (0x80E200F1) +#define FW_ERROR_SSTORAGE_KEY_INVALID_KEY_LEN (0x80E300F1) +#define FW_ERROR_SSTORAGE_KEY_INVALID_MODE (0x80E400F1) +#define FW_ERROR_SSTORAGE_INVALID_DATA_TYPE (0x80E500F1) +#define FW_ERROR_SSTORAGE_KEY_INVALID_KEYTYPE (0x80E600F1) +#define FW_ERROR_SSTORAGE_KEY_INVALID_SLOT_INDEX (0x80E700F1) +#define FW_ERROR_SSTORAGE_FACTORYKEY_INVALID_HMAC (0x80E800F1) +#define FW_ERROR_SSTORAGE_FACTORYKEY_INVALID_ENCODING (0x80E900F1) +#define FW_ERROR_SSTORAGE_FACTORYKEY_INVALID_KEYTYPE (0x80EA00F1) +#define FW_ERROR_RNG_INVALID_LEN (0x80f100F1) +#define FW_ERROR_KEYGEN_INVALID_KEYLEN (0x80f200F1) +#define FW_ERROR_PKA_IP_BUSY (0x80B100F1) +#define FW_ERROR_HASH_IP_BUSY (0x80B200F1) +#define FW_ERROR_PRNG_IP_BUSY (0x80B300F1) + + +#endif /* ISP_DRIVER_ERROR_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_flash.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_flash.h new file mode 100644 index 0000000..dde7ed8 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_flash.h @@ -0,0 +1,26 @@ +/*! + * @file isp_driver_flash.h + * @brief Headerfile : isp driver for flash memory + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef DRIVER_FLASH_H_ +#define DRIVER_FLASH_H_ + +#ifndef SSS_POR +#define SSS_POR +#endif + +#if defined(SSS_POR) +int SFS_Secure_Write_POR(const char *file_name, unsigned char *src_addr, unsigned int byte_len); +int SFS_Secure_Read_POR(const char *file_name, unsigned char *dst_addr, unsigned int byte_len); + +#else +int SFS_Secure_Read(const char *file_name, unsigned int dst_addr, unsigned int *byte_len); +int SFS_Secure_Write(const char *file_name, unsigned int dst_addr, unsigned int byte_len); + +#endif /* SSS_POR */ + +#endif /* DRIVER_FLASH_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_hash.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_hash.h new file mode 100644 index 0000000..4400589 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_hash.h @@ -0,0 +1,22 @@ +/*! + * @file isp_driver_hash.h + * @brief Headerfile : isp driver for hash + * @author jinsu.hyun + * @version v0.01 : 2015.7.7 + * @version v0.10 : 2016.7.15 pre-beta release + * @version v0.20 : 2016.7.22 support msg struct + * @version v0.50 : 2016.8.13 Init. release version + */ + + +#ifndef ISP_DRIVER_HASH_H_ +#define ISP_DRIVER_HASH_H_ + +#include "mb_cmd_hash.h" + +// ====================================== +// Function +// ====================================== +int isp_hash(unsigned char * hash, struct sHASH_MSG * hash_msg, unsigned int object_id); + +#endif /* ISP_DRIVER_HASH_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_hmac_securekey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_hmac_securekey.h new file mode 100644 index 0000000..9f3299a --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_hmac_securekey.h @@ -0,0 +1,20 @@ +/*! + * @file isp_driver_hmac_securekey.h + * @brief Headerfile : isp driver for hmac securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_HMAC_SECUREKEY_H_ +#define ISP_DRIVER_HMAC_SECUREKEY_H_ + +#include "mb_cmd_hmac_securekey.h" + +// ====================================== +// Function +// ====================================== +int isp_hmac_generate_key_securekey(unsigned int key_byte_len, unsigned int key_index); + +int isp_hmac_securekey(unsigned char * mac, struct sHMAC_MSG * hmac_msg, unsigned int object_id, unsigned int key_index); + +#endif /* ISP_DRIVER_HMAC_SECUREKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_rng.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_rng.h new file mode 100644 index 0000000..bc21cdd --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_rng.h @@ -0,0 +1,18 @@ +/*! + * @file isp_driver_rng.h + * @brief Headerfile : isp driver for rng + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_RNG_H_ +#define ISP_DRIVER_RNG_H_ + +#include "mb_cmd_rng.h" + +// ====================================== +// Function +// ====================================== +int isp_generate_random(unsigned int *random, unsigned int word_len); + +#endif /* ISP_DRIVER_RNG_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_rsa_securekey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_rsa_securekey.h new file mode 100644 index 0000000..485a46a --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_rsa_securekey.h @@ -0,0 +1,29 @@ +/*! + * @file isp_driver_rsa_securekey.h + * @brief Headerfile : isp driver for rsa securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + * @version v1.00 : 2016.12.23 Support sign/verify with msg_disgest + */ + +#ifndef ISP_DRIVER_RSA_SECUREKEY_H_ +#define ISP_DRIVER_RSA_SECUREKEY_H_ + +#include "mb_cmd_rsa_securekey.h" + +// ====================================== +// Function +// ====================================== +int isp_rsa_encrypt_securekey(unsigned char *output, unsigned int *output_byte_len, unsigned char *input, unsigned int input_byte_len, unsigned int key_index); +int isp_rsa_decrypt_securekey(unsigned char *output, unsigned int *output_byte_len, unsigned char * input, unsigned int input_byte_len, unsigned int key_index); + +int isp_rsa_sign_securekey(struct sRSA_SIGN *rsa_sign, unsigned char *msg, unsigned int msg_byte_len, unsigned int key_index); +int isp_rsa_verify_securekey(struct sRSA_SIGN *rsa_sign, unsigned char *msg, unsigned int msg_byte_len, unsigned int key_index); + +int isp_rsa_sign_md_securekey(struct sRSA_SIGN *rsa_sign, unsigned char *msg_digest, unsigned int msg_digest_byte_len, unsigned int key_index); +int isp_rsa_verify_md_securekey(struct sRSA_SIGN *rsa_sign, unsigned char *msg_digest, unsigned int msg_digest_byte_len, unsigned int key_index); + +int isp_rsa_generate_key_securekey(unsigned key_index, unsigned object_id, unsigned int pukey_e); +int isp_rsa_get_pukey_securekey(struct sRSA_KEY *rsa_key, unsigned object_id, unsigned key_index); + +#endif /* ISP_DRIVER_RSA_SECUREKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage.h new file mode 100644 index 0000000..47058e0 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage.h @@ -0,0 +1,56 @@ +/*! + * @file isp_driver_secure_storage.h + * @brief Headerfile : isp driver for secure storage + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + * @version v0.60 : 2016.12.13 Add for secure_storage_map function + */ + +#ifndef ISP_DRIVER_SECURE_STORAGE_H_ +#define ISP_DRIVER_SECURE_STORAGE_H_ + +// ====================================== +// Struct +// ====================================== +//! @struct SECURE_STORAGE_MAP +//! @brief struct of secure storage parameter +struct SECURE_STORAGE_MAP { + unsigned int offset; + unsigned int index_max; + unsigned int key_byte_len_max; + unsigned int slot_byte_len; + unsigned int type; +}; + +#define KEY_PATH_BASE "/mnt" +//#define KEY_PATH_BASE "/mnt/sss" + +#define SECURE_STORAGE_TYPE_FACTORYKEY_KEY (0x00) +#define SECURE_STORAGE_TYPE_FACTORYKEY_DATA (0x01) + +#define SECURE_STORAGE_TYPE_KEY_AES (0x0A) +#define SECURE_STORAGE_TYPE_KEY_HMAC (0x0B) +#define SECURE_STORAGE_TYPE_KEY_RSA (0x0C) +#define SECURE_STORAGE_TYPE_KEY_DH (0x0D) +#define SECURE_STORAGE_TYPE_KEY_ECC (0x0E) +#define SECURE_STORAGE_TYPE_DATA (0x10) +#define SECURE_STORAGE_TYPE_CERT (0x11) + +#define FACTORYKEY_ARTIK_PSK (0x80000100) +#define FACTORYKEY_ARTIK_DEVICE (0x00010120) +#define FACTORYKEY_ARTIK_CERT (0x00010122) +#define FACTORYKEY_DA_CA (0x00081110) +#define FACTORYKEY_DA_DEVICE (0x00081210) +#define FACTORYKEY_DA_PBKEY (0x00081211) +#define FACTORYKEY_IOTIVITY_ECC (0x00011120) +#define FACTORYKEY_IOTIVITY_ECC_CERT (0x00011122) +#define FACTORYKEY_IOTIVITY_SUB_CA_CERT (0x00011222) + +// ====================================== +// Function +// ====================================== +int read_secure_storage(unsigned int type, unsigned int index, unsigned int data_offset, unsigned int src_addr, unsigned int byte_len); +int write_secure_storage(unsigned int type, unsigned int index, unsigned int data_offset, unsigned int src_addr, unsigned int byte_len); +int secure_storage_map(unsigned int type, struct SECURE_STORAGE_MAP *map); + +#endif /* ISP_DRIVER_SECURE_STORAGE_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_cert.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_cert.h new file mode 100644 index 0000000..782aae7 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_cert.h @@ -0,0 +1,17 @@ +/*! + * @file isp_driver_secure_storage_cert.h + * @brief Headerfile : isp driver for secure storage cert + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_SECURE_STORAGE_CERT_H_ +#define ISP_DRIVER_SECURE_STORAGE_CERT_H_ + + +#include "mb_cmd_secure_storage_cert.h" + +int isp_read_cert(unsigned char *cert, unsigned int *cert_byte_len, unsigned int index); +int isp_write_cert(unsigned char *cert, unsigned int cert_byte_len, unsigned int index); + +#endif /* ISP_DRIVER_SECURE_STORAGE_CERT_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_data.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_data.h new file mode 100644 index 0000000..f3be842 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_data.h @@ -0,0 +1,19 @@ +/*! + * @file isp_driver_secure_storage_data.h + * @brief Headerfile : isp driver for secure storage data + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_SECURE_STORAGE_DATA_H_ +#define ISP_DRIVER_SECURE_STORAGE_DATA_H_ + +#include "mb_cmd_secure_storage_data.h" + +// ====================================== +// Function +// ====================================== +int isp_read_storage(unsigned char *data, unsigned int *data_byte_len, unsigned int index); +int isp_write_storage(unsigned char *data, unsigned int data_byte_len, unsigned int index); + +#endif /* ISP_DRIVER_SECURE_STORAGE_DATA_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_factorykey.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_factorykey.h new file mode 100644 index 0000000..2d53741 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_factorykey.h @@ -0,0 +1,23 @@ +/*! + * @file isp_driver_secure_storage_factorykey.h + * @brief Headerfile : isp driver for secure storage factorykey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + * @version v0.60 : 2016.12.29 Merge function to isp_set/get_factorykey_data, Support new Factorykey + */ + +#ifndef ISP_DRIVER_SECURE_STORAGE_FACTORYKEY_H_ +#define ISP_DRIVER_SECURE_STORAGE_FACTORYKEY_H_ + +#include "mb_cmd_hmac_securekey.h" +#include "mb_cmd_secure_storage_factorykey.h" + +// ====================================== +// Function +// ====================================== +int isp_set_factorykey(unsigned char * factorykey); + +int isp_set_factorykey_data(unsigned char *data, unsigned int data_byte_len, unsigned int key_id); +int isp_get_factorykey_data(unsigned char *data, unsigned int *data_byte_len, unsigned int key_id); + +#endif /* ISP_DRIVER_SECURE_STORAGE_FACTORYKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_key.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_key.h new file mode 100644 index 0000000..6848566 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_secure_storage_key.h @@ -0,0 +1,21 @@ +/*! + * @file isp_driver_secure_storage_key.h + * @brief Headerfile : isp driver for secure storage key + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_DRIVER_SECURE_STORAGE_KEY_H_ +#define ISP_DRIVER_SECURE_STORAGE_KEY_H_ + +#include "mb_cmd_secure_storage_key.h" + +// ====================================== +// Function +// ====================================== +int isp_set_securekey(unsigned char *key, unsigned int key_byte_len, unsigned int key_type, unsigned int index); +int isp_get_securekey(unsigned int *object_id, unsigned int key_type, unsigned int index); +int isp_remove_key(unsigned int key_type, unsigned int key_index); +int isp_set_genkey_securekey(unsigned int key_type, unsigned int index); + +#endif /* ISP_DRIVER_SECURE_STORAGE_KEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_driver_system.h b/os/arch/arm/src/s5j/soc/sss/isp_driver_system.h new file mode 100644 index 0000000..b672a62 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_driver_system.h @@ -0,0 +1,20 @@ +/*! + * @file isp_driver_system.h + * @brief Headerfile : isp driver for system + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef DRIVER_ISP_DRIVER_SYSTEM_H_ +#define DRIVER_ISP_DRIVER_SYSTEM_H_ + +#include "mb_cmd_system.h" + +// ====================================== +// Function +// ====================================== +int isp_get_status(void); +int isp_get_info(unsigned int *version); +int isp_clear(unsigned int type); + +#endif /* DRIVER_ISP_DRIVER_SYSTEM_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_oid.h b/os/arch/arm/src/s5j/soc/sss/isp_oid.h new file mode 100644 index 0000000..acae821 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_oid.h @@ -0,0 +1,75 @@ +/*! + * @file isp_oid.h + * @brief Headerfile : definitions for oid + * @author kiseok.bae + * @version v0.90 : 2016.9.29 initial + * + */ + +#ifndef ISP_OID_H_ +#define ISP_OID_H_ + + +/* + * OID LIST + */ +#define OIDMAX_HMAC (4) +#define OID_HMAC_SHA1_160 (0x00011100) +#define OID_HMAC_SHA2_256 (0x00012300) +#define OID_HMAC_SHA2_384 (0x00012400) +#define OID_HMAC_SHA2_512 (0x00012500) + +#define OIDMAX_HASH (8) +#define OID_SHA1_160 (0x00001100) +#define OID_SHA2_256 (0x00002300) +#define OID_SHA2_384 (0x00002400) +#define OID_SHA2_512 (0x00002500) +#define OID_SHA3_224 (0x00003200) +#define OID_SHA3_256 (0x00003300) +#define OID_SHA3_384 (0x00003400) +#define OID_SHA3_512 (0x00003500) + +#define OIDMAX_DH (2) +#define OID_DH_1024 (0x00001191) +#define OID_DH_2048 (0x00002392) + +#define OIDMAX_ECC (6) +#define OID_ECC_P192 (0x00000011) +#define OID_ECC_P224 (0x00000012) +#define OID_ECC_P256 (0x00000013) +#define OID_ECC_P384 (0x00000014) +#define OID_ECC_P521 (0x00000015) +#define OID_ECC_BP256 (0x00000053) + +#define OIDMAX_RSA (2) +#define OID_RSA_1024 (0x000000B1) +#define OID_RSA_2048 (0x000000B2) + +#define OIDMAX_ECDSA (24) +#define OID_ECDSA_BP256_SHA1_160 ( OID_ECC_BP256|OID_SHA1_160 ) +#define OID_ECDSA_BP256_SHA2_256 ( OID_ECC_BP256|OID_SHA2_256 ) +#define OID_ECDSA_BP256_SHA2_384 ( OID_ECC_BP256|OID_SHA2_384 ) +#define OID_ECDSA_BP256_SHA2_512 ( OID_ECC_BP256|OID_SHA2_512 ) + +#define OID_ECDSA_P192_SHA1_160 ( OID_ECC_P192|OID_SHA1_160 ) +#define OID_ECDSA_P192_SHA2_256 ( OID_ECC_P192|OID_SHA2_256 ) +#define OID_ECDSA_P192_SHA2_384 ( OID_ECC_P192|OID_SHA2_384 ) +#define OID_ECDSA_P192_SHA2_512 ( OID_ECC_P192|OID_SHA2_512 ) +#define OID_ECDSA_P224_SHA1_160 ( OID_ECC_P224|OID_SHA1_160 ) +#define OID_ECDSA_P224_SHA2_256 ( OID_ECC_P224|OID_SHA2_256 ) +#define OID_ECDSA_P224_SHA2_384 ( OID_ECC_P224|OID_SHA2_384 ) +#define OID_ECDSA_P224_SHA2_512 ( OID_ECC_P224|OID_SHA2_512 ) +#define OID_ECDSA_P256_SHA1_160 ( OID_ECC_P256|OID_SHA1_160 ) +#define OID_ECDSA_P256_SHA2_256 ( OID_ECC_P256|OID_SHA2_256 ) +#define OID_ECDSA_P256_SHA2_384 ( OID_ECC_P256|OID_SHA2_384 ) +#define OID_ECDSA_P256_SHA2_512 ( OID_ECC_P256|OID_SHA2_512 ) +#define OID_ECDSA_P384_SHA1_160 ( OID_ECC_P384|OID_SHA1_160 ) +#define OID_ECDSA_P384_SHA2_256 ( OID_ECC_P384|OID_SHA2_256 ) +#define OID_ECDSA_P384_SHA2_384 ( OID_ECC_P384|OID_SHA2_384 ) +#define OID_ECDSA_P384_SHA2_512 ( OID_ECC_P384|OID_SHA2_512 ) +#define OID_ECDSA_P521_SHA1_160 ( OID_ECC_P521|OID_SHA1_160 ) +#define OID_ECDSA_P521_SHA2_256 ( OID_ECC_P521|OID_SHA2_256 ) +#define OID_ECDSA_P521_SHA2_384 ( OID_ECC_P521|OID_SHA2_384 ) +#define OID_ECDSA_P521_SHA2_512 ( OID_ECC_P521|OID_SHA2_512 ) + +#endif /*ISP_OID_H_*/ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_sss_map.h b/os/arch/arm/src/s5j/soc/sss/isp_sss_map.h new file mode 100644 index 0000000..0a87cbd --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_sss_map.h @@ -0,0 +1,39 @@ +/*! + * @file isp_sss_map.h + * @brief Headerfile : sss sfr address map for isp + * @author jinsu.hyun + * @version v0.01 : 2016.7.7 + * @version v0.10 : 2016.7.15 pre-beta release + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef ISP_SSS_MAP_H_ +#define ISP_SSS_MAP_H_ + +#define MB_STATUS (*(volatile u32 *)(MB_REG_BASE + 0x0000)) + +#ifdef CONFIG_S5J_SILICON + #define MB_REG_BASE (0x800E0000) + #define MB_CM0_HRESET (*(volatile u32 *)(MB_REG_BASE + 0x0004)) + #define MB_CM0_SRAM_ACC_CON (*(volatile u32 *)(MB_REG_BASE + 0x0008)) + #define MB_CM0_DBGCON (*(volatile u32 *)(MB_REG_BASE + 0x0034)) +#else +#define MB_REG_BASE (0x70020000) +#endif + +#define CTRL_FIELD_BASE (MB_REG_BASE + 0x0100) +#define DATA_FIELD_BASE (MB_REG_BASE + 0x0110) + +#define CTRL_FIELD_ADDR(val) (CTRL_FIELD_BASE+(val<<2)) +#define DATA_FIELD_ADDR(val) (DATA_FIELD_BASE+(val<<2)) + +#define CTRL_FIELD(val) (*(volatile u32 *)(CTRL_FIELD_ADDR(val))) +#define DATA_FIELD(val) (*(volatile u32 *)(DATA_FIELD_ADDR(val))) + +#define ISP_DATA_FIELD_SET(index, value) DATA_FIELD(index) = value +#define ISP_DATA_FIELD_GET(index, value) value = DATA_FIELD(index) +#define ISP_CTRL_FIELD_SET(index, value) CTRL_FIELD(index) = value +#define ISP_CTRL_FIELD_GET(index, value) value = CTRL_FIELD(index) + + +#endif /* ISP_SSS_MAP_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_type.h b/os/arch/arm/src/s5j/soc/sss/isp_type.h new file mode 100644 index 0000000..f78372f --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_type.h @@ -0,0 +1,70 @@ +/*! + * @file isp_type.h + * @brief Headerfile : types for ISP + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +//! @defgroup SECURITY_ISP api for isp driver +//! @defgroup SECURITY_ISP_MAILBOX api for mailbox interface to ISP + +#ifndef ISP_TYPE_H_ +#define ISP_TYPE_H_ + +#ifndef CONFIG_S5J_SILICON +#define CONFIG_S5J_SILICON +#endif + +/********** types **********/ + +typedef unsigned int u32; +typedef signed int s32; +typedef unsigned char u8; +typedef signed char s8; + + +/********** Macro Function for SFR access **********/ +#define BIT(nbit) (0x1u << (nbit)) + +#define SFR_BIT_CLR(val, bit) ((val) &= (~(bit))) ///> 0)); \ + ((u8 *)(buf))[2] = ((u8)((dword) >> 8)); \ + ((u8 *)(buf))[1] = ((u8)((dword) >> 16)); \ + ((u8 *)(buf))[0] = ((u8)((dword) >> 24)); +#define GET_DWORD_FROM_BBUF(buf) \ + (u32)( \ + ((((u8 *)(buf))[3]) << 0) | \ + ((((u8 *)(buf))[2]) << 8) | \ + ((((u8 *)(buf))[1]) << 16) | \ + ((((u8 *)(buf))[0]) << 24)) + +#define SWAP32(val) \ + (u32)( \ + (((val) & 0xff) << 24) | \ + (((val) & 0xff00) << 8) | \ + (((val) & 0xff0000) >> 8) | \ + (((val) & 0xff000000) >> 24) \ + ) + +#define CEIL_BY_WORD(val) (val&0x3) ? (1+(val>>2)) : (val>>2) +#define CEIL_BY_16BYTE(val) (val&0xF) ? ((val&0xFFFFFFF0)+0x10) : (val) + +/********** Defines **********/ +#define SUCCESS (0x00) +#define FAIL (0x01) + +#ifndef NULL +#define NULL ((void *) 0) +#endif + + +#endif /* ISP_TYPE_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/isp_util.h b/os/arch/arm/src/s5j/soc/sss/isp_util.h new file mode 100644 index 0000000..654e52c --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/isp_util.h @@ -0,0 +1,41 @@ +/*! + * @file isp_util.h + * @brief Headerfile : util functions to support memset, memcpy, memcmp + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ +#ifndef ISP_UTIL_H_ +#define ISP_UTIL_H_ + +#include "isp_type.h" + +// ====================================== +// Function +// ====================================== +int _isp_memcpy_u32_4PKA(u32* pu32Dst, u32* pu32Src, u32 u32Size); +int _isp_memset_u32(u32* pu32Dst, u32 u32Src, u32 u32Size); +int _isp_memcpy_u32(u32* pu32Dst, u32* pu32Src, u32 u32Size); +int _isp_memcmp_u32(const u32* pu32Src1, const u32* pu32Src2, u32 u32Size); + +int _isp_memxor_u32(u32* pu32Dst, u32* pu32Src1, u32* pu32Src2, u32 u32Size); +int _isp_memcpy_u32_4PKA_Swap(u32* pu32Dst, u32* pu32Src, u32 u32Size, int u32Swap); +int _isp_memcpy_swap_u32(u32* pu32Dst, u32* pu32Src, u32 u32Size); + +int _isp_memset_u8(u8* pu8Dst, u8 u8Src, u32 u32Size); +int _isp_memcpy_u8(u8* pu8Dst, u8* pu8Src, u32 u32Size); +int _isp_memcmp_u8(const u8* pu8Src1, const u8* pu8Src2, u32 u32Size); + +int _isp_memcpy_mailbox(u32* pu32Dst, u32* pu32Src, u32 u32Size_byte_len); +int _isp_memcpy_mailbox_swap(u32* pu32Dst, u32* pu32Src, u32 u32Size_byte_len); + +int _isp_check_oid(u32 inputoid, u32 algorithm); +int _isp_is_zero(const u32* pu32Src, u32 u32Size); + +#define ISP_HMAC (0x001) +#define ISP_HASH (0x002) +#define ISP_DH (0x003) +#define ISP_ECDH (0x004) +#define ISP_RSA (0x005) +#define ISP_ECDSA (0x006) + +#endif /* ISP_UTIL_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/libispdriver.a b/os/arch/arm/src/s5j/soc/sss/libispdriver.a new file mode 100644 index 0000000000000000000000000000000000000000..8544906a3c6134b058a32aedd8a5203174d80a52 GIT binary patch literal 278550 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

o57hO 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 8)&0x07) + +// ====================================== +// Function +// ====================================== +int mb_hash_init(unsigned int object_id, unsigned int msg_byte_len); +int mb_hash_update(unsigned int block_byte_len, unsigned char * msg_block); +int mb_hash_final(unsigned char *hash, unsigned int block_byte_len, unsigned char * msg_block); + +int mb_hash_dma(unsigned char *hash, unsigned int object_id, unsigned int msg_byte_len, unsigned int msg_addr_low, unsigned int msg_addr_high); +int mb_hash_descriptor(unsigned char *hash, unsigned int object_id, unsigned int msg_byte_len, unsigned int descriptor_byte_len, unsigned int descriptor_addr_low, unsigned int descriptor_addr_high); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_HASH_INIT (0x00103102) +#define FUNC_HASH_UPDATE (0x00203102) +#define FUNC_HASH_FINAL (0x00303102) +#define FUNC_HASH_DMA (0x01013102) +#define FUNC_HASH_DESCRIPTOR (0x02013102) + + + + +#endif /* MB_CMD_HASH_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac.h new file mode 100644 index 0000000..dd8d61c --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac.h @@ -0,0 +1,27 @@ +/*! + * @file mb_cmd_hmac.h + * @brief Headerfile : mailbox command for hmac + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + + +#ifndef MB_CMD_HMAC_H_ +#define MB_CMD_HMAC_H_ + +#define MAX_HMAC_BLOCK_BLEN (128) + +//! @struct sHMAC_MSG +//! @brief struct of message for HMAC +struct sHMAC_MSG +{ + unsigned int addr_low; + unsigned int addr_high; + unsigned int descriptor_byte_len; + unsigned int msg_byte_len; + unsigned int msg_type; +}; + + +#endif /* MB_CMD_HMAC_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac_securekey.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac_securekey.h new file mode 100644 index 0000000..087d4a0 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_hmac_securekey.h @@ -0,0 +1,32 @@ +/*! + * @file mb_cmd_hmac_securekey.h + * @brief Headerfile : mailbox command for hmac securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef MB_CMD_HMAC_SECUREKEY_H_ +#define MB_CMD_HMAC_SECUREKEY_H_ + +#include "mb_cmd_hmac.h" + +// ====================================== +// Function +// ====================================== +int mb_hmac_generate_key_securekey(unsigned int key_byte_len, unsigned int key_index); + +int mb_hmac_init_securekey(unsigned int object_id, unsigned int msg_byte_len); +int mb_hmac_update_securekey(unsigned int block_byte_len, unsigned char * msg_block); +int mb_hmac_final_securekey(unsigned char *mac, unsigned int block_byte_len, unsigned char * msg_block); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_HMAC_KEYGEN_SECUREKEY (0x00013202) + +#define FUNC_HMAC_INIT_SECUREKEY (0x00113202) +#define FUNC_HMAC_UPDATE_SECUREKEY (0x00213202) +#define FUNC_HMAC_FINAL_SECUREKEY (0x00313202) + +#endif /* MB_CMD_HMAC_SECUREKEY_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_rng.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_rng.h new file mode 100644 index 0000000..1445346 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_rng.h @@ -0,0 +1,24 @@ +/*! + * @file mb_cmd_rng.h + * @brief Headerfile : mailbox command for rng + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + + +#ifndef MB_CMD_RNG_H_ +#define MB_CMD_RNG_H_ + + +// ====================================== +// Function +// ====================================== +int mb_generate_random_number(unsigned int *random_number, unsigned int random_wlen); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_RNG (0x00016102) + +#endif /* MB_CMD_RNG_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa.h new file mode 100644 index 0000000..c774b95 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa.h @@ -0,0 +1,38 @@ +/*! + * @file mb_cmd_rsa.h + * @brief Headerfile : mailbox command for rsa + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + + +#ifndef MB_CMD_RSA_H_ +#define MB_CMD_RSA_H_ + +// ====================================== +// Structure +// ====================================== +//! @struct sRSA_KEY +//! @brief struct of RSA Key parameter +struct sRSA_KEY{ + unsigned int object_id; + unsigned char *modules; + unsigned int modules_byte_len; + unsigned char *publickey; + unsigned int publickey_byte_len; + unsigned char *privatekey; +}; + + +//! @struct sRSA_SIGN +//! @brief struct of RSA Signature +struct sRSA_SIGN{ + unsigned int signature_byte_len; + unsigned char *signature; + unsigned int salt_byte_len; + unsigned int alg_type; +}; + + +#endif /* MB_CMD_RSA_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa_securekey.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa_securekey.h new file mode 100644 index 0000000..7a6e057 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_rsa_securekey.h @@ -0,0 +1,72 @@ +/*! + * @file mb_cmd_rsa_securekey.h + * @brief Headerfile : mailbox command for rsa securekey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + + +#ifndef MB_CMD_RSA_SECUREKEY_H_ +#define MB_CMD_RSA_SECUREKEY_H_ + +#include "mb_cmd_rsa.h" + +// ====================================== +// Functions +// ====================================== +int mb_rsa_encrypt_securekey_step1(unsigned int object_id, unsigned char *input, unsigned int input_byte_len); +int mb_rsa_encrypt_securekey_step2(unsigned int object_id); +int mb_rsa_encrypt_securekey_step3(unsigned int object_id, unsigned char *output, unsigned int *output_byte_len); + +int mb_rsa_decrypt_securekey_step1(unsigned int object_id, unsigned char *input, unsigned int input_byte_len); +int mb_rsa_decrypt_securekey_step2(unsigned int object_id); +int mb_rsa_decrypt_securekey_step3(unsigned int object_id, unsigned char *output, unsigned int *output_byte_len); + +int mb_rsa_sign_securekey_step1(unsigned int object_id, unsigned char *hash); +int mb_rsa_sign_securekey_step2(unsigned int object_id); +int mb_rsa_sign_securekey_step3(unsigned int object_id, struct sRSA_SIGN *rsa_sign); + +int mb_rsa_verify_securekey_step1(unsigned int object_id, unsigned char *hash); +int mb_rsa_verify_securekey_step2(unsigned int object_id); +int mb_rsa_verify_securekey_step3(unsigned int object_id, struct sRSA_SIGN *rsa_sign); +int mb_rsa_verify_securekey_step4(unsigned int object_id, struct sRSA_SIGN *rsa_sign); + +int mb_rsa_generate_key_secretkey_step1(unsigned int object_id, unsigned int pukey); + +int mb_rsa_get_pubkey_secretkey_step1(unsigned int object_id, struct sRSA_KEY *rsa_key); +int mb_rsa_get_pubkey_secretkey_step2(unsigned int object_id, struct sRSA_KEY *rsa_key); + +int mb_load_prime(void); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_RSA_ENCRYPT_SECUREKEY1 (0x00015102) +#define FUNC_RSA_ENCRYPT_SECUREKEY2 (0x01025102) +#define FUNC_RSA_ENCRYPT_SECUREKEY3 (0x00035102) + +#define FUNC_RSA_DECRYPT_SECUREKEY1 (0x00015202) +#define FUNC_RSA_DECRYPT_SECUREKEY2 (0x01025202) +//skip 03rd when securekey +#define FUNC_RSA_DECRYPT_SECUREKEY3 (0x00045202) + +#define FUNC_RSA_SIGN_SECUREKEY1 (0x00011502) +#define FUNC_RSA_SIGN_SECUREKEY2 (0x01021502) +//skip 03rd when secure key +#define FUNC_RSA_SIGN_SECUREKEY3 (0x00041502) +#define FUNC_RSA_SIGN_SECUREKEY3_PKCS (0x01041502) +#define FUNC_RSA_SIGN_SECUREKEY3_PSS (0x00041502) + +#define FUNC_RSA_VERIFY_SECUREKEY1 (0x00011602) +#define FUNC_RSA_VERIFY_SECUREKEY2 (0x01021602) +#define FUNC_RSA_VERIFY_SECUREKEY3 (0x00031602) +#define FUNC_RSA_VERIFY_SECUREKEY4 (0x00041602) + +#define FUNC_RSA_GENKEY_SECUREKEY1_RNDPK (0x01011702) +#define FUNC_RSA_GENKEY_SECUREKEY1_USERPK (0x03011702) + +#define FUNC_RSA_GET_PUBKEY_SECUREKEY1 (0x01021702) +#define FUNC_RSA_GET_PUBKEY_SECUREKEY2 (0x01031702) + +#endif /* MB_CMD_RSA_SECUREKEY_H_ */ + diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_cert.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_cert.h new file mode 100644 index 0000000..ec4d6da --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_cert.h @@ -0,0 +1,40 @@ +/*! + * @file mb_cmd_secure_storage_cert.h + * @brief Headerfile : mailbox command for secure storage cert + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef MB_CMD_SECURE_STORAGE_CERT_H_ +#define MB_CMD_SECURE_STORAGE_CERT_H_ + + +#define SSTORAGE_CERT_SLOT_INDEX_MAX (8) +#define SSTORAGE_CERT_DATA_MAX (0x1000) // 4096 +#define SSTORAGE_CERT_SLOT_MAX (0x1100) // 4096+256 + +// ====================================== +// Function +// ====================================== +// Secure Storage for Cert +int mb_storage_set_cert_init(unsigned char * iv, unsigned int msg_byte_len, unsigned int index); +int mb_storage_set_cert_update(unsigned char *out_block, unsigned char *in_block); +int mb_storage_set_cert_final(unsigned char *out_block, unsigned char *in_block, unsigned int in_block_byte_len); + +int mb_storage_get_cert_init(unsigned char *iv, unsigned int msg_byte_len, unsigned int index); +int mb_storage_get_cert_update(unsigned char *out_block, unsigned char *in_block); +int mb_storage_get_cert_final(unsigned char *out_block, unsigned char *in_block, unsigned int block_byte_len); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_SSTORAGE_CERT_ENC_INIT (0x0001A102) +#define FUNC_SSTORAGE_CERT_ENC_UPDATE (0x0002A102) +#define FUNC_SSTORAGE_CERT_ENC_FINAL (0x0003A102) + +#define FUNC_SSTORAGE_CERT_DEC_INIT (0x0011A102) +#define FUNC_SSTORAGE_CERT_DEC_UPDATE (0x0012A102) +#define FUNC_SSTORAGE_CERT_DEC_FINAL (0x0013A102) + + +#endif /* MB_CMD_SECURE_STORAGE_CERT_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_data.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_data.h new file mode 100644 index 0000000..6c25383 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_data.h @@ -0,0 +1,41 @@ +/*! + * @file mb_cmd_secure_storage_data.h + * @brief Headerfile : mailbox command for secure storage data + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef MB_CMD_SECURE_STORAGE_DATA_H_ +#define MB_CMD_SECURE_STORAGE_DATA_H_ + + +#define SSTORAGE_DATA_SLOT_INDEX_MAX (32) +#define SSTORAGE_DATA_DATA_MAX (208) +#define SSTORAGE_DATA_SLOT_MAX (256) + + +// ====================================== +// Function +// ====================================== +// Secure Storage for Data +int mb_storage_set_data_init(unsigned char * iv, unsigned int msg_byte_len, unsigned int index); +int mb_storage_set_data_update(unsigned char * out_block, unsigned char *in_block); +int mb_storage_set_data_final(unsigned char * out_block, unsigned char *in_block, unsigned int in_block_byte_len); + +int mb_storage_get_data_init(unsigned char *iv, unsigned int msg_byte_len, unsigned int index); +int mb_storage_get_data_update(unsigned char * out_block, unsigned char *in_block); +int mb_storage_get_data_final(unsigned char * out_block, unsigned char *in_block, unsigned int block_byte_len); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_SSTORAGE_DATA_ENC_INIT (0x0001A202) +#define FUNC_SSTORAGE_DATA_ENC_UPDATE (0x0002A202) +#define FUNC_SSTORAGE_DATA_ENC_FINAL (0x0003A202) + +#define FUNC_SSTORAGE_DATA_DEC_INIT (0x0011A202) +#define FUNC_SSTORAGE_DATA_DEC_UPDATE (0x0012A202) +#define FUNC_SSTORAGE_DATA_DEC_FINAL (0x0013A202) + + +#endif /* MB_CMD_SECURE_STORAGE_DATA_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_factorykey.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_factorykey.h new file mode 100644 index 0000000..c488739 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_factorykey.h @@ -0,0 +1,46 @@ +/*! + * @file mb_cmd_secure_storage_factorykey.h + * @brief Headerfile : mailbox command for secure storage for factorykey + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef MB_CMD_SECURE_STORAGE_FACTORYKEY_H_ +#define MB_CMD_SECURE_STORAGE_FACTORYKEY_H_ + +// ====================================== +// Function +// ====================================== +int mb_storage_set_factorykey_init(unsigned int key_byte_len); +int mb_storage_set_factorykey_update(unsigned char *in_block); +int mb_storage_set_factorykey_final(unsigned char *in_block, unsigned int block_byte_len); + +int mb_storage_get_factorykey_init(unsigned char *iv, unsigned int msg_byte_len, unsigned int type); +int mb_storage_get_factorykey_update(unsigned char *in_block); +int mb_storage_get_factorykey_final(unsigned char *in_block, unsigned int block_byte_len); + +int mb_storage_set_factorykey_data_init(unsigned char * iv, unsigned int msg_byte_len, unsigned int key_id); +int mb_storage_set_factorykey_data_update(unsigned char *out_block, unsigned char *in_block); +int mb_storage_set_factorykey_data_final(unsigned char *out_block, unsigned char *in_block, unsigned int in_block_byte_len); + +int mb_storage_get_factorykey_data_init(unsigned char *iv, unsigned int msg_byte_len, unsigned int key_id); +int mb_storage_get_factorykey_data_update(unsigned char *out_block, unsigned char *in_block); +int mb_storage_get_factorykey_data_final(unsigned char *out_block, unsigned char *in_block, unsigned int block_byte_len); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_SSTORAGE_FACTORYKEY_ENC_INIT (0x0001A402) +#define FUNC_SSTORAGE_FACTORYKEY_ENC_UPDATE (0x0002A402) +#define FUNC_SSTORAGE_FACTORYKEY_ENC_FINAL (0x0003A402) + +#define FUNC_SSTORAGE_FACTORYKEY_DATA_ENC_INIT (0x0021A402) +#define FUNC_SSTORAGE_FACTORYKEY_DATA_ENC_UPDATE (0x0022A402) +#define FUNC_SSTORAGE_FACTORYKEY_DATA_ENC_FINAL (0x0023A402) + +#define FUNC_SSTORAGE_FACTORYKEY_DATA_DEC_INIT (0x0031A402) +#define FUNC_SSTORAGE_FACTORYKEY_DATA_DEC_UPDATE (0x0032A402) +#define FUNC_SSTORAGE_FACTORYKEY_DATA_DEC_FINAL (0x0033A402) + + +#endif /* MB_CMD_SECURE_STORAGE_FACTORYKEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_key.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_key.h new file mode 100644 index 0000000..aa24868 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_secure_storage_key.h @@ -0,0 +1,46 @@ +/*! + * @file mb_cmd_secure_storage_key.h + * @brief Headerfile : mailbox command for secure storage key + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + +#ifndef MB_CMD_SECURE_STORAGE_KEY_H_ +#define MB_CMD_SECURE_STORAGE_KEY_H_ + + +// Storage Map +#define MB_SSTORAGE_BLOCK_BYTELEN_MAX (240) + +// ====================================== +// Function +// ====================================== +// Secure Storage for Key +int mb_storage_set_securekey_init(unsigned char * iv, unsigned int msg_byte_len, unsigned int type, unsigned int index); +int mb_storage_set_securekey_update(unsigned char * out_block, unsigned char *in_block, unsigned int type); +int mb_storage_set_securekey_final(unsigned char *out_block, unsigned char *in_block, unsigned int block_byte_len, unsigned int type); + +int mb_storage_get_securekey_init(unsigned char *iv, unsigned int msg_byte_len, unsigned int type, unsigned int index); +int mb_storage_get_securekey_update(unsigned char *in_block); +int mb_storage_get_securekey_final(unsigned int *object_id, unsigned char *in_block, unsigned int block_byte_len); + +int mb_storage_set_genkey_securekey_init(unsigned char * iv, unsigned int *msg_byte_len, unsigned int type, unsigned int index); +int mb_storage_set_genkey_securekey_update(unsigned char * out_block, unsigned int type); +int mb_storage_set_genkey_securekey_final(unsigned char *out_block, unsigned int type); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_SSTORAGE_KEY_ENC_INIT (0x0001A302) +#define FUNC_SSTORAGE_KEY_ENC_UPDATE (0x0002A302) +#define FUNC_SSTORAGE_KEY_ENC_FINAL (0x0003A302) + +#define FUNC_SSTORAGE_KEY_DEC_INIT (0x0011A302) +#define FUNC_SSTORAGE_KEY_DEC_UPDATE (0x0012A302) +#define FUNC_SSTORAGE_KEY_DEC_FINAL (0x0013A302) + +#define FUNC_SSTORAGE_KEY_ENC_KEYGEN_INIT (0x0021A302) +#define FUNC_SSTORAGE_KEY_ENC_KEYGEN_UPDATE (0x0022A302) +#define FUNC_SSTORAGE_KEY_ENC_KEYGEN_FINAL (0x0023A302) + +#endif /* MB_CMD_SECURE_STORAGE_KEY_H_ */ diff --git a/os/arch/arm/src/s5j/soc/sss/mb_cmd_system.h b/os/arch/arm/src/s5j/soc/sss/mb_cmd_system.h new file mode 100644 index 0000000..b9dffb4 --- /dev/null +++ b/os/arch/arm/src/s5j/soc/sss/mb_cmd_system.h @@ -0,0 +1,25 @@ +/*! + * @file mb_cmd_system.h + * @brief Headerfile : mailbox command for system function + * @author jinsu.hyun + * @version v0.50 : 2016.8.13 Init. release version + */ + + +#ifndef MB_CMD_SYSTEM_H_ +#define MB_CMD_SYSTEM_H_ + +// ====================================== +// Function +// ====================================== +int mb_system_clear(unsigned int type); +int mb_system_get_info(unsigned int *version); + +// ====================================== +// Mailbox Command +// ====================================== +#define FUNC_SYSTEM_GET_INFO (0x00000102) +#define FUNC_SYSTEM_CLEAR (0x00000202) + +#endif /* MB_CMD_SYSTEM_H_ */ + -- 2.7.4