From f8d018a2747661d9b1d5533b9925e8fb745397c9 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sat, 29 Jun 2013 12:16:17 +0200 Subject: [PATCH] Made asn1_get_alg() and asn1_get_alg_null() as generic functions A generic function for retrieving the AlgorithmIdentifier structure with its parameters and adapted X509, PKCS#5 and PKCS#12 to use them. --- include/polarssl/asn1.h | 29 ++++++++++ library/asn1parse.c | 61 ++++++++++++++++++++- library/pkcs12.c | 22 +++----- library/pkcs5.c | 74 ++++++++------------------ library/x509parse.c | 54 +++---------------- tests/suites/test_suite_x509parse.data | 4 +- 6 files changed, 127 insertions(+), 117 deletions(-) diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index 61ea908ab9..ae498d0cd7 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -244,6 +244,35 @@ int asn1_get_mpi( unsigned char **p, mpi *X ); #endif +/** + * Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_alg( unsigned char **p, + const unsigned char *end, + asn1_buf *alg, asn1_buf *params ); + +/** + * Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no params. + * Updates the pointer to immediately behind the full AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + asn1_buf *alg ); + #ifdef __cplusplus } #endif diff --git a/library/asn1parse.c b/library/asn1parse.c index 2584774a77..b8823c1901 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -1,7 +1,7 @@ /* * Generic ASN.1 parsing * - * Copyright (C) 2006-2011, Brainspark B.V. + * Copyright (C) 2006-2013, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker @@ -257,4 +257,63 @@ int asn1_get_sequence_of( unsigned char **p, return( 0 ); } +int asn1_get_alg( unsigned char **p, + const unsigned char *end, + asn1_buf *alg, asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = asn1_get_tag( p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end = *p + len; + alg->tag = **p; + + if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + memset( params, 0, sizeof(asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + asn1_buf *alg ) +{ + int ret; + asn1_buf params; + + memset( ¶ms, 0, sizeof(asn1_buf) ); + + if( ( ret = asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( POLARSSL_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + #endif diff --git a/library/pkcs12.c b/library/pkcs12.c index 2ee9c5ea2c..6251293176 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -45,12 +45,12 @@ #include "polarssl/des.h" #endif -static int pkcs12_parse_pbe_params( unsigned char **p, - const unsigned char *end, +static int pkcs12_parse_pbe_params( asn1_buf *params, asn1_buf *salt, int *iterations ) { int ret; - size_t len = 0; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; /* * pkcs-12PbeParams ::= SEQUENCE { @@ -59,13 +59,9 @@ static int pkcs12_parse_pbe_params( unsigned char **p, * } * */ - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); - } - - end = *p + len; + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); @@ -91,16 +87,12 @@ static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type, int ret, iterations; asn1_buf salt; size_t i; - unsigned char *p, *end; unsigned char unipwd[258]; memset(&salt, 0, sizeof(asn1_buf)); memset(&unipwd, 0, sizeof(unipwd)); - p = pbe_params->p; - end = p + pbe_params->len; - - if( ( ret = pkcs12_parse_pbe_params( &p, end, &salt, &iterations ) ) != 0 ) + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, &iterations ) ) != 0 ) return( ret ); for(i = 0; i < pwdlen; i++) diff --git a/library/pkcs5.c b/library/pkcs5.c index c41927b637..a36352916c 100644 --- a/library/pkcs5.c +++ b/library/pkcs5.c @@ -42,15 +42,18 @@ #include "polarssl/cipher.h" #include "polarssl/oid.h" -static int pkcs5_parse_pbkdf2_params( unsigned char **p, - const unsigned char *end, +static int pkcs5_parse_pbkdf2_params( asn1_buf *params, asn1_buf *salt, int *iterations, int *keylen, md_type_t *md_type ) { int ret; - size_t len = 0; asn1_buf prf_alg_oid; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); /* * PBKDF2-params ::= SEQUENCE { * salt OCTET STRING, @@ -60,14 +63,6 @@ static int pkcs5_parse_pbkdf2_params( unsigned char **p, * } * */ - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - end = *p + len; - if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); @@ -89,7 +84,7 @@ static int pkcs5_parse_pbkdf2_params( unsigned char **p, if( *p == end ) return( 0 ); - if( ( ret = asn1_get_tag( p, end, &prf_alg_oid.len, ASN1_OID ) ) != 0 ) + if( ( ret = asn1_get_alg_null( p, end, &prf_alg_oid ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) ) @@ -110,11 +105,12 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, unsigned char *output ) { int ret, iterations = 0, keylen = 0; - unsigned char *p, *end, *end2; - asn1_buf kdf_alg_oid, enc_scheme_oid, salt; + unsigned char *p, *end; + asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + asn1_buf salt; md_type_t md_type = POLARSSL_MD_SHA1; unsigned char key[32], iv[32]; - size_t len = 0, olen = 0; + size_t olen = 0; const md_info_t *md_info; const cipher_info_t *cipher_info; md_context_t md_ctx; @@ -130,32 +126,19 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} * } */ - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { + if( pbe_params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) + return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { - return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - end2 = p + len; - - if( ( ret = asn1_get_tag( &p, end2, &kdf_alg_oid.len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - - kdf_alg_oid.p = p; - p += kdf_alg_oid.len; // Only PBKDF2 supported at the moment // if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) ) return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); - if( ( ret = pkcs5_parse_pbkdf2_params( &p, end2, + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, &salt, &iterations, &keylen, &md_type ) ) != 0 ) { @@ -166,19 +149,8 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, if( md_info == NULL ) return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { + if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid, &enc_scheme_params ) ) != 0 ) return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - end2 = p + len; - - if( ( ret = asn1_get_tag( &p, end2, &enc_scheme_oid.len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - - enc_scheme_oid.p = p; - p += enc_scheme_oid.len; if ( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); @@ -189,13 +161,13 @@ int pkcs5_pbes2( asn1_buf *pbe_params, int mode, keylen = cipher_info->key_length / 8; - if( ( ret = asn1_get_tag( &p, end2, &len, ASN1_OCTET_STRING ) ) != 0 ) - return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); - - if( len != cipher_info->iv_size ) + if( enc_scheme_params.tag != ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { return( POLARSSL_ERR_PKCS5_INVALID_FORMAT ); + } - memcpy( iv, p, len ); + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) return( ret ); diff --git a/library/x509parse.c b/library/x509parse.c index 0335db4b78..c49c48adb5 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -182,34 +182,10 @@ static int x509_get_alg( unsigned char **p, x509_buf *alg ) { int ret; - size_t len; - if( ( ret = asn1_get_tag( p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 ) return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - end = *p + len; - alg->tag = **p; - - if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - - alg->p = *p; - *p += alg->len; - - if( *p == end ) - return( 0 ); - - /* - * assume the algorithm parameters must be NULL - */ - if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + ret ); - - if( *p != end ) - return( POLARSSL_ERR_X509_CERT_INVALID_ALG + - POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); - return( 0 ); } @@ -451,8 +427,8 @@ static int x509_get_pubkey( unsigned char **p, unsigned char *end2; pk_type_t pk_alg = POLARSSL_PK_NONE; - if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 ) - return( ret ); + if( ( ret = asn1_get_alg_null( p, end, pk_alg_oid ) ) != 0 ) + return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + ret ); /* * only RSA public keys handled at this time @@ -2149,7 +2125,7 @@ static int x509parse_key_pkcs8_unencrypted_der( if( rsa->ver != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_VERSION + ret ); - if( ( ret = x509_get_alg( &p, end, &pk_alg_oid ) ) != 0 ) + if( ( ret = asn1_get_alg_null( &p, end, &pk_alg_oid ) ) != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); /* @@ -2190,7 +2166,7 @@ static int x509parse_key_pkcs8_encrypted_der( { int ret; size_t len; - unsigned char *p, *end, *end2; + unsigned char *p, *end; x509_buf pbe_alg_oid, pbe_params; unsigned char buf[2048]; #if defined(POLARSSL_PKCS12_C) @@ -2228,26 +2204,8 @@ static int x509parse_key_pkcs8_encrypted_der( end = p + len; - if( ( ret = asn1_get_tag( &p, end, &len, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) - { + if( ( ret = asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - } - - end2 = p + len; - - if( ( ret = asn1_get_tag( &p, end, &pbe_alg_oid.len, ASN1_OID ) ) != 0 ) - return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); - - pbe_alg_oid.p = p; - p += pbe_alg_oid.len; - - /* - * Store the algorithm parameters - */ - pbe_params.p = p; - pbe_params.len = end2 - p; - p += pbe_params.len; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT + ret ); diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 8622df11de..66a4fa4b31 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -412,7 +412,7 @@ X509 Certificate ASN1 (TBSCertificate, alg oid no data in sequence) x509parse_crt:"300f300da0030201048204deadbeef3000":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA X509 Certificate ASN1 (TBSCertificate, alg with params) -x509parse_crt:"30163014a0030201048204deadbeef30070604cafed00d01":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_UNEXPECTED_TAG +x509parse_crt:"30163014a0030201048204deadbeef30070604cafed00d01":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA X509 Certificate ASN1 (TBSCertificate, correct alg data, no params unknown version) x509parse_crt:"30153013a0030201048204deadbeef30060604cafed00d":"":POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION @@ -475,7 +475,7 @@ X509 Certificate ASN1 (TBSCertificate, valid subject, no pubkeyinfo) x509parse_crt:"30563054a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374":"":POLARSSL_ERR_X509_CERT_INVALID_FORMAT + POLARSSL_ERR_ASN1_OUT_OF_DATA X509 Certificate ASN1 (TBSCertificate, pubkey, no alg) -x509parse_crt:"30583056a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743000":"":POLARSSL_ERR_X509_CERT_INVALID_ALG + POLARSSL_ERR_ASN1_OUT_OF_DATA +x509parse_crt:"30583056a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743000":"":POLARSSL_ERR_X509_CERT_INVALID_PUBKEY + POLARSSL_ERR_ASN1_OUT_OF_DATA X509 Certificate ASN1 (TBSCertificate, valid subject, unknown pk alg) x509parse_crt:"30673065a0030201028204deadbeef300d06092a864886f70d0101020500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a30080600130454657374300f300d06092A864886F70D0101000500":"":POLARSSL_ERR_X509_UNKNOWN_PK_ALG