asn1_named_data *asn1_store_named_data( asn1_named_data **head, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len ) { asn1_named_data *cur; if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) { // Add new entry if not present yet based on OID // if( ( cur = polarssl_malloc( sizeof(asn1_named_data) ) ) == NULL ) return( NULL ); memset( cur, 0, sizeof(asn1_named_data) ); cur->oid.len = oid_len; cur->oid.p = polarssl_malloc( oid_len ); if( cur->oid.p == NULL ) { polarssl_free( cur ); return( NULL ); } cur->val.len = val_len; cur->val.p = polarssl_malloc( val_len ); if( cur->val.p == NULL ) { polarssl_free( cur->oid.p ); polarssl_free( cur ); return( NULL ); } memcpy( cur->oid.p, oid, oid_len ); cur->next = *head; *head = cur; } else if( cur->val.len < val_len ) { // Enlarge existing value buffer if needed // polarssl_free( cur->val.p ); cur->val.p = NULL; cur->val.len = val_len; cur->val.p = polarssl_malloc( val_len ); if( cur->val.p == NULL ) { polarssl_free( cur->oid.p ); polarssl_free( cur ); return( NULL ); } } if( val != NULL ) memcpy( cur->val.p, val, val_len ); return( cur ); }
/* * Name ::= CHOICE { -- only one possibility for now -- * rdnSequence RDNSequence } * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * 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 ) { int ret; size_t set_len; const unsigned char *end_set; /* don't use recursion, we'd risk stack overflow if not optimized */ while( 1 ) { /* * parse SET */ if( ( ret = asn1_get_tag( p, end, &set_len, ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); end_set = *p + set_len; while( 1 ) { if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) return( ret ); if( *p == end_set ) break; /* Mark this item as being not the only one in a set */ cur->next_merged = 1; cur->next = 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 */ if( *p == end ) return( 0 ); cur->next = 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; } }
/* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ int x509_get_name( unsigned char **p, const unsigned char *end, x509_name *cur ) { int ret; size_t len; const unsigned char *end2; x509_name *use; if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); end2 = end; end = *p + len; use = cur; do { if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 ) return( ret ); if( *p != end ) { use->next = (x509_name *) polarssl_malloc( sizeof( x509_name ) ); if( use->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memset( use->next, 0, sizeof( x509_name ) ); use = use->next; } } while( *p != end ); /* * recurse until end of SEQUENCE is reached */ if( *p == end2 ) return( 0 ); 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 ) ); return( x509_get_name( p, end2, cur->next ) ); }
static void *eckey_alloc_wrap( void ) { void *ctx = polarssl_malloc( sizeof( ecp_keypair ) ); if( ctx != NULL ) ecp_keypair_init( ctx ); return( ctx ); }
static void *rsa_alloc_wrap( void ) { void *ctx = polarssl_malloc( sizeof( rsa_context ) ); if( ctx != NULL ) rsa_init( (rsa_context *) ctx, 0, 0 ); return ctx; }
static void *rsa_alt_alloc_wrap( void ) { void *ctx = polarssl_malloc( sizeof( rsa_alt_context ) ); if( ctx != NULL ) memset( ctx, 0, sizeof( rsa_alt_context ) ); return ctx; }
static void *ecdsa_alloc_wrap( void ) { void *ctx = polarssl_malloc( sizeof( ecdsa_context ) ); if( ctx != NULL ) ecdsa_init( (ecdsa_context *) ctx ); return( ctx ); }
static void *tts_alloc( void ) { void *ctx = polarssl_malloc( sizeof( tts_context ) ); if( ctx != NULL ) { memset( ctx, 0, sizeof( tts_context ) ); } return( ctx ); }
static void * aes_ctx_alloc( void ) { aes_context *aes = (aes_context *) polarssl_malloc( sizeof( aes_context ) ); if( aes == NULL ) return( NULL ); aes_init( aes ); return( aes ); }
static void * des_ctx_alloc( void ) { des_context *des = (des_context *) polarssl_malloc( sizeof( des_context ) ); if( des == NULL ) return( NULL ); des_init( des ); return( des ); }
static void * blowfish_ctx_alloc( void ) { blowfish_context *ctx; ctx = (blowfish_context *) polarssl_malloc( sizeof( blowfish_context ) ); if( ctx == NULL ) return( NULL ); blowfish_init( ctx ); return( ctx ); }
static void * camellia_ctx_alloc( void ) { camellia_context *ctx; ctx = (camellia_context *) polarssl_malloc( sizeof( camellia_context ) ); if( ctx == NULL ) return( NULL ); camellia_init( ctx ); return( ctx ); }
static void * arc4_ctx_alloc( void ) { arc4_context *ctx; ctx = (arc4_context *) polarssl_malloc( sizeof( arc4_context ) ); if( ctx == NULL ) return( NULL ); arc4_init( ctx ); return( ctx ); }
static void * ripemd160_ctx_alloc( void ) { ripemd160_context *ctx; ctx = (ripemd160_context *) polarssl_malloc( sizeof( ripemd160_context ) ); if( ctx == NULL ) return( NULL ); ripemd160_init( ctx ); return( ctx ); }
static void * sha512_ctx_alloc( void ) { sha512_context *ctx; ctx = (sha512_context *) polarssl_malloc( sizeof( sha512_context ) ); if( ctx == NULL ) return( NULL ); sha512_init( ctx ); return( ctx ); }
/* * Parses and splits an ASN.1 "SEQUENCE OF <tag>" */ int asn1_get_sequence_of( unsigned char **p, const unsigned char *end, asn1_sequence *cur, int tag) { int ret; size_t len; asn1_buf *buf; /* Get main sequence tag */ if( ( ret = asn1_get_tag( p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); if( *p + len != end ) return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); while( *p < end ) { buf = &(cur->buf); buf->tag = **p; if( ( ret = asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) return( ret ); buf->p = *p; *p += buf->len; /* Allocate and assign next pointer */ if (*p < end) { cur->next = (asn1_sequence *) polarssl_malloc( sizeof( asn1_sequence ) ); if( cur->next == NULL ) return( POLARSSL_ERR_ASN1_MALLOC_FAILED ); memset( cur->next, 0, sizeof( asn1_sequence ) ); cur = cur->next; } } /* Set final sequence entry's next pointer to NULL */ cur->next = NULL; if( *p != end ) return( POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); return( 0 ); }
int pkcs11_x509_cert_init( x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) { int ret = 1; unsigned char *cert_blob = NULL; size_t cert_blob_size = 0; if( cert == NULL ) { ret = 2; goto cleanup; } if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, &cert_blob_size ) != CKR_OK ) { ret = 3; goto cleanup; } cert_blob = polarssl_malloc( cert_blob_size ); if( NULL == cert_blob ) { ret = 4; goto cleanup; } if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, &cert_blob_size ) != CKR_OK ) { ret = 5; goto cleanup; } if( 0 != x509_crt_parse( cert, cert_blob, cert_blob_size ) ) { ret = 6; goto cleanup; } ret = 0; cleanup: if( NULL != cert_blob ) polarssl_free( cert_blob ); return( ret ); }
/* * Parse one X.509 certificate in DER format from a buffer and add them to a * chained list */ int x509_crt_parse_der( x509_crt *chain, const unsigned char *buf, size_t buflen ) { int ret; x509_crt *crt = chain, *prev = NULL; /* * Check for valid input */ if( crt == NULL || buf == NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); while( crt->version != 0 && crt->next != NULL ) { prev = crt; crt = crt->next; } /* * Add new certificate on the end of the chain if needed. */ if ( crt->version != 0 && crt->next == NULL) { crt->next = (x509_crt *) polarssl_malloc( sizeof( x509_crt ) ); if( crt->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); prev = crt; crt = crt->next; x509_crt_init( crt ); } if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) { if( prev ) prev->next = NULL; if( crt != chain ) polarssl_free( crt ); return( ret ); } return( 0 ); }
/* * Get signature algorithm from alg OID and optional parameters */ int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params, md_type_t *md_alg, pk_type_t *pk_alg, void **sig_opts ) { int ret; if( *sig_opts != NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret ); #if defined(POLARSSL_X509_RSASSA_PSS_SUPPORT) if( *pk_alg == POLARSSL_PK_RSASSA_PSS ) { pk_rsassa_pss_options *pss_opts; pss_opts = polarssl_malloc( sizeof( pk_rsassa_pss_options ) ); if( pss_opts == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); ret = x509_get_rsassa_pss_params( sig_params, md_alg, &pss_opts->mgf1_hash_id, &pss_opts->expected_salt_len ); if( ret != 0 ) { polarssl_free( pss_opts ); return( ret ); } *sig_opts = (void *) pss_opts; } else #endif /* POLARSSL_X509_RSASSA_PSS_SUPPORT */ { /* Make sure parameters are absent or NULL */ if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) || sig_params->len != 0 ) return( POLARSSL_ERR_X509_INVALID_ALG ); } return( 0 ); }
char *debug_fmt( const char *format, ... ) { va_list argp; #if defined(POLARSSL_THREADING_C) char *str = polarssl_malloc( DEBUG_BUF_SIZE ); if( str == NULL ) return( NULL ); #else static char str[DEBUG_BUF_SIZE]; #endif va_start( argp, format ); vsnprintf( str, DEBUG_BUF_SIZE - 1, format, argp ); va_end( argp ); str[DEBUG_BUF_SIZE - 1] = '\0'; return( str ); }
/* * Load all data from a file into a given buffer. */ static int load_file( const char *path, unsigned char **buf, size_t *n ) { FILE *f; long size; if( ( f = fopen( path, "rb" ) ) == NULL ) return( -1 ); fseek( f, 0, SEEK_END ); if( ( size = ftell( f ) ) == -1 ) { fclose( f ); return( -1 ); } fseek( f, 0, SEEK_SET ); *n = (size_t) size; if( *n + 1 == 0 || ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL ) { fclose( f ); return( -1 ); } if( fread( *buf, 1, *n, f ) != *n ) { fclose( f ); free( *buf ); *buf = NULL; return( -1 ); } fclose( f ); (*buf)[*n] = '\0'; return( 0 ); }
/* * Load all data from a file into a given buffer. */ int x509_load_file( const char *path, unsigned char **buf, size_t *n ) { FILE *f; long size; if( ( f = fopen( path, "rb" ) ) == NULL ) return( POLARSSL_ERR_X509_FILE_IO_ERROR ); fseek( f, 0, SEEK_END ); if( ( size = ftell( f ) ) == -1 ) { fclose( f ); return( POLARSSL_ERR_X509_FILE_IO_ERROR ); } fseek( f, 0, SEEK_SET ); *n = (size_t) size; if( *n + 1 == 0 || ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL ) { fclose( f ); return( POLARSSL_ERR_X509_MALLOC_FAILED ); } if( fread( *buf, 1, *n, f ) != *n ) { fclose( f ); polarssl_free( *buf ); return( POLARSSL_ERR_X509_FILE_IO_ERROR ); } fclose( f ); (*buf)[*n] = '\0'; return( 0 ); }
/* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * 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. */ int x509_get_name( unsigned char **p, const unsigned char *end, x509_name *cur ) { int ret; size_t set_len; const unsigned char *end_set; /* * parse first SET, restricted to 1 element */ if( ( ret = asn1_get_tag( p, end, &set_len, ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 ) return( POLARSSL_ERR_X509_INVALID_NAME + ret ); end_set = *p + set_len; if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) return( ret ); if( *p != end_set ) return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); /* * recurse until end of SEQUENCE is reached */ if( *p == end ) return( 0 ); 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 ) ); return( x509_get_name( p, end, cur->next ) ); }
static void * blowfish_ctx_alloc( void ) { return polarssl_malloc( sizeof( blowfish_context ) ); }
static void * sha384_ctx_alloc( void ) { return polarssl_malloc( sizeof( sha512_context ) ); }
static void * sha224_ctx_alloc( void ) { return polarssl_malloc( sizeof( sha256_context ) ); }
static void * md5_ctx_alloc( void ) { return polarssl_malloc( sizeof( md5_context ) ); }
/* * Parse one CRLs in DER format and append it to the chained list */ int x509_crl_parse_der( x509_crl *chain, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; x509_buf sig_params1, sig_params2; x509_crl *crl = chain; /* * Check for valid input */ if( crl == NULL || buf == NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); memset( &sig_params1, 0, sizeof( x509_buf ) ); memset( &sig_params2, 0, sizeof( x509_buf ) ); /* * Add new CRL on the end of the chain if needed. */ while( crl->version != 0 && crl->next != NULL ) crl = crl->next; if( crl->version != 0 && crl->next == NULL ) { crl->next = polarssl_malloc( sizeof( x509_crl ) ); if( crl->next == NULL ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_MALLOC_FAILED ); } x509_crl_init( crl->next ); crl = crl->next; } /* * Copy raw DER-encoded CRL */ if( ( p = polarssl_malloc( buflen ) ) == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memcpy( p, buf, buflen ); crl->raw.p = p; crl->raw.len = buflen; end = p + buflen; /* * CertificateList ::= SEQUENCE { * tbsCertList TBSCertList, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } /* * TBSCertList ::= SEQUENCE { */ crl->tbs.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } end = p + len; crl->tbs.len = end - crl->tbs.p; /* * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } * -- if present, MUST be v2 * * signature AlgorithmIdentifier */ if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || ( ret = x509_get_alg( &p, end, &crl->sig_oid1, &sig_params1 ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } crl->version++; if( crl->version > 2 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); } if( ( ret = x509_get_sig_alg( &crl->sig_oid1, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); } /* * issuer Name */ crl->issuer_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } crl->issuer_raw.len = p - crl->issuer_raw.p; /* * thisUpdate Time * nextUpdate Time OPTIONAL */ if( ( ret = x509_get_time( &p, end, &crl->this_update ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } if( ( ret = x509_get_time( &p, end, &crl->next_update ) ) != 0 ) { if( ret != ( POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) && ret != ( POLARSSL_ERR_X509_INVALID_DATE + POLARSSL_ERR_ASN1_OUT_OF_DATA ) ) { x509_crl_free( crl ); return( ret ); } } /* * revokedCertificates SEQUENCE OF SEQUENCE { * userCertificate CertificateSerialNumber, * revocationDate Time, * crlEntryExtensions Extensions OPTIONAL * -- if present, MUST be v2 * } OPTIONAL */ if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } /* * crlExtensions EXPLICIT Extensions OPTIONAL * -- if present, MUST be v2 */ if( crl->version == 2 ) { ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); if( ret != 0 ) { x509_crl_free( crl ); return( ret ); } } if( p != end ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } end = crl->raw.p + crl->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if( ( ret = x509_get_alg( &p, end, &crl->sig_oid2, &sig_params2 ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } if( crl->sig_oid1.len != crl->sig_oid2.len || memcmp( crl->sig_oid1.p, crl->sig_oid2.p, crl->sig_oid1.len ) != 0 || sig_params1.len != sig_params2.len || ( sig_params1.len != 0 && memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_SIG_MISMATCH ); } if( ( ret = x509_get_sig( &p, end, &crl->sig ) ) != 0 ) { x509_crl_free( crl ); return( ret ); } if( p != end ) { x509_crl_free( crl ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }
/* * X.509 CRL Entries */ static int x509_get_entries( unsigned char **p, const unsigned char *end, x509_crl_entry *entry ) { int ret; size_t entry_len; x509_crl_entry *cur_entry = entry; if( *p == end ) return( 0 ); if( ( ret = asn1_get_tag( p, end, &entry_len, ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) { if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) return( 0 ); return( ret ); } end = *p + entry_len; while( *p < end ) { size_t len2; const unsigned char *end2; if( ( ret = asn1_get_tag( p, end, &len2, ASN1_SEQUENCE | ASN1_CONSTRUCTED ) ) != 0 ) { return( ret ); } cur_entry->raw.tag = **p; cur_entry->raw.p = *p; cur_entry->raw.len = len2; end2 = *p + len2; if( ( ret = x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) return( ret ); if( ( ret = x509_get_time( p, end2, &cur_entry->revocation_date ) ) != 0 ) return( ret ); if( ( ret = x509_get_crl_entry_ext( p, end2, &cur_entry->entry_ext ) ) != 0 ) return( ret ); if( *p < end ) { cur_entry->next = polarssl_malloc( sizeof( x509_crl_entry ) ); if( cur_entry->next == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memset( cur_entry->next, 0, sizeof( x509_crl_entry ) ); cur_entry = cur_entry->next; } } return( 0 ); }
/* * Parse a CSR */ int x509_csr_parse( x509_csr *csr, const unsigned char *buf, size_t buflen ) { int ret; size_t len; unsigned char *p, *end; #if defined(POLARSSL_PEM_PARSE_C) size_t use_len; pem_context pem; #endif /* * Check for valid input */ if( csr == NULL || buf == NULL ) return( POLARSSL_ERR_X509_BAD_INPUT_DATA ); x509_csr_init( csr ); #if defined(POLARSSL_PEM_PARSE_C) pem_init( &pem ); ret = pem_read_buffer( &pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len ); if( ret == 0 ) { /* * Was PEM encoded */ buflen -= use_len; buf += use_len; /* * Steal PEM buffer */ p = pem.buf; pem.buf = NULL; len = pem.buflen; pem_free( &pem ); } else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) { pem_free( &pem ); return( ret ); } else #endif { /* * nope, copy the raw DER data */ p = (unsigned char *) polarssl_malloc( len = buflen ); if( p == NULL ) return( POLARSSL_ERR_X509_MALLOC_FAILED ); memcpy( p, buf, buflen ); buflen = 0; } csr->raw.p = p; csr->raw.len = len; end = p + len; /* * CertificationRequest ::= SEQUENCE { * certificationRequestInfo CertificationRequestInfo, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT ); } if( len != (size_t) ( end - p ) ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } /* * CertificationRequestInfo ::= SEQUENCE { */ csr->cri.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } end = p + len; csr->cri.len = end - csr->cri.p; /* * Version ::= INTEGER { v1(0) } */ if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } csr->version++; if( csr->version != 1 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_UNKNOWN_VERSION ); } /* * subject Name */ csr->subject_raw.p = p; if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } csr->subject_raw.len = p - csr->subject_raw.p; /* * subjectPKInfo SubjectPublicKeyInfo */ if( ( ret = pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } /* * attributes [0] Attributes */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + ret ); } // TODO Parse Attributes / extension requests p += len; end = csr->raw.p + csr->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING */ if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md, &csr->sig_pk ) ) != 0 ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG ); } if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 ) { x509_csr_free( csr ); return( ret ); } if( p != end ) { x509_csr_free( csr ); return( POLARSSL_ERR_X509_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); } return( 0 ); }