blob: d1eb14d69ac64f0a06de1f3a7118ea7ae0ee6ec4 [file] [log] [blame]
/* Copyright 2019 NXP
* SPDX-License-Identifier: Apache-2.0
*/
#include "seTool.h"
#include <ex_sss_boot.h>
#include <fsl_sss_se05x_apis.h>
#include <nxEnsure.h>
#include <nxLog_App.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <se05x_APDU.h>
#include <se05x_const.h>
#include <se05x_ecc_curves.h>
#include <se05x_ecc_curves_values.h>
#include <se05x_tlv.h>
#include <stdio.h>
#include <string.h>
static ex_sss_boot_ctx_t gex_sss_se_tool;
#define EX_SSS_BOOT_PCONTEXT (&gex_sss_se_tool)
#define EX_SSS_BOOT_DO_ERASE 0
#define EX_SSS_BOOT_EXPOSE_ARGC_ARGV 1
#include <ex_sss_main_inc.h>
void usage()
{
LOG_W("Usage:");
LOG_W("\tseTool genECC <keyId>");
LOG_W("\tseTool setECC <keyId> <filename>");
LOG_W("\tseTool getPublic <keyId> <filename>");
LOG_W("\tseTool getRef <keyId> <filename>");
}
sss_status_t ex_sss_entry(ex_sss_boot_ctx_t *pCtx)
{
sss_status_t status = kStatus_SSS_Fail;
int argc = gex_sss_argc;
const char **argv = gex_sss_argv;
int genECC = 0;
int getPublic = 0;
int getRef = 0;
int setECC = 0;
if (argc < 2) {
usage();
goto exit;
}
if (strncmp(argv[1], "genECC", sizeof("genECC")) == 0) {
genECC = 1;
}
else if (strncmp(argv[1], "getPublic", sizeof("getPublic")) == 0) {
getPublic = 1;
}
else if (strncmp(argv[1], "getRef", sizeof("getRef")) == 0) {
getRef = 1;
}
else if (strncmp(argv[1], "setECC", sizeof("setECC")) == 0) {
setECC = 1;
}
else {
LOG_E("Invalid command line parameter");
usage();
goto exit;
}
if (genECC) {
if (argc < 3) {
usage();
goto exit;
}
long int id = strtoul(argv[2], NULL, 0);
uint32_t keyId = (uint32_t)(id);
/*We demonstrate for cipher type and key size corresponding to NISTP-256 keypair only*/
sss_object_t obj;
sss_key_part_t keyPart = kSSS_KeyPart_Pair;
sss_cipher_type_t cipherType = kSSS_CipherType_EC_NIST_P;
size_t keyBitLen = 256;
status = sss_key_object_init(&obj, &pCtx->ks);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status =
sss_key_object_allocate_handle(&obj, keyId, keyPart, cipherType, keyBitLen * 8, kKeyObject_Mode_Persistent);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status = sss_key_store_generate_key(&pCtx->ks, &obj, keyBitLen, NULL);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
}
else if (getPublic) {
if (argc < 4) {
usage();
goto exit;
}
long int id = strtoul(argv[2], NULL, 0);
uint32_t keyId = (uint32_t)(id);
/*We demonstrate for cipher type and key size corresponding to NISTP-256 keypair only*/
sss_object_t obj;
size_t keyBitLen = 256;
uint8_t key[256] = {0};
size_t keyByteLen = sizeof(key);
status = sss_key_object_init(&obj, &pCtx->ks);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status = sss_key_object_get_handle(&obj, keyId);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status = sss_key_store_get_key(&pCtx->ks, &obj, key, &keyByteLen, &keyBitLen);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
BIO *bio = BIO_new_mem_buf(key, (int)sizeof(key));
if (bio == NULL) {
LOG_E("Unable to initialize BIO");
status = kStatus_SSS_Fail;
goto exit;
}
EVP_PKEY *pKey = d2i_PUBKEY_bio(bio, NULL);
if (!pKey) {
LOG_E("Failed to load public key");
status = kStatus_SSS_Fail;
goto exit;
}
char file_name[MAX_FILE_NAME_SIZE] = {0};
FILE *fp = NULL;
strncpy(file_name, argv[3], sizeof(file_name) - 1);
fp = fopen(file_name, "wb+");
if (fp == NULL) {
LOG_E("Can not open the file");
status = kStatus_SSS_Fail;
goto exit;
}
else {
PEM_write_PUBKEY(fp, pKey);
fclose(fp);
}
}
else if (getRef) {
if (argc < 4) {
usage();
goto exit;
}
long int id = strtoul(argv[2], NULL, 0);
uint32_t keyId = (uint32_t)(id);
/*We demonstrate for cipher type and key size corresponding to NISTP-256 keypair only*/
sss_object_t obj;
size_t keyBitLen = 256;
uint8_t key[256] = {0};
size_t keyByteLen = sizeof(key);
uint8_t priv_header[] = PRIV_PREFIX_NIST_P_256;
uint8_t pub_header[] = PUBLIC_PREFIX_NIST_P_256;
uint8_t magic[] = MAGIC_BYTES_SE05X_OPENSSL_ENGINE;
uint8_t ref[256] = {0};
size_t ref_len = 0;
uint8_t id_array[4] = {0};
status = sss_key_object_init(&obj, &pCtx->ks);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status = sss_key_object_get_handle(&obj, keyId);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status = sss_key_store_get_key(&pCtx->ks, &obj, key, &keyByteLen, &keyBitLen);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
memcpy(&ref[ref_len], priv_header, sizeof(priv_header));
ref_len += sizeof(priv_header);
id_array[0] = (keyId & 0xFF000000) >> (8 * 3);
id_array[1] = (keyId & 0x00FF0000) >> (8 * 2);
id_array[2] = (keyId & 0x0000FF00) >> (8 * 1);
id_array[3] = (keyId & 0x000000FF) >> (8 * 0);
memcpy(&ref[ref_len], id_array, sizeof(id_array));
ref_len += sizeof(id_array);
memcpy(&ref[ref_len], magic, sizeof(magic));
ref_len += sizeof(magic);
ref[ref_len++] = 0x10; // Hardcoded for Keypair
ref[ref_len++] = 0x00; // Hardcoded as 0x00
memcpy(&ref[ref_len], pub_header, sizeof(pub_header));
ref_len += sizeof(pub_header);
if ((ref_len + (keyByteLen - 22)) > sizeof(ref)) {
status = kStatus_SSS_Fail;
goto exit;
}
if ((23 + (keyByteLen - 22)) > sizeof(key)) {
status = kStatus_SSS_Fail;
goto exit;
}
/* Copy only public key part */
memcpy(&ref[ref_len], &key[23], keyByteLen - 22);
ref_len += (keyByteLen - 22);
BIO *bio = BIO_new_mem_buf(ref, (int)(ref_len));
if (bio == NULL) {
LOG_E("Unable to initialize BIO");
status = kStatus_SSS_Fail;
goto exit;
}
EVP_PKEY *pKey = d2i_PrivateKey_bio(bio, NULL);
if (!pKey) {
LOG_E("Failed to load public key");
status = kStatus_SSS_Fail;
goto exit;
}
char file_name[MAX_FILE_NAME_SIZE] = {0};
FILE *fp = NULL;
strncpy(file_name, argv[3], sizeof(file_name) - 1);
fp = fopen(file_name, "wb+");
if (fp == NULL) {
LOG_E("Can not open the file");
status = kStatus_SSS_Fail;
goto exit;
}
else {
PEM_write_PrivateKey(fp, pKey, NULL, NULL, 0, NULL, NULL);
fclose(fp);
}
}
else if (setECC) {
if (argc < 4) {
usage();
goto exit;
}
long int id = strtoul(argv[2], NULL, 0);
uint32_t keyId = (uint32_t)(id);
/*We demonstrate for cipher type and key size corresponding to NISTP-256 keypair only*/
sss_object_t obj;
sss_key_part_t keyPart = kSSS_KeyPart_Pair;
sss_cipher_type_t cipherType = kSSS_CipherType_EC_NIST_P;
size_t keyBitLen = 256;
uint8_t key[256] = {0};
size_t keyByteLen = sizeof(key);
unsigned char *data = &key[0];
EVP_PKEY *pKey = NULL;
char file_name[MAX_FILE_NAME_SIZE] = {0};
FILE *fp = NULL;
strncpy(file_name, argv[3], sizeof(file_name) - 1);
fp = fopen(file_name, "rb");
if (fp == NULL) {
LOG_E("Can not open the file");
status = kStatus_SSS_Fail;
goto exit;
}
else {
PEM_read_PrivateKey(fp, &pKey, NULL, NULL);
fclose(fp);
if (pKey == NULL) {
LOG_E("Failed to read Keypair");
status = kStatus_SSS_Fail;
goto exit;
}
}
keyByteLen = i2d_PrivateKey(pKey, &data);
status = sss_key_object_init(&obj, &pCtx->ks);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status =
sss_key_object_allocate_handle(&obj, keyId, keyPart, cipherType, keyBitLen * 8, kKeyObject_Mode_Persistent);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
status = sss_key_store_set_key(&pCtx->ks, &obj, key, keyByteLen, keyBitLen, NULL, 0);
ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success);
}
exit:
return status;
}