Suppport otherName of type hardware module name
Add support of parsing of subject alternative name, of type otherName.
Currently supports only hardware module name, as defined in rfc 4108.
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 97a06d5..f9cbed0 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -618,7 +618,8 @@
* nameAssigner [0] DirectoryString OPTIONAL,
* partyName [1] DirectoryString }
*
- * NOTE: we only parse and use dNSName at this point.
+ * NOTE: we only parse and use dNSName at this point,
+ * and otherName of type HwModuleName, as defined in RFC 4108.
*/
static int x509_get_subject_alt_name( unsigned char **p,
const unsigned char *end,
@@ -657,13 +658,6 @@
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
}
- /* Skip everything but DNS name */
- if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
- {
- *p += tag_len;
- continue;
- }
-
/* Allocate and assign next pointer */
if( cur->buf.p != NULL )
{
@@ -1435,32 +1429,195 @@
}
#endif /* MBEDTLS_FS_IO */
+/*
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * HardwareModuleName ::= SEQUENCE {
+ * hwType OBJECT IDENTIFIER,
+ * hwSerialNum OCTET STRING }
+ *
+ * NOTE: we currently only parse and use otherName of type HwModuleName,
+ * as defined in RFC 4108.
+ */
+static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
+ mbedtls_x509_san_other_name *other_name )
+{
+ int ret;
+ size_t len;
+ unsigned char *p = subject_alt_name->p;
+ const unsigned char *end = p + subject_alt_name->len;
+ mbedtls_x509_buf cur_oid;
+
+ if( ( subject_alt_name->tag &
+ ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) !=
+ ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) )
+ {
+ /*
+ * The given subject alternative name is not of type "othername".
+ */
+ return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+ }
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_OID ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ cur_oid.tag = MBEDTLS_ASN1_OID;
+ cur_oid.p = p;
+ cur_oid.len = len;
+
+ /*
+ * Only HwModuleName is currently supported.
+ */
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 )
+ {
+ return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+ }
+
+ if( p + len >= end )
+ {
+ mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+ p += len;
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 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 = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
+ other_name->value.hardware_module_name.oid.p = p;
+ other_name->value.hardware_module_name.oid.len = len;
+
+ if( p + len >= end )
+ {
+ mbedtls_platform_zeroize( other_name, sizeof( other_name ) );
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+ p += len;
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
+ other_name->value.hardware_module_name.val.p = p;
+ other_name->value.hardware_module_name.val.len = len;
+ other_name->value.hardware_module_name.next = NULL;
+ other_name->value.hardware_module_name.next_merged = 0;
+ p += len;
+ if( p != end )
+ {
+ mbedtls_platform_zeroize( other_name,
+ sizeof( other_name ) );
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+ return( 0 );
+}
+
static int x509_info_subject_alt_name( char **buf, size_t *size,
- const mbedtls_x509_sequence *subject_alt_name )
+ const mbedtls_x509_sequence *subject_alt_name,
+ const char *prefix )
{
size_t i;
+ int ret;
size_t n = *size;
char *p = *buf;
const mbedtls_x509_sequence *cur = subject_alt_name;
- const char *sep = "";
- size_t sep_len = 0;
while( cur != NULL )
{
- if( cur->buf.len + sep_len >= n )
+ switch( cur->buf.tag &
+ ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) )
{
- *p = '\0';
- return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ /*
+ * otherName
+ */
+ case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
+ {
+ mbedtls_x509_san_other_name other_name;
+
+ ret = x509_get_other_name( &cur->buf, &other_name );
+ if( ret != 0 )
+ {
+ /*
+ * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
+ * then the "otherName" is of an unsupported type. Ignore.
+ */
+ if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+ ret = 0;
+ return( ret );
+ }
+
+ ret = mbedtls_snprintf( p, n, "\n%s otherName :", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
+ &other_name.value.hardware_module_name.oid ) != 0 )
+ {
+ ret = mbedtls_snprintf( p, n, "\n%s hardware module name :", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ ret = mbedtls_snprintf( p, n, "\n%s hardware type : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ ret = mbedtls_oid_get_numeric_string( p, n, &other_name.value.hardware_module_name.oid );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ if( other_name.value.hardware_module_name.val.len >= n )
+ {
+ *p = '\0';
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ }
+
+ for( i = 0; i < other_name.value.hardware_module_name.val.len; i++ )
+ {
+ *p++ = other_name.value.hardware_module_name.val.p[i];
+ }
+ n -= other_name.value.hardware_module_name.val.len;
+
+ }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+ }
+ break;
+
+ /*
+ * dNSName
+ */
+ case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+ {
+
+ ret = mbedtls_snprintf( p, n, "\n%s dNSName : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ if( cur->buf.len >= n )
+ {
+ *p = '\0';
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ }
+ n -= cur->buf.len;
+ for( i = 0; i < cur->buf.len; i++ )
+ *p++ = cur->buf.p[i];
+ }
+ break;
+
+ /*
+ * Type not supported, skip item.
+ */
+ default:
+ break;
}
- n -= cur->buf.len + sep_len;
- for( i = 0; i < sep_len; i++ )
- *p++ = sep[i];
- for( i = 0; i < cur->buf.len; i++ )
- *p++ = cur->buf.p[i];
-
- sep = ", ";
- sep_len = 2;
cur = cur->next;
}
@@ -1473,6 +1630,105 @@
return( 0 );
}
+int mbedtls_x509_parse_subject_alternative_name( const mbedtls_x509_crt *crt,
+ mbedtls_x509_subject_alternative_name **san )
+{
+ int ret;
+ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
+ mbedtls_x509_subject_alternative_name *cur_san = *san, *prev_san = NULL;
+
+ if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
+ {
+ if( cur_san != NULL )
+ {
+ return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+ }
+
+ while( cur != NULL )
+ {
+ switch( cur->buf.tag &
+ ( MBEDTLS_ASN1_TAG_CLASS_MASK |
+ MBEDTLS_ASN1_TAG_VALUE_MASK ) )
+ {
+ /*
+ * otherName
+ */
+ case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
+ {
+ mbedtls_x509_san_other_name other_name;
+
+ ret = x509_get_other_name( &cur->buf, &other_name );
+ if( ret != 0 )
+ {
+ /*
+ * In case MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned,
+ * then the "otherName" is of an unsupported type. Ignore.
+ */
+ if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+ ret = 0;
+ cur = cur->next;
+ continue;
+ }
+
+ cur_san = mbedtls_calloc( 1, sizeof( mbedtls_x509_subject_alternative_name ) );
+ if( cur_san == NULL )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+ if( prev_san != NULL )
+ prev_san->next = cur_san;
+
+ cur_san->type = MBEDTLS_X509_SAN_OTHER_NAME;
+ memcpy( &cur_san->san.other_name,
+ &other_name, sizeof( other_name ) );
+
+ }
+ break;
+
+ /*
+ * dNSName
+ */
+ case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+ {
+ cur_san = mbedtls_calloc( 1, sizeof( mbedtls_x509_subject_alternative_name ) );
+ if( cur_san == NULL )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+ if( prev_san != NULL )
+ prev_san->next = cur_san;
+
+ memset( cur_san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+ cur_san->type = MBEDTLS_X509_SAN_DNS_NAME;
+
+ memcpy( &cur_san->san.unstructured_name,
+ &cur->buf, sizeof( cur->buf ) );
+
+ }
+ break;
+
+ /*
+ * Type not supported, skip item.
+ */
+ default:
+ break;
+ }
+
+ if( *san == NULL )
+ *san = cur_san;
+
+ if( cur_san != NULL )
+ {
+ prev_san = cur_san;
+ cur_san = cur_san->next;
+ }
+
+ cur = cur->next;
+ }/* while( cur != NULL ) */
+ }/* crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME */
+ return( 0 );
+}
+
#define PRINT_ITEM(i) \
{ \
ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
@@ -1659,11 +1915,12 @@
if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
{
- ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
+ ret = mbedtls_snprintf( p, n, "\n%ssubject alt name :", prefix );
MBEDTLS_X509_SAFE_SNPRINTF;
if( ( ret = x509_info_subject_alt_name( &p, &n,
- &crt->subject_alt_names ) ) != 0 )
+ &crt->subject_alt_names,
+ prefix) ) != 0 )
return( ret );
}