From 8eabfc14616e746fbf2c1bb87475668cc5572291 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 10:18:25 +0200 Subject: [PATCH] Rewrote x509 certificate request writing to use structure for storing --- include/polarssl/x509write.h | 21 ++- library/x509write.c | 157 +++++++++++++++++++-- programs/x509/cert_req.c | 121 +++++----------- tests/suites/test_suite_x509write.function | 35 ++--- 4 files changed, 215 insertions(+), 119 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 0d94f0154..c845f78ec 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -33,6 +33,10 @@ #include "rsa.h" +#define POLARSSL_ERR_X509_WRITE_UNKNOWN_OID -1 +#define POLARSSL_ERR_X509_WRITE_BAD_INPUT_DATA -1 +#define POLARSSL_ERR_X509_WRITE_MALLOC_FAILED -1 + #ifdef __cplusplus extern "C" { #endif @@ -46,10 +50,23 @@ typedef struct _x509_req_name } x509_req_name; +typedef struct _x509_cert_req +{ + rsa_context *rsa; + x509_req_name *subject; + md_type_t md_alg; +} +x509_cert_req; + +void x509cert_req_init( x509_cert_req *ctx ); +int x509cert_req_set_subject_name( x509_cert_req *ctx, char *subject_name ); +void x509cert_req_set_rsa_key( x509_cert_req *ctx, rsa_context *rsa ); +void x509cert_req_set_md_alg( x509_cert_req *ctx, md_type_t md_alg ); +void x509cert_req_free( x509_cert_req *ctx ); + int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ); int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa ); -int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, - x509_req_name *req_name, md_type_t md_alg ); +int x509_write_cert_req( x509_cert_req *ctx, unsigned char *buf, size_t size ); #ifdef __cplusplus } diff --git a/library/x509write.c b/library/x509write.c index 7aa65ce37..213add6a0 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -33,6 +33,126 @@ #include "polarssl/md.h" #include "polarssl/oid.h" +#if defined(POLARSSL_MEMORY_C) +#include "polarssl/memory.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + +void x509cert_req_init( x509_cert_req *ctx ) +{ + memset( ctx, 0, sizeof(x509_cert_req) ); +} + +void x509cert_req_free( x509_cert_req *ctx ) +{ + x509_req_name *cur; + + while( ( cur = ctx->subject ) != NULL ) + { + ctx->subject = cur->next; + polarssl_free( cur ); + } + + memset( ctx, 0, sizeof(x509_cert_req) ); +} + +void x509cert_req_set_md_alg( x509_cert_req *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509cert_req_set_rsa_key( x509_cert_req *ctx, rsa_context *rsa ) +{ + ctx->rsa = rsa; +} + +int x509cert_req_set_subject_name( x509_cert_req *ctx, char *subject_name ) +{ + int ret = 0; + char *s = subject_name, *c = s; + char *end = s + strlen( s ); + char *oid = NULL; + int in_tag = 1; + x509_req_name *cur = ctx->subject; + + while( ctx->subject ) + { + cur = ctx->subject; + ctx->subject = ctx->subject->next; + polarssl_free( cur ); + } + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 ) + oid = OID_AT_CN; + else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 ) + oid = OID_AT_COUNTRY; + else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 ) + oid = OID_AT_ORGANIZATION; + else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 ) + oid = OID_AT_LOCALITY; + else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 ) + oid = OID_PKCS9_EMAIL; + else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 ) + oid = OID_AT_ORG_UNIT; + else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 ) + oid = OID_AT_STATE; + else + { + ret = POLARSSL_ERR_X509_WRITE_UNKNOWN_OID; + goto exit; + } + + s = c + 1; + in_tag = 0; + } + + if( !in_tag && ( *c == ',' || c == end ) ) + { + if( c - s > 127 ) + { + ret = POLARSSL_ERR_X509_WRITE_BAD_INPUT_DATA; + goto exit; + } + + if( cur == NULL ) + { + ctx->subject = cur = polarssl_malloc( sizeof(x509_req_name) ); + } + else + { + cur->next = polarssl_malloc( sizeof(x509_req_name) ); + cur = cur->next; + } + + if( cur == NULL ) + { + ret = POLARSSL_ERR_X509_WRITE_MALLOC_FAILED; + goto exit; + } + + memset( cur, 0, sizeof(x509_req_name) ); + + strncpy( cur->oid, oid, strlen( oid ) ); + strncpy( cur->name, s, c - s ); + + s = c + 1; + in_tag = 1; + } + c++; + } + +exit: + + return( ret ); +} + int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) { int ret; @@ -41,6 +161,12 @@ int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) c = buf + size - 1; + /* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); @@ -50,6 +176,11 @@ int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) if( c - buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ *--c = 0; len += 1; @@ -167,8 +298,8 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, return( len ); } -int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, - x509_req_name *req_name, md_type_t md_alg ) +int x509_write_cert_req( x509_cert_req *ctx, unsigned char *buf, + size_t size ) { int ret; const char *sig_oid; @@ -178,15 +309,15 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, unsigned char tmp_buf[2048]; size_t sub_len = 0, pub_len = 0, sig_len = 0; size_t len = 0; - x509_req_name *cur = req_name; + x509_req_name *cur = ctx->subject; c = tmp_buf + 2048 - 1; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->E ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->N ) ); + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) ); + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) ); ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) ); ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); @@ -194,6 +325,11 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, if( c - tmp_buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + /* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ *--c = 0; pub_len += 1; @@ -217,21 +353,24 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - md( md_info_from_type( md_alg ), c, len, hash ); + md( md_info_from_type( ctx->md_alg ), c, len, hash ); - rsa_pkcs1_sign( rsa, NULL, NULL, RSA_PRIVATE, md_alg, 0, hash, sig ); + rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); // Generate correct OID // - ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, md_alg, &sig_oid ); + ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid ); c2 = buf + size - 1; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, rsa->len ) ); + ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) ); c2 -= len; memcpy( c2, c, len ); diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index cbd62521d..b2797c079 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -65,8 +65,7 @@ void my_debug( void *ctx, int level, const char *str ) } } -void write_certificate_request( rsa_context *rsa, x509_req_name *req_name, - char *output_file ) +int write_certificate_request( x509_cert_req *req, char *output_file ) { FILE *f; unsigned char output_buf[4096]; @@ -76,19 +75,22 @@ void write_certificate_request( rsa_context *rsa, x509_req_name *req_name, size_t len = 0, olen = 4096; memset(output_buf, 0, 4096); - ret = x509_write_cert_req( output_buf, 4096, rsa, req_name, POLARSSL_MD_SHA1 ); + ret = x509_write_cert_req( req, output_buf, 4096 ); if( ret < 0 ) - return; + return( ret ); len = ret; c = output_buf + 4095 - len; - base64_encode( base_buf, &olen, c, len ); + if( ( ret = base64_encode( base_buf, &olen, c, len ) ) != 0 ) + return( ret ); c = base_buf; - f = fopen( output_file, "w" ); + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + fprintf(f, "-----BEGIN CERTIFICATE REQUEST-----\n"); while (olen) { @@ -101,6 +103,8 @@ void write_certificate_request( rsa_context *rsa, x509_req_name *req_name, } fprintf(f, "-----END CERTIFICATE REQUEST-----\n"); fclose(f); + + return( 0 ); } #define USAGE \ @@ -131,15 +135,13 @@ int main( int argc, char *argv[] ) char buf[1024]; int i, j, n; char *p, *q; - char *s, *c, *end; - int in_tag; - char *oid = NULL; - x509_req_name *req_name = NULL; - x509_req_name *cur = req_name; + x509_cert_req req; /* * Set to sane values */ + x509cert_req_init( &req ); + x509cert_req_set_md_alg( &req, POLARSSL_MD_SHA1 ); memset( &rsa, 0, sizeof( rsa_context ) ); memset( buf, 0, 1024 ); @@ -191,74 +193,13 @@ int main( int argc, char *argv[] ) /* * 1.0. Check the subject name for validity */ - s = opt.subject_name; - end = s + strlen( s ); - - c = s; - - in_tag = 1; - while( c <= end ) + if( ( ret = x509cert_req_set_subject_name( &req, opt.subject_name ) ) != 0 ) { - if( in_tag && *c == '=' ) - { - if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 ) - oid = OID_AT_CN; - else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 ) - oid = OID_AT_COUNTRY; - else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 ) - oid = OID_AT_ORGANIZATION; - else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 ) - oid = OID_AT_LOCALITY; - else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 ) - oid = OID_PKCS9_EMAIL; - else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 ) - oid = OID_AT_ORG_UNIT; - else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 ) - oid = OID_AT_STATE; - else - { - printf("Failed to parse subject name.\n"); - goto exit; - } - - s = c + 1; - in_tag = 0; - } - - if( !in_tag && ( *c == ',' || c == end ) ) - { - if( c - s > 127 ) - { - printf("Name too large for buffer.\n"); - goto exit; - } - - if( cur == NULL ) - { - req_name = malloc( sizeof(x509_req_name) ); - cur = req_name; - } - else - { - cur->next = malloc( sizeof(x509_req_name) ); - cur = cur->next; - } - - if( cur == NULL ) - { - printf( "Failed to allocate memory.\n" ); - goto exit; - } - - memset( cur, 0, sizeof(x509_req_name) ); - - strncpy( cur->oid, oid, strlen( oid ) ); - strncpy( cur->name, s, c - s ); - - s = c + 1; - in_tag = 1; - } - c++; +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509cert_req_set_subject_name returned %d - %s\n\n", ret, buf ); + goto exit; } /* @@ -275,16 +216,32 @@ int main( int argc, char *argv[] ) error_strerror( ret, buf, 1024 ); #endif printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); - rsa_free( &rsa ); + goto exit; + } + + x509cert_req_set_rsa_key( &req, &rsa ); + + printf( " ok\n" ); + + /* + * 1.2. Writing the request + */ + printf( " . Writing the certificate request ..." ); + fflush( stdout ); + + if( ( ret = write_certificate_request( &req, opt.output_file ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! write_certifcate_request %d - %s\n\n", ret, buf ); goto exit; } printf( " ok\n" ); - write_certificate_request( &rsa, req_name, opt.output_file ); - exit: - + x509cert_req_free( &req ); rsa_free( &rsa ); #if defined(_WIN32) diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 680dfb4c4..c44cfb7ed 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -16,31 +16,14 @@ void x509_cert_req_check( char *key_file, int md_type, { rsa_context rsa; pem_context pem; - x509_req_name req_name, *cur; + x509_cert_req req; unsigned char *c; unsigned char buf[4000]; unsigned char check_buf[4000]; int ret; size_t olen = 2000; FILE *f; - - cur = &req_name; - - memset( cur, 0, sizeof(x509_req_name) ); - strcpy( cur->oid, OID_AT_CN ); - strcpy( cur->name, "PolarSSL Server 1" ); - cur->next = malloc( sizeof(x509_req_name) ); - cur = cur->next; - - memset( cur, 0, sizeof(x509_req_name) ); - strcpy( cur->oid, OID_AT_ORGANIZATION ); - strcpy( cur->name, "PolarSSL" ); - cur->next = malloc( sizeof(x509_req_name) ); - cur = cur->next; - - memset( cur, 0, sizeof(x509_req_name) ); - strcpy( cur->oid, OID_AT_COUNTRY ); - strcpy( cur->name, "NL" ); + char *subject_name = "CN=PolarSSL Server 1,O=PolarSSL,C=NL"; memset( &rsa, 0, sizeof(rsa_context) ); ret = x509parse_keyfile_rsa( &rsa, key_file, NULL ); @@ -48,7 +31,12 @@ void x509_cert_req_check( char *key_file, int md_type, if( ret != 0 ) return; - ret = x509_write_cert_req( buf, 4000, &rsa, &req_name, md_type ); + x509cert_req_init( &req ); + x509cert_req_set_md_alg( &req, md_type ); + x509cert_req_set_rsa_key( &req, &rsa ); + TEST_ASSERT( x509cert_req_set_subject_name( &req, subject_name ) == 0 ); + + ret = x509_write_cert_req( &req, buf, 4000 ); TEST_ASSERT( ret >= 0 ); c = buf + 3999 - ret; @@ -64,12 +52,7 @@ void x509_cert_req_check( char *key_file, int md_type, TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); TEST_ASSERT( pem.buflen == (size_t) ret ); - while( ( cur = req_name.next ) != NULL ) - { - req_name.next = cur->next; - free( cur ); - } - + x509cert_req_free( &req ); rsa_free( &rsa ); pem_free( &pem ); }