in core/asn1/x509_cert_build.c [612:716]
int x509_cert_build_create_self_signed_certificate (const struct x509_engine *engine,
struct x509_certificate *cert, const uint8_t *priv_key, size_t key_length,
enum hash_type sig_hash, const uint8_t *serial_num, size_t serial_length, const char *name,
int type, const struct x509_extension_builder *const *extra_extensions, size_t ext_count)
{
const struct x509_engine_cert_build *x509 = (const struct x509_engine_cert_build*) engine;
DERBuilderContext *der;
struct ecc_public_key ecc_pub_key;
uint8_t *pub_key_der = NULL;
size_t pub_key_der_len;
const uint8_t *auth_key;
uint8_t auth_key_digest[SHA1_DIGEST_LENGTH];
const int *sig_oid;
int status;
if ((x509 == NULL) || (cert == NULL) || (priv_key == NULL) || (key_length == 0) ||
(serial_num == NULL) || (serial_length == 0) || (name == NULL)) {
return X509_ENGINE_INVALID_ARGUMENT;
}
if ((ext_count != 0) && (extra_extensions == NULL)) {
return X509_ENGINE_INVALID_ARGUMENT;
}
switch (sig_hash) {
case HASH_TYPE_SHA256:
sig_oid = ecdsaWithSHA256OID;
break;
case HASH_TYPE_SHA384:
sig_oid = ecdsaWithSHA384OID;
break;
case HASH_TYPE_SHA512:
sig_oid = ecdsaWithSHA512OID;
break;
default:
return X509_ENGINE_UNSUPPORTED_SIG_HASH;
}
status = x509_cert_build_check_serial_number (serial_num, serial_length);
if (status != 0) {
return status;
}
cert->context = NULL;
status = x509->ecc->init_key_pair (x509->ecc, priv_key, key_length, NULL, &ecc_pub_key);
if (status != 0) {
return status;
}
status = x509->ecc->get_public_key_der (x509->ecc, &ecc_pub_key, &pub_key_der,
&pub_key_der_len);
if (status != 0) {
goto err_free_key;
}
status = ecc_der_decode_public_key_no_copy (pub_key_der, pub_key_der_len, &auth_key);
if (ROT_IS_ERROR (status)) {
/* This is highly unlikely since the encoded DER just came from the ECC engine. */
goto err_free_key;
}
status = x509->hash->calculate_sha1 (x509->hash, auth_key, status, auth_key_digest,
sizeof (auth_key_digest));
if (status != 0) {
goto err_free_key_der;
}
der = x509_cert_build_new_cert (x509);
if (der == NULL) {
status = X509_ENGINE_NO_MEMORY;
goto err_free_key_der;
}
status = x509_cert_build_build_certificate_tbs_data (der, name, auth_key_digest, name,
auth_key_digest, serial_num, serial_length, pub_key_der, pub_key_der_len, sig_oid, type,
extra_extensions, ext_count);
if (status != 0) {
status = (status == -1) ? X509_ENGINE_SELF_SIGNED_FAILED : status;
goto err_free_cert;
}
status = x509_cert_build_sign_certificate (der, priv_key, key_length, x509->ecc, x509->hash,
sig_hash, sig_oid);
if (status == -1) {
status = X509_ENGINE_SELF_SIGNED_FAILED;
}
err_free_cert:
if (status == 0) {
cert->context = der;
}
else {
x509_cert_build_free_cert (der);
}
err_free_key_der:
platform_free (pub_key_der);
err_free_key:
x509->ecc->release_key_pair (x509->ecc, NULL, &ecc_pub_key);
return status;
}