blob: a7097c687b11a476a2952e73fc4e192c2e06d739 [file] [log] [blame]
/* Copyright 2019 NXP
* SPDX-License-Identifier: Apache-2.0
*/
#include <ex_sss_boot.h>
#include <fsl_sss_se05x_apis.h>
#include <nxLog_App.h>
#include <openssl/asn1t.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.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>
#include <time.h>
#include "certificate.h"
static ex_sss_boot_ctx_t gex_sss_gen_cert;
#define EX_SSS_BOOT_PCONTEXT (&gex_sss_gen_cert)
#define EX_SSS_BOOT_DO_ERASE 0
#define EX_SSS_BOOT_EXPOSE_ARGC_ARGV 0
#include <ex_sss_main_inc.h>
sss_status_t ex_sss_entry(ex_sss_boot_ctx_t *pCtx)
{
sss_status_t status = kStatus_SSS_Fail;
sss_object_t obj;
X509 *certificate = X509_new();
status = sss_key_object_init(&obj, &pCtx->ks);
if (status != kStatus_SSS_Success) {
LOG_E("sss_key_object_init Failed!!!");
return status;
}
if (!X509_set_version(certificate, 2)) {
return status;
}
ASN1_INTEGER *serialNumber = ASN1_INTEGER_new();
if (!ASN1_INTEGER_set(serialNumber, 1) || !X509_set_serialNumber(certificate, serialNumber)) {
return status;
}
X509_NAME *subjectName = X509_NAME_new();
if (!X509_NAME_add_entry_by_txt(subjectName,
"CN",
MBSTRING_ASC,
(const unsigned char *)"selfSignedCA",
-1 /* len */,
-1 /* loc */,
0 /* set */) ||
!X509_set_subject_name(certificate, subjectName)) {
return status;
}
if (!X509_set_issuer_name(certificate, subjectName)) {
return status;
}
ASN1_TIME *notBefore = ASN1_TIME_new();
time_t activeDateTime = time(NULL);
if (!ASN1_TIME_set(notBefore, activeDateTime) || !X509_set_notBefore(certificate, notBefore)) {
return status;
}
ASN1_TIME *notAfter = ASN1_TIME_new();
time_t notAfterTime = time(NULL);
if (!ASN1_TIME_set(notAfter, notAfterTime * 2) || !X509_set_notAfter(certificate, notAfter)) {
return status;
}
/*Generate a keypair*/
uint8_t key[550];
size_t keybytelen = sizeof(key);
size_t keybitlen = keybytelen * 8;
uint32_t keyId = CERTIFICATE_KEY_ID;
status = sss_key_object_get_handle(&obj, keyId);
status = sss_key_store_get_key(&pCtx->ks, &obj, key, &keybytelen, &keybitlen);
LOG_I("sss_key_store_get_key status %x", status);
if (status != kStatus_SSS_Success)
return status;
status = kStatus_SSS_Fail;
BIO *bio = BIO_new_mem_buf(key, (int)sizeof(key));
if (bio == NULL) {
return status;
}
EVP_PKEY *pKey = d2i_PUBKEY_bio(bio, NULL);
if (pKey == NULL) {
return status;
}
/*Add public key*/
if (!X509_set_pubkey(certificate, pKey)) {
return status;
}
X509V3_CTX x509v3_ctx = {0};
char *subjectAlternateName = "email:d:NXP-A71CH-D:377813426378607196897279";
char *basicConstraints = "CA:TRUE";
X509_EXTENSION *extension_SAN = X509V3_EXT_nconf_nid(NULL, &x509v3_ctx, NID_subject_alt_name, subjectAlternateName);
if (!X509_add_ext(certificate, extension_SAN, -1)) {
return status;
}
X509_EXTENSION *extension_BasicConstraints =
X509V3_EXT_nconf_nid(NULL, &x509v3_ctx, NID_basic_constraints, basicConstraints);
if (!X509_add_ext(certificate, extension_BasicConstraints, -1)) {
return status;
}
int type = NID_ecdsa_with_SHA256;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
X509_ALGOR *tbs_algo = certificate->cert_info->signature;
X509_ALGOR *algo = certificate->sig_alg;
X509_ALGOR_set0(algo, OBJ_nid2obj(type), V_ASN1_NULL, NULL);
#else
const X509_ALGOR *tmp_tbs_algo = X509_get0_tbs_sigalg((const X509 *)certificate);
X509_ALGOR *tbs_algo = (X509_ALGOR *)tmp_tbs_algo;
#endif
X509_ALGOR_set0(tbs_algo, OBJ_nid2obj(type), V_ASN1_NULL, NULL);
/*Convert to DER format to sign*/
int len = 0;
uint8_t tbs_bytes[500];
uint8_t *p_tbs_bytes = &tbs_bytes[0];
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
X509_CINF *cinf = certificate->cert_info;
len = i2d_X509_CINF(cinf, &p_tbs_bytes);
#else
len = i2d_re_X509_tbs(certificate, &p_tbs_bytes);
LOG_I("len = %d", len);
#endif
/*Calculate digest for signing*/
uint8_t digest[32] = {0};
size_t digestLen = sizeof(digest);
sss_digest_t digestCtx;
status = sss_digest_context_init(&digestCtx, &pCtx->session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest);
status = sss_digest_one_go(&digestCtx, &tbs_bytes[0], len, digest, &digestLen);
sss_digest_context_free(&digestCtx);
if (status != kStatus_SSS_Success)
return status;
status = kStatus_SSS_Fail;
/*Sign digest*/
sss_asymmetric_t asymmCtx;
uint8_t signature[256];
uint8_t *p_signature = &signature[0];
size_t signatureLen = sizeof(signature);
status = sss_asymmetric_context_init(&asymmCtx, &pCtx->session, &obj, kAlgorithm_SSS_SHA256, kMode_SSS_Sign);
status = sss_asymmetric_sign_digest(&asymmCtx, digest, digestLen, signature, &signatureLen);
if (status != kStatus_SSS_Success)
return status;
/*Add signature to certificate structure*/
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
ASN1_BIT_STRING *sig = certificate->signature;
#else
ASN1_BIT_STRING *sig;
const X509_ALGOR *tmp_algo = NULL;
X509_get0_signature((const ASN1_BIT_STRING **)&sig, &tmp_algo, (const X509 *)certificate);
X509_ALGOR *algo = (X509_ALGOR *)tmp_algo;
X509_ALGOR_set0(algo, OBJ_nid2obj(type), V_ASN1_NULL, NULL);
#endif
len = ASN1_BIT_STRING_set(sig, p_signature, signatureLen);
unsigned char cert[2000];
unsigned char *pCert = &cert[0];
len = i2d_X509(certificate, NULL);
if (len == 0) {
LOG_I("i2d_X509 Failed");
return kStatus_SSS_Fail;
}
len = i2d_X509(certificate, &pCert);
LOG_AU8_I(cert, len);
sss_object_t cert_obj;
sss_key_part_t keyPart = kSSS_KeyPart_Default;
sss_cipher_type_t cipherType = kSSS_CipherType_Binary;
status = sss_key_object_init(&cert_obj, &pCtx->ks);
status = sss_key_object_allocate_handle(&cert_obj, keyId + 1, keyPart, cipherType, len, kKeyObject_Mode_Persistent);
status = sss_key_store_set_key(&pCtx->ks, &cert_obj, cert, len, len * 8, NULL, 0);
if (status != kStatus_SSS_Success)
LOG_E("Failed to inject generated certificate");
else
LOG_I("Success");
return status;
}