int x509_mbedtls_create_csr()

in core/asn1/x509_mbedtls.c [254:418]


int x509_mbedtls_create_csr (const struct x509_engine *engine, const uint8_t *priv_key,
	size_t key_length, enum hash_type sig_hash, const char *name, int type, const uint8_t *eku,
	size_t eku_length, const struct x509_extension_builder *const *extra_extensions,
	size_t ext_count, uint8_t **csr, size_t *csr_length)
{
	const struct x509_engine_mbedtls *mbedtls = (const struct x509_engine_mbedtls*) engine;
	mbedtls_x509write_csr x509;
	mbedtls_pk_context key;
	mbedtls_md_type_t md_alg;
	char *subject;
	size_t i;
	int status;

	if (csr == NULL) {
		return X509_ENGINE_INVALID_ARGUMENT;
	}

	*csr = NULL;
	if ((mbedtls == NULL) || (priv_key == NULL) || (name == NULL) || (csr_length == NULL) ||
		(key_length == 0)) {
		return X509_ENGINE_INVALID_ARGUMENT;
	}

	if ((eku_length != 0) && (eku == NULL)) {
		return X509_ENGINE_INVALID_ARGUMENT;
	}

	if ((ext_count != 0) && (extra_extensions == NULL)) {
		return X509_ENGINE_INVALID_ARGUMENT;
	}

	if ((type == X509_CERT_END_ENTITY) && (eku != NULL)) {
		return X509_ENGINE_NOT_CA_CERT;
	}

	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;
	}

	mbedtls_x509write_csr_init (&x509);

	status = x509_mbedtls_load_key (&key, priv_key, key_length, true);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_X509_LOAD_KEY_EC, status, 0);

		goto err_free_csr;
	}

	mbedtls_x509write_csr_set_key (&x509, &key);

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

	strcpy (subject, "CN=");
	strcpy (&subject[3], name);
	status = mbedtls_x509write_csr_set_subject_name (&x509, subject);
	if (status != 0) {
		debug_log_create_entry (DEBUG_LOG_SEVERITY_INFO, DEBUG_LOG_COMPONENT_CRYPTO,
			CRYPTO_LOG_MSG_MBEDTLS_X509_CSR_SET_SUBJECT_EC, status, 0);

		goto err_free_subject;
	}

	if (type) {
		status = x509_mbedtls_add_key_usage_extension (&x509.extensions,
			MBEDTLS_X509_KU_KEY_CERT_SIGN);
	}
	else {
		status = x509_mbedtls_add_key_usage_extension (&x509.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.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 (eku != NULL) {
		status = x509_mbedtls_add_extended_key_usage_extension (&x509.extensions, (char*) eku,
			eku_length, false);
		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.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.extensions);
		if (status != 0) {
			goto err_free_subject;
		}
	}

	mbedtls_x509write_csr_set_md_alg (&x509, md_alg);
	status = mbedtls_x509write_csr_der (&x509, 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_X509_CSR_DER_WRITE_EC, status, 0);

		goto err_free_subject;
	}

	*csr = platform_malloc (status);
	if (*csr == NULL) {
		status = X509_ENGINE_NO_MEMORY;
		goto err_free_subject;
	}

	memcpy (*csr, &mbedtls->state->der_buf[X509_MAX_SIZE - status], status);
	*csr_length = status;
	status = 0;

err_free_subject:
	platform_free (subject);
err_free_key:
	mbedtls_pk_free (&key);
err_free_csr:
	mbedtls_x509write_csr_free (&x509);

	return status;
}