Merge pull request #6866 from mprse/extract-key-ids
Extracting SubjectKeyId and AuthorityKeyId in case of x509 V3 extensions v.2
This commit is contained in:
commit
97edeb4fb8
9 changed files with 355 additions and 43 deletions
|
@ -318,6 +318,18 @@ static const oid_x509_ext_t oid_x509_ext[] =
|
|||
"Certificate Policies"),
|
||||
MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
|
||||
},
|
||||
{
|
||||
OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
|
||||
"id-ce-subjectKeyIdentifier",
|
||||
"Subject Key Identifier"),
|
||||
MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
|
||||
},
|
||||
{
|
||||
OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
|
||||
"id-ce-authorityKeyIdentifier",
|
||||
"Authority Key Identifier"),
|
||||
MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
|
||||
},
|
||||
{
|
||||
NULL_OID_DESCRIPTOR,
|
||||
0,
|
||||
|
|
|
@ -1201,53 +1201,19 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SubjectAltName ::= GeneralNames
|
||||
/* Check mbedtls_x509_get_subject_alt_name for detailed description.
|
||||
*
|
||||
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
|
||||
*
|
||||
* GeneralName ::= CHOICE {
|
||||
* otherName [0] OtherName,
|
||||
* rfc822Name [1] IA5String,
|
||||
* dNSName [2] IA5String,
|
||||
* x400Address [3] ORAddress,
|
||||
* directoryName [4] Name,
|
||||
* ediPartyName [5] EDIPartyName,
|
||||
* uniformResourceIdentifier [6] IA5String,
|
||||
* iPAddress [7] OCTET STRING,
|
||||
* registeredID [8] OBJECT IDENTIFIER }
|
||||
*
|
||||
* OtherName ::= SEQUENCE {
|
||||
* type-id OBJECT IDENTIFIER,
|
||||
* value [0] EXPLICIT ANY DEFINED BY type-id }
|
||||
*
|
||||
* EDIPartyName ::= SEQUENCE {
|
||||
* nameAssigner [0] DirectoryString OPTIONAL,
|
||||
* partyName [1] DirectoryString }
|
||||
*
|
||||
* We list all types, but use the following GeneralName types from RFC 5280:
|
||||
* "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
|
||||
* of type "otherName", as defined in RFC 4108.
|
||||
* In some cases while parsing subject alternative names the sequence tag is optional
|
||||
* (e.g. CertSerialNumber). This function is designed to handle such case.
|
||||
*/
|
||||
int mbedtls_x509_get_subject_alt_name(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_x509_sequence *subject_alt_name)
|
||||
int mbedtls_x509_get_subject_alt_name_ext(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;
|
||||
size_t tag_len;
|
||||
mbedtls_asn1_sequence *cur = subject_alt_name;
|
||||
|
||||
/* Get main sequence tag */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
|
||||
if (*p + len != end) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
while (*p < end) {
|
||||
mbedtls_x509_subject_alternative_name dummy_san_buf;
|
||||
mbedtls_x509_buf tmp_san_buf;
|
||||
|
@ -1315,6 +1281,55 @@ int mbedtls_x509_get_subject_alt_name(unsigned char **p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SubjectAltName ::= GeneralNames
|
||||
*
|
||||
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
|
||||
*
|
||||
* GeneralName ::= CHOICE {
|
||||
* otherName [0] OtherName,
|
||||
* rfc822Name [1] IA5String,
|
||||
* dNSName [2] IA5String,
|
||||
* x400Address [3] ORAddress,
|
||||
* directoryName [4] Name,
|
||||
* ediPartyName [5] EDIPartyName,
|
||||
* uniformResourceIdentifier [6] IA5String,
|
||||
* iPAddress [7] OCTET STRING,
|
||||
* registeredID [8] OBJECT IDENTIFIER }
|
||||
*
|
||||
* OtherName ::= SEQUENCE {
|
||||
* type-id OBJECT IDENTIFIER,
|
||||
* value [0] EXPLICIT ANY DEFINED BY type-id }
|
||||
*
|
||||
* EDIPartyName ::= SEQUENCE {
|
||||
* nameAssigner [0] DirectoryString OPTIONAL,
|
||||
* partyName [1] DirectoryString }
|
||||
*
|
||||
* We list all types, but use the following GeneralName types from RFC 5280:
|
||||
* "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
|
||||
* of type "otherName", as defined in RFC 4108.
|
||||
*/
|
||||
int mbedtls_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;
|
||||
|
||||
/* Get main sequence tag */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
|
||||
if (*p + len != end) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);
|
||||
}
|
||||
|
||||
int mbedtls_x509_get_ns_cert_type(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
unsigned char *ns_cert_type)
|
||||
|
|
|
@ -591,6 +591,114 @@ static int x509_get_ext_key_usage(unsigned char **p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SubjectKeyIdentifier ::= KeyIdentifier
|
||||
*
|
||||
* KeyIdentifier ::= OCTET STRING
|
||||
*/
|
||||
static int x509_get_subject_key_id(unsigned char **p,
|
||||
const unsigned char *end,
|
||||
mbedtls_x509_buf *subject_key_id)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len = 0u;
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_OCTET_STRING)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
|
||||
subject_key_id->len = len;
|
||||
subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING;
|
||||
subject_key_id->p = *p;
|
||||
*p += len;
|
||||
|
||||
if (*p != end) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AuthorityKeyIdentifier ::= SEQUENCE {
|
||||
* keyIdentifier [0] KeyIdentifier OPTIONAL,
|
||||
* authorityCertIssuer [1] GeneralNames OPTIONAL,
|
||||
* authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
|
||||
*
|
||||
* KeyIdentifier ::= OCTET STRING
|
||||
*/
|
||||
static int x509_get_authority_key_id(unsigned char **p,
|
||||
unsigned char *end,
|
||||
mbedtls_x509_authority *authority_key_id)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len = 0u;
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
|
||||
if (*p + len != end) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONTEXT_SPECIFIC);
|
||||
|
||||
/* KeyIdentifier is an OPTIONAL field */
|
||||
if (ret == 0) {
|
||||
authority_key_id->keyIdentifier.len = len;
|
||||
authority_key_id->keyIdentifier.p = *p;
|
||||
/* Setting tag of the keyIdentfier intentionally to 0x04.
|
||||
* Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL),
|
||||
* its tag with the content is the payload of on OCTET STRING primitive */
|
||||
authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING;
|
||||
|
||||
*p += len;
|
||||
} else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
|
||||
if (*p < end) {
|
||||
/* Getting authorityCertIssuer using the required specific class tag [1] */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
|
||||
1)) != 0) {
|
||||
/* authorityCertIssuer and authorityCertSerialNumber MUST both
|
||||
be present or both be absent. At this point we expect to have both. */
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
/* "end" also includes the CertSerialNumber field so "len" shall be used */
|
||||
ret = mbedtls_x509_get_subject_alt_name_ext(p,
|
||||
(*p+len),
|
||||
&authority_key_id->authorityCertIssuer);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Getting authorityCertSerialNumber using the required specific class tag [2] */
|
||||
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
|
||||
MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
|
||||
}
|
||||
authority_key_id->authorityCertSerialNumber.len = len;
|
||||
authority_key_id->authorityCertSerialNumber.p = *p;
|
||||
authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER;
|
||||
*p += len;
|
||||
}
|
||||
|
||||
if (*p != end) {
|
||||
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
|
||||
*
|
||||
|
@ -889,8 +997,25 @@ static int x509_get_crt_ext(unsigned char **p,
|
|||
}
|
||||
break;
|
||||
|
||||
case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:
|
||||
/* Parse subject key identifier */
|
||||
if ((ret = x509_get_subject_key_id(p, end_ext_data,
|
||||
&crt->subject_key_id)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:
|
||||
/* Parse authority key identifier */
|
||||
if ((ret = x509_get_authority_key_id(p, end_ext_octet,
|
||||
&crt->authority_key_id)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
|
||||
/* Parse subject alt name */
|
||||
/* Parse subject alt name
|
||||
* SubjectAltName ::= GeneralNames
|
||||
*/
|
||||
if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet,
|
||||
&crt->subject_alt_names)) != 0) {
|
||||
return ret;
|
||||
|
@ -1550,6 +1675,27 @@ cleanup:
|
|||
#endif /* MBEDTLS_FS_IO */
|
||||
|
||||
#if !defined(MBEDTLS_X509_REMOVE_INFO)
|
||||
#define PRINT_ITEM(i) \
|
||||
do { \
|
||||
ret = mbedtls_snprintf(p, n, "%s" i, sep); \
|
||||
MBEDTLS_X509_SAFE_SNPRINTF; \
|
||||
sep = ", "; \
|
||||
} while (0)
|
||||
|
||||
#define CERT_TYPE(type, name) \
|
||||
do { \
|
||||
if (ns_cert_type & (type)) { \
|
||||
PRINT_ITEM(name); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define KEY_USAGE(code, name) \
|
||||
do { \
|
||||
if (key_usage & (code)) { \
|
||||
PRINT_ITEM(name); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int x509_info_ext_key_usage(char **buf, size_t *size,
|
||||
const mbedtls_x509_sequence *extended_key_usage)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue