diff options
author | Jorge Ramirez-Ortiz <jorge@foundries.io> | 2020-12-15 18:58:53 +0100 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2021-01-05 12:31:29 +0100 |
commit | d419b2b23d8e3ff143693519429fb528d951b276 (patch) | |
tree | 43218ba392fd6333aec0ecbe7dd935e0ff1327a2 /core | |
parent | fab914923b94fccbb1e77538a355a8cdcad6b9a4 (diff) |
crypto: se050: adaptors: elliptic curve
APDU and utility functions required to support elliptic curve
cryptography.
Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
Acked-by: Etienne Carriere <etienne.carriere@linaro.org>
Diffstat (limited to 'core')
4 files changed, 250 insertions, 0 deletions
diff --git a/core/drivers/crypto/se050/adaptors/apis/apdu.c b/core/drivers/crypto/se050/adaptors/apis/apdu.c index 21ac2859..d00559f2 100644 --- a/core/drivers/crypto/se050/adaptors/apis/apdu.c +++ b/core/drivers/crypto/se050/adaptors/apis/apdu.c @@ -524,3 +524,209 @@ sss_status_t se050_scp03_send_rotate_cmd(pSe05xSession_t ctx, return kStatus_SSS_Fail; } + +static uint8_t *alloc_pubkey_buf(struct se050_ecc_keypub *keypub, size_t *len) +{ + size_t pubkey_len = 0; + uint8_t *pubkey = NULL; + uint8_t *buf = NULL; + + pubkey_len = keypub->x_len + keypub->y_len + 1; + buf = malloc(pubkey_len); + if (!buf) + return NULL; + + *buf = 0x04; + pubkey = buf + 1; + memcpy(pubkey, keypub->x, keypub->x_len); + memcpy(pubkey + keypub->x_len, keypub->y, keypub->y_len); + *len = pubkey_len; + + return buf; +} + +sss_status_t se050_ecc_gen_shared_secret(pSe05xSession_t ctx, uint32_t kid, + struct se050_ecc_keypub *keypub, + uint8_t *secret, size_t *len) +{ + smStatus_t status = SM_OK; + uint8_t *buf = NULL; + size_t pubkey_len = 0; + + if (!keypub || !secret || !len) + return kStatus_SSS_Fail; + + buf = alloc_pubkey_buf(keypub, &pubkey_len); + if (!buf) + return kStatus_SSS_Fail; + + status = Se05x_API_ECGenSharedSecret(ctx, kid, + buf, pubkey_len, secret, len); + free(buf); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_ecc_public(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + SE05x_TransientType_t type, + struct se050_ecc_keypub *keypub) +{ + size_t pubkey_len = 0; + smStatus_t status = SM_NOT_OK; + uint8_t *buf = NULL; + + buf = alloc_pubkey_buf(keypub, &pubkey_len); + if (!buf) + return kStatus_SSS_Fail; + + k_object->curve_id = keypub->curve; + status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, + k_object->keyId, + keypub->curve, + NULL, + 0, + buf, + pubkey_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_Public); + free(buf); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_ecc_private(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + SE05x_TransientType_t type, + struct se050_ecc_keypair *keypair) +{ + smStatus_t status = SM_NOT_OK; + + k_object->curve_id = keypair->pub.curve; + status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, + k_object->keyId, + keypair->pub.curve, + keypair->d, + keypair->d_len, + NULL, + 0, + (SE05x_INS_t)type, + kSE05x_KeyPart_Private); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_ecc_pair(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + SE05x_TransientType_t type, + struct se050_ecc_keypair *keypair) +{ + size_t pubkey_len = 0; + smStatus_t status = SM_NOT_OK; + uint8_t *buf = NULL; + + buf = alloc_pubkey_buf(&keypair->pub, &pubkey_len); + if (!buf) + return kStatus_SSS_Fail; + + k_object->curve_id = keypair->pub.curve; + status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, + k_object->keyId, + keypair->pub.curve, + keypair->d, + keypair->d_len, + buf, + pubkey_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_Pair); + free(buf); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t se050_key_store_set_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *k_object, + struct se050_ecc_keypair *keypair, + struct se050_ecc_keypub *keypub) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + Se05xPolicy_t policy = { }; + + if (!store || !store->session || !k_object) + return kStatus_SSS_Fail; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + switch (k_object->objectType) { + case kSSS_KeyPart_Public: + if (!keypub) + return kStatus_SSS_Fail; + + return set_ecc_public(&store->session->s_ctx, + &policy, k_object, type, keypub); + case kSSS_KeyPart_Private: + if (!keypair) + return kStatus_SSS_Fail; + + return set_ecc_private(&store->session->s_ctx, + &policy, k_object, type, keypair); + case kSSS_KeyPart_Pair: + if (!keypair) + return kStatus_SSS_Fail; + + return set_ecc_pair(&store->session->s_ctx, + &policy, k_object, type, keypair); + default: + return kStatus_SSS_Fail; + } +} + +sss_status_t se050_key_store_get_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *k_object, + uint8_t *key, size_t *key_len) +{ + smStatus_t status = SM_NOT_OK; + uint8_t *buf = NULL; + size_t buflen = 0; + + if (!store || !store->session || !k_object || !key || !key_len) + return kStatus_SSS_Fail; + + switch (k_object->cipherType) { + case kSSS_CipherType_EC_NIST_P: + case kSSS_CipherType_EC_NIST_K: + case kSSS_CipherType_EC_BRAINPOOL: + case kSSS_CipherType_EC_BARRETO_NAEHRIG: + case kSSS_CipherType_EC_MONTGOMERY: + case kSSS_CipherType_EC_TWISTED_ED: + add_ecc_header(key, &buf, &buflen, k_object->curve_id); + status = Se05x_API_ReadObject(&store->session->s_ctx, + k_object->keyId, 0, 0, + buf, key_len); + if (status != SM_OK) + return kStatus_SSS_Fail; + + *key_len += buflen; + buflen = *key_len; + get_ecc_raw_data(key, &buf, &buflen, k_object->curve_id); + + /* return only the binary data */ + *key_len = buflen; + memcpy(key, buf, buflen); + return kStatus_SSS_Success; + default: + return kStatus_SSS_Fail; + } +} diff --git a/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h b/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h index b6247561..766d12e3 100644 --- a/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h +++ b/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h @@ -54,4 +54,31 @@ sss_status_t se050_get_free_memory(pSe05xSession_t ctx, uint16_t *t, sss_status_t se050_scp03_send_rotate_cmd(pSe05xSession_t ctx, struct s050_scp_rotate_cmd *cmd); +struct se050_ecc_keypub { + uint8_t *x; + size_t x_len; + uint8_t *y; + size_t y_len; + uint32_t curve; +}; + +struct se050_ecc_keypair { + struct se050_ecc_keypub pub; + uint8_t *d; + size_t d_len; +}; + +sss_status_t se050_key_store_set_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *object, + struct se050_ecc_keypair *pair, + struct se050_ecc_keypub *pub); + +sss_status_t se050_key_store_get_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *object, + uint8_t *key, size_t *len); + +sss_status_t se050_ecc_gen_shared_secret(pSe05xSession_t ctx, uint32_t id, + struct se050_ecc_keypub *pub, + uint8_t *secret, size_t *len); + #endif /* SE050_APDU_APIS_H_ */ diff --git a/core/drivers/crypto/se050/adaptors/include/se050_utils.h b/core/drivers/crypto/se050/adaptors/include/se050_utils.h index 95ecad61..e25067c1 100644 --- a/core/drivers/crypto/se050/adaptors/include/se050_utils.h +++ b/core/drivers/crypto/se050/adaptors/include/se050_utils.h @@ -33,8 +33,10 @@ struct s050_scp_rotate_cmd { sss_status_t se050_get_oid(sss_key_object_mode_t type, uint32_t *val); struct rsa_keypair; +struct ecc_keypair; uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key); +uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key); uint64_t se050_generate_private_key(uint32_t oid); void se050_refcount_init_ctx(uint8_t **cnt); diff --git a/core/drivers/crypto/se050/adaptors/utils/utils.c b/core/drivers/crypto/se050/adaptors/utils/utils.c index 34dbdd05..83edf944 100644 --- a/core/drivers/crypto/se050/adaptors/utils/utils.c +++ b/core/drivers/crypto/se050/adaptors/utils/utils.c @@ -134,6 +134,21 @@ uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key) return se050_key(key_id); } +uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key) +{ + uint64_t key_id = 0; + + if (!key) + return 0; + + if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t)) + return 0; + + crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id); + + return se050_key(key_id); +} + uint64_t se050_generate_private_key(uint32_t oid) { return WATERMARKED(oid); |