mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-02-03 20:54:00 +00:00
Added ability to include the SubjectAltName extension to a CSR
Signed-off-by: Hannes Tschofenig <hannes.tschofenig@arm.com>
This commit is contained in:
parent
ec718afb41
commit
6b108606fa
@ -83,6 +83,19 @@ typedef struct mbedtls_x509write_csr {
|
|||||||
}
|
}
|
||||||
mbedtls_x509write_csr;
|
mbedtls_x509write_csr;
|
||||||
|
|
||||||
|
typedef struct mbedtls_x509_san_node {
|
||||||
|
int type; /**< Subject Alternative Name types */
|
||||||
|
char *name; /**< Value, following the syntax allowed bythe type */
|
||||||
|
size_t len; /**< Length of the provided value */
|
||||||
|
}
|
||||||
|
mbedtls_x509_san_node;
|
||||||
|
|
||||||
|
typedef struct mbedtls_x509_san_list {
|
||||||
|
mbedtls_x509_san_node node;
|
||||||
|
struct mbedtls_x509_san_list *next;
|
||||||
|
}
|
||||||
|
mbedtls_x509_san_list;
|
||||||
|
|
||||||
#if defined(MBEDTLS_X509_CSR_PARSE_C)
|
#if defined(MBEDTLS_X509_CSR_PARSE_C)
|
||||||
/**
|
/**
|
||||||
* \brief Load a Certificate Signing Request (CSR) in DER format
|
* \brief Load a Certificate Signing Request (CSR) in DER format
|
||||||
@ -220,6 +233,20 @@ void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_typ
|
|||||||
*/
|
*/
|
||||||
int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage);
|
int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set Subject Alternative Name
|
||||||
|
*
|
||||||
|
* \param ctx CSR context to use
|
||||||
|
* \param san_list List of SAN values
|
||||||
|
*
|
||||||
|
* \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED
|
||||||
|
*
|
||||||
|
* \note Only "dnsName", "uniformResourceIdentifier" and "otherName",
|
||||||
|
* as defined in RFC 5280, are supported.
|
||||||
|
*/
|
||||||
|
int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
|
||||||
|
const mbedtls_x509_san_list *san_list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the Netscape Cert Type flags
|
* \brief Set the Netscape Cert Type flags
|
||||||
* (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL)
|
* (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL)
|
||||||
|
@ -85,6 +85,79 @@ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
|
|||||||
critical, val, val_len);
|
critical, val, val_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
|
||||||
|
const mbedtls_x509_san_list *san_list)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
size_t sandeep = 0;
|
||||||
|
const mbedtls_x509_san_list *cur = san_list;
|
||||||
|
unsigned char *buf;
|
||||||
|
unsigned char *p;
|
||||||
|
size_t len;
|
||||||
|
size_t buflen = 0;
|
||||||
|
|
||||||
|
/* Determine the maximum size of the SubjectAltName list */
|
||||||
|
while (cur != NULL) {
|
||||||
|
if (cur->node.len <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate size of the required buffer:
|
||||||
|
* + length of value for each name entry,
|
||||||
|
* + maximum 4 bytes for the length field,
|
||||||
|
* + 1 byte for the tag/type.
|
||||||
|
*/
|
||||||
|
buflen += cur->node.len + 4 + 1;
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the extra length field and tag */
|
||||||
|
buflen += 4 + 1;
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
buf = mbedtls_calloc(1, buflen);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_platform_zeroize(buf, buflen);
|
||||||
|
p = buf + buflen;
|
||||||
|
|
||||||
|
/* Write ASN.1-based structure */
|
||||||
|
cur = san_list;
|
||||||
|
len = 0;
|
||||||
|
while (cur != NULL) {
|
||||||
|
MBEDTLS_ASN1_CHK_ADD(len,
|
||||||
|
mbedtls_asn1_write_raw_buffer(&p, buf,
|
||||||
|
(const unsigned char *) cur->node.name,
|
||||||
|
cur->node.len));
|
||||||
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, cur->node.len));
|
||||||
|
MBEDTLS_ASN1_CHK_ADD(len,
|
||||||
|
mbedtls_asn1_write_tag(&p, buf,
|
||||||
|
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
|
||||||
|
cur->node.type));
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
|
||||||
|
MBEDTLS_ASN1_CHK_ADD(len,
|
||||||
|
mbedtls_asn1_write_tag(&p, buf,
|
||||||
|
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
|
||||||
|
|
||||||
|
ret = mbedtls_x509write_csr_set_extension(
|
||||||
|
ctx,
|
||||||
|
MBEDTLS_OID_SUBJECT_ALT_NAME,
|
||||||
|
MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
|
||||||
|
0,
|
||||||
|
buf + buflen - len,
|
||||||
|
len);
|
||||||
|
|
||||||
|
mbedtls_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
|
int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
|
||||||
{
|
{
|
||||||
unsigned char buf[4] = { 0 };
|
unsigned char buf[4] = { 0 };
|
||||||
|
@ -63,6 +63,11 @@ int main(void)
|
|||||||
" debug_level=%%d default: 0 (disabled)\n" \
|
" debug_level=%%d default: 0 (disabled)\n" \
|
||||||
" output_file=%%s default: cert.req\n" \
|
" output_file=%%s default: cert.req\n" \
|
||||||
" subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \
|
" subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \
|
||||||
|
" san=%%s default: (none)\n" \
|
||||||
|
" Comma-separated-list of values:\n" \
|
||||||
|
" DNS:value\n" \
|
||||||
|
" URI:value\n" \
|
||||||
|
" OTHER:value\n" \
|
||||||
" key_usage=%%s default: (empty)\n" \
|
" key_usage=%%s default: (empty)\n" \
|
||||||
" Comma-separated-list of values:\n" \
|
" Comma-separated-list of values:\n" \
|
||||||
" digital_signature\n" \
|
" digital_signature\n" \
|
||||||
@ -96,16 +101,17 @@ int main(void)
|
|||||||
* global options
|
* global options
|
||||||
*/
|
*/
|
||||||
struct options {
|
struct options {
|
||||||
const char *filename; /* filename of the key file */
|
const char *filename; /* filename of the key file */
|
||||||
const char *password; /* password for the key file */
|
const char *password; /* password for the key file */
|
||||||
int debug_level; /* level of debugging */
|
int debug_level; /* level of debugging */
|
||||||
const char *output_file; /* where to store the constructed key file */
|
const char *output_file; /* where to store the constructed key file */
|
||||||
const char *subject_name; /* subject name for certificate request */
|
const char *subject_name; /* subject name for certificate request */
|
||||||
unsigned char key_usage; /* key usage flags */
|
mbedtls_x509_san_list *san_list; /* subjectAltName for certificate request */
|
||||||
int force_key_usage; /* Force adding the KeyUsage extension */
|
unsigned char key_usage; /* key usage flags */
|
||||||
unsigned char ns_cert_type; /* NS cert type */
|
int force_key_usage; /* Force adding the KeyUsage extension */
|
||||||
int force_ns_cert_type; /* Force adding NsCertType extension */
|
unsigned char ns_cert_type; /* NS cert type */
|
||||||
mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */
|
int force_ns_cert_type; /* Force adding NsCertType extension */
|
||||||
|
mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
int write_certificate_request(mbedtls_x509write_csr *req, const char *output_file,
|
int write_certificate_request(mbedtls_x509write_csr *req, const char *output_file,
|
||||||
@ -145,11 +151,12 @@ int main(int argc, char *argv[])
|
|||||||
mbedtls_pk_context key;
|
mbedtls_pk_context key;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int i;
|
int i;
|
||||||
char *p, *q, *r;
|
char *p, *q, *r, *r2;
|
||||||
mbedtls_x509write_csr req;
|
mbedtls_x509write_csr req;
|
||||||
mbedtls_entropy_context entropy;
|
mbedtls_entropy_context entropy;
|
||||||
mbedtls_ctr_drbg_context ctr_drbg;
|
mbedtls_ctr_drbg_context ctr_drbg;
|
||||||
const char *pers = "csr example app";
|
const char *pers = "csr example app";
|
||||||
|
mbedtls_x509_san_list *cur, *prev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set to sane values
|
* Set to sane values
|
||||||
@ -175,6 +182,7 @@ usage:
|
|||||||
opt.ns_cert_type = DFL_NS_CERT_TYPE;
|
opt.ns_cert_type = DFL_NS_CERT_TYPE;
|
||||||
opt.force_ns_cert_type = DFL_FORCE_NS_CERT_TYPE;
|
opt.force_ns_cert_type = DFL_FORCE_NS_CERT_TYPE;
|
||||||
opt.md_alg = DFL_MD_ALG;
|
opt.md_alg = DFL_MD_ALG;
|
||||||
|
opt.san_list = NULL;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
|
|
||||||
@ -197,6 +205,52 @@ usage:
|
|||||||
}
|
}
|
||||||
} else if (strcmp(p, "subject_name") == 0) {
|
} else if (strcmp(p, "subject_name") == 0) {
|
||||||
opt.subject_name = q;
|
opt.subject_name = q;
|
||||||
|
} else if (strcmp(p, "san") == 0) {
|
||||||
|
prev = NULL;
|
||||||
|
|
||||||
|
while (q != NULL) {
|
||||||
|
if ((r = strchr(q, ',')) != NULL) {
|
||||||
|
*r++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = mbedtls_calloc(1, sizeof(mbedtls_x509_san_list));
|
||||||
|
if (cur == NULL) {
|
||||||
|
mbedtls_printf("Not enough memory for subjectAltName list\n");
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->next = NULL;
|
||||||
|
|
||||||
|
if ((r2 = strchr(q, ':')) != NULL) {
|
||||||
|
*r2++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(q, "URI") == 0) {
|
||||||
|
cur->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
|
||||||
|
} else if (strcmp(q, "DNS") == 0) {
|
||||||
|
cur->node.type = MBEDTLS_X509_SAN_DNS_NAME;
|
||||||
|
} else if (strcmp(q, "OTHER") == 0) {
|
||||||
|
cur->node.type = MBEDTLS_X509_SAN_OTHER_NAME;
|
||||||
|
} else {
|
||||||
|
mbedtls_free(cur);
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = r2;
|
||||||
|
|
||||||
|
cur->node.name = q;
|
||||||
|
cur->node.len = strlen(q);
|
||||||
|
|
||||||
|
if (prev == NULL) {
|
||||||
|
opt.san_list = cur;
|
||||||
|
} else {
|
||||||
|
prev->next = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = cur;
|
||||||
|
q = r;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (strcmp(p, "md") == 0) {
|
} else if (strcmp(p, "md") == 0) {
|
||||||
const mbedtls_md_info_t *md_info =
|
const mbedtls_md_info_t *md_info =
|
||||||
mbedtls_md_info_from_string(q);
|
mbedtls_md_info_from_string(q);
|
||||||
@ -274,14 +328,39 @@ usage:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the MD algorithm to use for the signature in the CSR */
|
||||||
mbedtls_x509write_csr_set_md_alg(&req, opt.md_alg);
|
mbedtls_x509write_csr_set_md_alg(&req, opt.md_alg);
|
||||||
|
|
||||||
|
/* Set the Key Usage Extension flags in the CSR */
|
||||||
if (opt.key_usage || opt.force_key_usage == 1) {
|
if (opt.key_usage || opt.force_key_usage == 1) {
|
||||||
mbedtls_x509write_csr_set_key_usage(&req, opt.key_usage);
|
ret = mbedtls_x509write_csr_set_key_usage(&req, opt.key_usage);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
mbedtls_printf(" failed\n ! mbedtls_x509write_csr_set_key_usage returned %d", ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the Cert Type flags in the CSR */
|
||||||
if (opt.ns_cert_type || opt.force_ns_cert_type == 1) {
|
if (opt.ns_cert_type || opt.force_ns_cert_type == 1) {
|
||||||
mbedtls_x509write_csr_set_ns_cert_type(&req, opt.ns_cert_type);
|
ret = mbedtls_x509write_csr_set_ns_cert_type(&req, opt.ns_cert_type);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
mbedtls_printf(" failed\n ! mbedtls_x509write_csr_set_ns_cert_type returned %d", ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the SubjectAltName in the CSR */
|
||||||
|
if (opt.san_list != NULL) {
|
||||||
|
ret = mbedtls_x509write_csr_set_subject_alternative_name(&req, opt.san_list);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
mbedtls_printf(
|
||||||
|
" failed\n ! mbedtls_x509write_csr_set_subject_alternative_name returned %d",
|
||||||
|
ret);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -363,6 +442,14 @@ exit:
|
|||||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||||
mbedtls_entropy_free(&entropy);
|
mbedtls_entropy_free(&entropy);
|
||||||
|
|
||||||
|
cur = opt.san_list;
|
||||||
|
while (cur != NULL) {
|
||||||
|
prev = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
mbedtls_free(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mbedtls_exit(exit_code);
|
mbedtls_exit(exit_code);
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
|
#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user