From 555fbf875806a12eaf702a99431627977c59c08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 4 Feb 2015 17:11:55 +0000 Subject: [PATCH] Support composite RDNs in X.509 certs parsing --- include/polarssl/asn1.h | 1 + library/x509.c | 44 ++++++++++++++++++++------ library/x509_crt.c | 4 +++ tests/suites/test_suite_x509parse.data | 6 +++- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index 6a8716012..0a657e1c2 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -155,6 +155,7 @@ typedef struct _asn1_named_data asn1_buf oid; /**< The object identifier. */ asn1_buf val; /**< The named value. */ struct _asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ } asn1_named_data; diff --git a/library/x509.c b/library/x509.c index b34cf3255..a3cb66943 100644 --- a/library/x509.c +++ b/library/x509.c @@ -393,6 +393,11 @@ static int x509_get_attr_type_value( unsigned char **p, } /* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * @@ -404,9 +409,11 @@ static int x509_get_attr_type_value( unsigned char **p, * * AttributeValue ::= ANY DEFINED BY AttributeType * - * We restrict RelativeDistinguishedName to be a set of 1 element. This is - * the most common case, and our x509_name structure currently can't handle - * more than that. + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg x509_dn_gets(). */ int x509_get_name( unsigned char **p, const unsigned char *end, x509_name *cur ) @@ -419,7 +426,7 @@ int x509_get_name( unsigned char **p, const unsigned char *end, while( 1 ) { /* - * parse first SET, restricted to 1 element + * parse SET */ if( ( ret = asn1_get_tag( p, end, &set_len, ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) @@ -427,11 +434,26 @@ int x509_get_name( unsigned char **p, const unsigned char *end, end_set = *p + set_len; - if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) - return( ret ); + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); - if( *p != end_set ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + if( *p == end_set ) + break; + + /* Mark this item as being only one in a set */ + cur->next_merged = 1; + + cur->next = (x509_name *) polarssl_malloc( sizeof( x509_name ) ); + + if( cur->next == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memset( cur->next, 0, sizeof( x509_name ) ); + + cur = cur->next; + } /* * continue until end of SEQUENCE is reached @@ -690,7 +712,7 @@ int x509_dn_gets( char *buf, size_t size, const x509_name *dn ) { int ret; size_t i, n; - unsigned char c; + unsigned char c, merge = 0; const x509_name *name; const char *short_name = NULL; char s[X509_MAX_DN_NAME_SIZE], *p; @@ -711,7 +733,7 @@ int x509_dn_gets( char *buf, size_t size, const x509_name *dn ) if( name != dn ) { - ret = snprintf( p, n, ", " ); + ret = snprintf( p, n, merge ? " + " : ", " ); SAFE_SNPRINTF(); } @@ -736,6 +758,8 @@ int x509_dn_gets( char *buf, size_t size, const x509_name *dn ) s[i] = '\0'; ret = snprintf( p, n, "%s", s ); SAFE_SNPRINTF(); + + merge = name->next_merged; name = name->next; } diff --git a/library/x509_crt.c b/library/x509_crt.c index e114c0f32..d1d7d7396 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1652,6 +1652,10 @@ static int x509_name_cmp( const x509_name *a, const x509_name *b ) if( x509_string_cmp( &a->val, &b->val ) != 0 ) return( -1 ); + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + a = a->next; b = b->next; } diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 072a667d3..a65ac2bad 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -778,7 +778,7 @@ X509 Certificate ASN1 (TBSCertificate, issuer, no string data) x509parse_crt:"30253023a0030201028204deadbeef300d06092a864886f70d0101020500300731053003060013":"":POLARSSL_ERR_X509_INVALID_NAME + POLARSSL_ERR_ASN1_OUT_OF_DATA X509 Certificate ASN1 (TBSCertificate, issuer, no full following string) -x509parse_crt:"302b3029a0030201028204deadbeef300d06092a864886f70d0101020500300d310b3009060013045465737400":"":POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +x509parse_crt:"302b3029a0030201028204deadbeef300d06092a864886f70d0101020500300d310b3009060013045465737400":"":POLARSSL_ERR_X509_INVALID_NAME+POLARSSL_ERR_ASN1_UNEXPECTED_TAG X509 Certificate ASN1 (TBSCertificate, valid issuer, no validity) x509parse_crt:"302a3028a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374":"":POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA @@ -961,6 +961,10 @@ X509 Certificate ASN1 (Name with unknown X520 part) depends_on:POLARSSL_RSA_C x509parse_crt:"308199308183a0030201008204deadbeef300d06092a864886f70d0101020500300f310d300b06035504de130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name \: ?\?=Test\nsubject name \: ?\?=Test\nissued on \: 2009-01-01 00\:00\:00\nexpires on \: 2009-12-31 23\:59\:59\nsigned using \: RSA with MD2\nRSA key size \: 128 bits\n":0 +X509 Certificate ASN1 (Name with composite RDN) +depends_on:POLARSSL_RSA_C +x509parse_crt:"3082029f30820208a00302010202044c20e3bd300d06092a864886f70d01010505003056310b3009060355040613025553310b300906035504080c0243413121301f060355040a0c18496e7465726e6574205769646769747320507479204c74643117301506035504030c0e4672616e6b656e63657274204341301e170d3133303830323135313433375a170d3135303831373035353433315a3081d1310b3009060355040613025553311330110603550408130a57617368696e67746f6e31133011060b2b0601040182373c0201031302555331193017060b2b0601040182373c020102130844656c6177617265311a3018060355040a1311417574686f72697a652e4e6574204c4c43311d301b060355040f131450726976617465204f7267616e697a6174696f6e312a300e06035504051307343336393139313018060355040313117777772e617574686f72697a652e6e6574311630140603550407130d53616e204672616e636973636f30819f300d06092a864886f70d010101050003818d0030818902818100d885c62e209b6ac005c64f0bcfdaac1f2b67a18802f75b08851ff933deed888b7b68a62fcabdb21d4a8914becfeaaa1b7e08a09ffaf9916563586dc95e2877262b0b5f5ec27eb4d754aa6facd1d39d25b38a2372891bacdd3e919f791ed25704e8920e380e5623a38e6a23935978a3aec7a8e761e211d42effa2713e44e7de0b0203010001300d06092a864886f70d010105050003818100092f7424d3f6da4b8553829d958ed1980b9270b42c0d3d5833509a28c66bb207df9f3c51d122065e00b87c08c2730d2745fe1c279d16fae4d53b4bf5bdfa3631fceeb2e772b6b08a3eca5a2e2c687aefd23b4b73bf77ac6099711342cf070b35c6f61333a7cbf613d8dd4bd73e9df34bcd4284b0b4df57c36c450613f11e5dac":"cert. version \: 3\nserial number \: 4C\:20\:E3\:BD\nissuer name \: C=US, ST=CA, O=Internet Widgits Pty Ltd, CN=Frankencert CA\nsubject name \: C=US, ST=Washington, ??=US, ??=Delaware, O=Authorize.Net LLC, ??=Private Organization, serialNumber=4369191 + CN=www.authorize.net, L=San Francisco\nissued on \: 2013-08-02 15\:14\:37\nexpires on \: 2015-08-17 05\:54\:31\nsigned using \: RSA with SHA1\nRSA key size \: 1024 bits\n":0 + X509 Certificate ASN1 (Name with PKCS9 email) depends_on:POLARSSL_RSA_C x509parse_crt:"30819f308189a0030201008204deadbeef300d06092a864886f70d010102050030153113301106092a864886f70d010901130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374302a300d06092A864886F70D010101050003190030160210ffffffffffffffffffffffffffffffff0202ffff300d06092a864886f70d0101020500030200ff":"cert. version \: 1\nserial number \: DE\:AD\:BE\:EF\nissuer name \: emailAddress=Test\nsubject name \: ?\?=Test\nissued on \: 2009-01-01 00\:00\:00\nexpires on \: 2009-12-31 23\:59\:59\nsigned using \: RSA with MD2\nRSA key size \: 128 bits\n":0