Parsing v3 extensions from a CSR
A parsed CSR struct (`mbedtls_x509_csr`) now includes some of the X.509v3 extensions included in the CSR -- the key usage, Netscape cert-type, and Subject Alternative Names. Author: Jens Alfke <jens@couchbase.com> Signed-off-by: Przemek Stekiel <przemyslaw.stekiel@mobica.com>
This commit is contained in:
parent
449bd8303e
commit
2d9e359275
4 changed files with 174 additions and 9 deletions
|
@ -370,6 +370,15 @@ int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
|
|||
int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
|
||||
const char *oid, size_t oid_len,
|
||||
unsigned char *sig, size_t size);
|
||||
int x509_get_ns_cert_type(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned char *ns_cert_type);
|
||||
int x509_get_key_usage(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned int *key_usage);
|
||||
int x509_get_subject_alt_name(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_x509_sequence *subject_alt_name);
|
||||
|
||||
#define MBEDTLS_X509_SAFE_SNPRINTF \
|
||||
do { \
|
||||
|
|
|
@ -58,6 +58,10 @@ typedef struct mbedtls_x509_csr {
|
|||
|
||||
mbedtls_pk_context pk; /**< Container for the public key context. */
|
||||
|
||||
unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */
|
||||
unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
|
||||
mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
|
||||
|
||||
mbedtls_x509_buf sig_oid;
|
||||
mbedtls_x509_buf MBEDTLS_PRIVATE(sig);
|
||||
mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */
|
||||
|
|
|
@ -562,9 +562,9 @@ static int x509_get_basic_constraints(unsigned char **p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int x509_get_ns_cert_type(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned char *ns_cert_type)
|
||||
int x509_get_ns_cert_type(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned char *ns_cert_type)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_x509_bitstring bs = { 0, 0, NULL };
|
||||
|
@ -583,9 +583,9 @@ static int x509_get_ns_cert_type(unsigned char **p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int x509_get_key_usage(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned int *key_usage)
|
||||
int x509_get_key_usage(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned int *key_usage)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t i;
|
||||
|
@ -660,9 +660,9 @@ static int x509_get_ext_key_usage(unsigned char **p,
|
|||
* NOTE: we list all types, but only use dNSName and otherName
|
||||
* of type HwModuleName, as defined in RFC 4108, at this point.
|
||||
*/
|
||||
static int x509_get_subject_alt_name(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_x509_sequence *subject_alt_name)
|
||||
int x509_get_subject_alt_name(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_x509_sequence *subject_alt_name)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len, tag_len;
|
||||
|
|
|
@ -69,6 +69,153 @@ static int x509_csr_get_version(unsigned char **p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse CSR extension requests in DER format
|
||||
*/
|
||||
static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
|
||||
unsigned char **p, const unsigned char *end)
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
unsigned char *end_ext_data;
|
||||
|
||||
while (*p < end) {
|
||||
mbedtls_x509_buf extn_oid = { 0, 0, NULL };
|
||||
int ext_type = 0;
|
||||
|
||||
/* Read sequence tag */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
|
||||
end_ext_data = *p + len;
|
||||
|
||||
/* Get extension ID */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
|
||||
MBEDTLS_ASN1_OID)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
|
||||
extn_oid.tag = MBEDTLS_ASN1_OID;
|
||||
extn_oid.p = *p;
|
||||
*p += extn_oid.len;
|
||||
|
||||
/* Data should be octet string type */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
|
||||
MBEDTLS_ASN1_OCTET_STRING)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
if (*p + len != end_ext_data) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
if (mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type) == 0) {
|
||||
switch (ext_type) {
|
||||
case MBEDTLS_X509_EXT_KEY_USAGE:
|
||||
/* Parse key usage */
|
||||
if ((ret = x509_get_key_usage(p, end_ext_data,
|
||||
&csr->key_usage)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
|
||||
/* Parse subject alt name */
|
||||
if ((ret = x509_get_subject_alt_name(p, end_ext_data,
|
||||
&csr->subject_alt_names)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBEDTLS_X509_EXT_NS_CERT_TYPE:
|
||||
/* Parse netscape certificate type */
|
||||
if ((ret = x509_get_ns_cert_type(p, end_ext_data,
|
||||
&csr->ns_cert_type)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*p = end_ext_data;
|
||||
}
|
||||
|
||||
if (*p != end) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse CSR attributes in DER format
|
||||
*/
|
||||
static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
|
||||
const unsigned char *start, const unsigned char *end)
|
||||
{
|
||||
int ret;
|
||||
size_t len;
|
||||
unsigned char *end_attr_data;
|
||||
unsigned char **p = (unsigned char **) &start;
|
||||
|
||||
while (*p < end) {
|
||||
mbedtls_x509_buf attr_oid = { 0, 0, NULL };
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
end_attr_data = *p + len;
|
||||
|
||||
/* Get attribute ID */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
|
||||
MBEDTLS_ASN1_OID)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
|
||||
attr_oid.tag = MBEDTLS_ASN1_OID;
|
||||
attr_oid.p = *p;
|
||||
*p += attr_oid.len;
|
||||
|
||||
/* Check that this is an extension-request attribute */
|
||||
if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
|
||||
0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
|
||||
if ((ret = x509_csr_parse_extensions(csr, p, *p + len)) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret;
|
||||
}
|
||||
|
||||
if (*p != end_attr_data) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
*p = end_attr_data;
|
||||
}
|
||||
|
||||
if (*p != end) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a CSR in DER format
|
||||
*/
|
||||
|
@ -197,6 +344,11 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
|
|||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
|
||||
}
|
||||
|
||||
if ((ret = x509_csr_parse_attributes(csr, p, p + len)) != 0) {
|
||||
mbedtls_x509_csr_free(csr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
p += len;
|
||||
|
||||
end = csr->raw.p + csr->raw.len;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue