static int x509_mbedtls_create_certificate()

in core/asn1/x509_mbedtls.c [441:642]


static int x509_mbedtls_create_certificate (const struct x509_engine_mbedtls *mbedtls,
	struct x509_certificate *cert, mbedtls_pk_context *cert_key, enum hash_type sig_hash,
	const uint8_t *serial_num, size_t serial_length, const char *name, int type,
	mbedtls_pk_context *ca_key, const struct x509_certificate *ca_cert,
	const struct x509_extension_builder *const *extra_extensions, size_t ext_count)
{
	mbedtls_x509_crt *x509;
	mbedtls_x509_crt *ca_x509;
	mbedtls_x509write_cert x509_build;
	mbedtls_pk_context *signing_key;
	mbedtls_md_type_t md_alg;
	char *subject;
	size_t i;
	int status;

	switch (sig_hash) {
		case HASH_TYPE_SHA256:
			md_alg = MBEDTLS_MD_SHA256;
			break;

		case HASH_TYPE_SHA384:
			md_alg = MBEDTLS_MD_SHA384;
			break;

		case HASH_TYPE_SHA512:
			md_alg = MBEDTLS_MD_SHA512;
			break;

		default:
			return X509_ENGINE_UNSUPPORTED_SIG_HASH;
	}

	if (ca_key) {
		signing_key = ca_key;
		ca_x509 = (mbedtls_x509_crt*) ca_cert->context;
	}
	else {
		signing_key = cert_key;
		ca_x509 = NULL;
	}

	mbedtls_x509write_crt_init (&x509_build);
	mbedtls_x509write_crt_set_version (&x509_build, MBEDTLS_X509_CRT_VERSION_3);
	mbedtls_x509write_crt_set_subject_key (&x509_build, cert_key);
	mbedtls_x509write_crt_set_issuer_key (&x509_build, signing_key);

	status = mbedtls_mpi_read_binary (&x509_build.serial, serial_num, serial_length);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_MPI_READ_BIN_EC, status, 0);

		goto err_free_crt;
	}

	if (mbedtls_mpi_cmp_int (&x509_build.serial, 0) == 0) {
		status = X509_ENGINE_INVALID_SERIAL_NUM;
		goto err_free_crt;
	}

	subject = platform_malloc (strlen (name) + 4);
	if (subject == NULL) {
		status = X509_ENGINE_NO_MEMORY;
		goto err_free_crt;
	}

	strcpy (subject, "CN=");
	strcpy (&subject[3], name);
	status = mbedtls_x509write_crt_set_subject_name (&x509_build, subject);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_CRT_SET_SUBJECT_EC, status, 0);

		goto err_free_subject;
	}

	if (!ca_key) {
		status = mbedtls_x509write_crt_set_issuer_name (&x509_build, subject);

		if (status != 0) {
			debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
				CRYPTO_LOG_MSG_MBEDTLS_CRT_SET_ISSUER_EC, status, 0);
		}
	}
	else {
		mbedtls_asn1_store_named_data (&x509_build.issuer, (char*) ca_x509->subject.oid.p,
			ca_x509->subject.oid.len, ca_x509->subject.val.p, ca_x509->subject.val.len);
		if (x509_build.issuer == NULL) {
			status = X509_ENGINE_NO_MEMORY;
		}

		x509_build.issuer->val.tag = MBEDTLS_ASN1_UTF8_STRING;
	}

	if (status != 0) {
		goto err_free_subject;
	}

	status = mbedtls_x509write_crt_set_validity (&x509_build, "20180101000000", "99991231235959");
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_CRT_SET_VALIDITY_EC, status, 0);

		goto err_free_subject;
	}

	status = mbedtls_x509write_crt_set_subject_key_identifier (&x509_build);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_CRT_SET_SUBJECT_EC, status, 0);

		goto err_free_subject;
	}

	status = mbedtls_x509write_crt_set_authority_key_identifier (&x509_build);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_CRT_SET_AUTHORITY_EC, status, 0);

		goto err_free_subject;
	}

	if (type) {
		status = x509_mbedtls_add_key_usage_extension (&x509_build.extensions,
			MBEDTLS_X509_KU_KEY_CERT_SIGN);
	}
	else {
		status = x509_mbedtls_add_key_usage_extension (&x509_build.extensions,
			(MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_AGREEMENT));
	}

	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_X509_ADD_KEY_USAGE_EC, status, 0);

		goto err_free_subject;
	}

	if (type == X509_CERT_END_ENTITY) {
		status = x509_mbedtls_add_extended_key_usage_extension (&x509_build.extensions,
			MBEDTLS_OID_CLIENT_AUTH, MBEDTLS_OID_SIZE (MBEDTLS_OID_CLIENT_AUTH), true);
		if (status != 0) {
			debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
				CRYPTO_LOG_MSG_MBEDTLS_X509_ADD_EXT_KEY_USAGE_EC, status, 0);

			goto err_free_subject;
		}
	}

	if (type) {
		status = x509_mbedtls_add_basic_constraints_extension (&x509_build.extensions, true,
			X509_CERT_PATHLEN (type));
		if (status != 0) {
			debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
				CRYPTO_LOG_MSG_MBEDTLS_X509_ADD_BASIC_CONSTRAINTS_EC, status, 0);

			goto err_free_subject;
		}
	}

	for (i = 0; i < ext_count; i++) {
		status = x509_mbedtls_add_custom_extension (extra_extensions[i], &x509_build.extensions);
		if (status != 0) {
			goto err_free_subject;
		}
	}

	mbedtls_x509write_crt_set_md_alg (&x509_build, md_alg);
	status = mbedtls_x509write_crt_der (&x509_build, mbedtls->state->der_buf, X509_MAX_SIZE,
		mbedtls_ctr_drbg_random, &mbedtls->state->ctr_drbg);
	if (status < 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_CRT_WRITE_DER_EC, status, 0);

		goto err_free_subject;
	}

	x509 = x509_mbedtls_new_cert ();
	if (x509 == NULL) {
		status = X509_ENGINE_NO_MEMORY;
		goto err_free_subject;
	}

	status = mbedtls_x509_crt_parse_der (x509, &mbedtls->state->der_buf[X509_MAX_SIZE - status],
		status);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_CRT_PARSE_DER_EC, status, 0);

		x509_mbedtls_free_cert (x509);
		goto err_free_subject;
	}

	cert->context = x509;
	status = 0;

err_free_subject:
	platform_free (subject);
err_free_crt:
	mbedtls_x509write_crt_free (&x509_build);

	return status;
}