From 8eabfc14616e746fbf2c1bb87475668cc5572291 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 10:18:25 +0200 Subject: [PATCH 01/19] 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 ); } From 2130796658f1ce3f48b85da9318e55a88cc7a541 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 10:33:27 +0200 Subject: [PATCH 02/19] Switched order of storing x509_req_names to match inputed order --- library/x509write.c | 15 +++++---------- tests/suites/test_suite_x509write.function | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index 213add6a0..330263645 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -76,7 +76,7 @@ int x509cert_req_set_subject_name( x509_cert_req *ctx, char *subject_name ) char *end = s + strlen( s ); char *oid = NULL; int in_tag = 1; - x509_req_name *cur = ctx->subject; + x509_req_name *cur; while( ctx->subject ) { @@ -121,15 +121,7 @@ int x509cert_req_set_subject_name( x509_cert_req *ctx, char *subject_name ) 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; - } + cur = polarssl_malloc( sizeof(x509_req_name) ); if( cur == NULL ) { @@ -139,6 +131,9 @@ int x509cert_req_set_subject_name( x509_cert_req *ctx, char *subject_name ) memset( cur, 0, sizeof(x509_req_name) ); + cur->next = ctx->subject; + ctx->subject = cur; + strncpy( cur->oid, oid, strlen( oid ) ); strncpy( cur->name, s, c - s ); diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index c44cfb7ed..2453bd403 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -23,7 +23,7 @@ void x509_cert_req_check( char *key_file, int md_type, int ret; size_t olen = 2000; FILE *f; - char *subject_name = "CN=PolarSSL Server 1,O=PolarSSL,C=NL"; + char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1"; memset( &rsa, 0, sizeof(rsa_context) ); ret = x509parse_keyfile_rsa( &rsa, key_file, NULL ); From 384d4351cebadfc30768022f9e60a5aab9e4d965 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 10:34:32 +0200 Subject: [PATCH 03/19] Added cert_req to CMakeLists.txt --- programs/x509/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt index 08a962aef..d07cff82d 100644 --- a/programs/x509/CMakeLists.txt +++ b/programs/x509/CMakeLists.txt @@ -16,6 +16,9 @@ target_link_libraries(cert_app ${libs}) add_executable(crl_app crl_app.c) target_link_libraries(crl_app ${libs}) -install(TARGETS cert_app crl_app +add_executable(cert_req cert_req.c) +target_link_libraries(cert_req ${libs}) + +install(TARGETS cert_app crl_app cert_req DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) From 82e2945ed2aa42867fb883ed7274f894c3a746d9 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 11:01:31 +0200 Subject: [PATCH 04/19] Changed naming and prototype convention for x509write functions CSR writing functions now start with x509write_csr_*() DER writing functions now have the context at the start instead of the end conforming to other modules. --- include/polarssl/x509write.h | 24 +++++++++------------- library/x509write.c | 21 +++++++++---------- programs/x509/cert_req.c | 18 ++++++++-------- tests/suites/test_suite_x509write.data | 14 ++++++------- tests/suites/test_suite_x509write.function | 16 +++++++-------- 5 files changed, 44 insertions(+), 49 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index c845f78ec..c95172f57 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -29,8 +29,6 @@ #include "config.h" -#if defined(POLARSSL_X509_WRITE_C) - #include "rsa.h" #define POLARSSL_ERR_X509_WRITE_UNKNOWN_OID -1 @@ -50,28 +48,26 @@ typedef struct _x509_req_name } x509_req_name; -typedef struct _x509_cert_req +typedef struct _x509_csr { rsa_context *rsa; x509_req_name *subject; md_type_t md_alg; } -x509_cert_req; +x509_csr; -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 ); +void x509write_csr_init( x509_csr *ctx ); +int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ); +void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ); +void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); +void x509write_csr_free( x509_csr *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( x509_cert_req *ctx, unsigned char *buf, size_t size ); +int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ); +int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); +int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ); #ifdef __cplusplus } #endif -#endif /* POLARSSL_X509_WRITE_C */ - #endif /* POLARSSL_X509_WRITE_H */ diff --git a/library/x509write.c b/library/x509write.c index 330263645..0e6e4bf6a 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -41,12 +41,12 @@ #define polarssl_free free #endif -void x509cert_req_init( x509_cert_req *ctx ) +void x509write_csr_init( x509_csr *ctx ) { - memset( ctx, 0, sizeof(x509_cert_req) ); + memset( ctx, 0, sizeof(x509_csr) ); } -void x509cert_req_free( x509_cert_req *ctx ) +void x509write_csr_free( x509_csr *ctx ) { x509_req_name *cur; @@ -56,20 +56,20 @@ void x509cert_req_free( x509_cert_req *ctx ) polarssl_free( cur ); } - memset( ctx, 0, sizeof(x509_cert_req) ); + memset( ctx, 0, sizeof(x509_csr) ); } -void x509cert_req_set_md_alg( x509_cert_req *ctx, md_type_t md_alg ) +void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ) { ctx->md_alg = md_alg; } -void x509cert_req_set_rsa_key( x509_cert_req *ctx, rsa_context *rsa ) +void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ) { ctx->rsa = rsa; } -int x509cert_req_set_subject_name( x509_cert_req *ctx, char *subject_name ) +int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) { int ret = 0; char *s = subject_name, *c = s; @@ -148,7 +148,7 @@ exit: return( ret ); } -int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) +int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; unsigned char *c; @@ -190,7 +190,7 @@ int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) return( len ); } -int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa ) +int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; unsigned char *c; @@ -293,8 +293,7 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, return( len ); } -int x509_write_cert_req( x509_cert_req *ctx, unsigned char *buf, - size_t size ) +int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) { int ret; const char *sig_oid; diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index b2797c079..3e8be3001 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -65,7 +65,7 @@ void my_debug( void *ctx, int level, const char *str ) } } -int write_certificate_request( x509_cert_req *req, char *output_file ) +int write_certificate_request( x509_csr *req, char *output_file ) { FILE *f; unsigned char output_buf[4096]; @@ -75,7 +75,7 @@ int write_certificate_request( x509_cert_req *req, char *output_file ) size_t len = 0, olen = 4096; memset(output_buf, 0, 4096); - ret = x509_write_cert_req( req, output_buf, 4096 ); + ret = x509write_csr_der( req, output_buf, 4096 ); if( ret < 0 ) return( ret ); @@ -135,13 +135,13 @@ int main( int argc, char *argv[] ) char buf[1024]; int i, j, n; char *p, *q; - x509_cert_req req; + x509_csr req; /* * Set to sane values */ - x509cert_req_init( &req ); - x509cert_req_set_md_alg( &req, POLARSSL_MD_SHA1 ); + x509write_csr_init( &req ); + x509write_csr_set_md_alg( &req, POLARSSL_MD_SHA1 ); memset( &rsa, 0, sizeof( rsa_context ) ); memset( buf, 0, 1024 ); @@ -193,12 +193,12 @@ int main( int argc, char *argv[] ) /* * 1.0. Check the subject name for validity */ - if( ( ret = x509cert_req_set_subject_name( &req, opt.subject_name ) ) != 0 ) + if( ( ret = x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 ) { #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 ); + printf( " failed\n ! x509write_csr_set_subject_name returned %d - %s\n\n", ret, buf ); goto exit; } @@ -219,7 +219,7 @@ int main( int argc, char *argv[] ) goto exit; } - x509cert_req_set_rsa_key( &req, &rsa ); + x509write_csr_set_rsa_key( &req, &rsa ); printf( " ok\n" ); @@ -241,7 +241,7 @@ int main( int argc, char *argv[] ) printf( " ok\n" ); exit: - x509cert_req_free( &req ); + x509write_csr_free( &req ); rsa_free( &rsa ); #if defined(_WIN32) diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index c4984360b..7a48440e4 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -1,27 +1,27 @@ Certificate Request check Server1 SHA1 depends_on:POLARSSL_SHA1_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA1:"data_files/server1.req.sha1" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA1:"data_files/server1.req.sha1" Certificate Request check Server1 SHA224 depends_on:POLARSSL_SHA256_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA224:"data_files/server1.req.sha224" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA224:"data_files/server1.req.sha224" Certificate Request check Server1 SHA256 depends_on:POLARSSL_SHA256_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA256:"data_files/server1.req.sha256" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA256:"data_files/server1.req.sha256" Certificate Request check Server1 SHA384 depends_on:POLARSSL_SHA512_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA384:"data_files/server1.req.sha384" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA384:"data_files/server1.req.sha384" Certificate Request check Server1 SHA512 depends_on:POLARSSL_SHA512_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA512:"data_files/server1.req.sha512" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA512:"data_files/server1.req.sha512" Certificate Request check Server1 MD4 depends_on:POLARSSL_MD4_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_MD4:"data_files/server1.req.md4" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD4:"data_files/server1.req.md4" Certificate Request check Server1 MD5 depends_on:POLARSSL_MD5_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req.md5" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req.md5" diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 2453bd403..d3c801a1d 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -11,12 +11,12 @@ */ /* BEGIN_CASE */ -void x509_cert_req_check( char *key_file, int md_type, +void x509_csr_check( char *key_file, int md_type, char *cert_req_check_file ) { rsa_context rsa; pem_context pem; - x509_cert_req req; + x509_csr req; unsigned char *c; unsigned char buf[4000]; unsigned char check_buf[4000]; @@ -31,12 +31,12 @@ void x509_cert_req_check( char *key_file, int md_type, if( ret != 0 ) return; - 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 ); + x509write_csr_init( &req ); + x509write_csr_set_md_alg( &req, md_type ); + x509write_csr_set_rsa_key( &req, &rsa ); + TEST_ASSERT( x509write_csr_set_subject_name( &req, subject_name ) == 0 ); - ret = x509_write_cert_req( &req, buf, 4000 ); + ret = x509write_csr_der( &req, buf, 4000 ); TEST_ASSERT( ret >= 0 ); c = buf + 3999 - ret; @@ -52,7 +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 ); - x509cert_req_free( &req ); + x509write_csr_free( &req ); rsa_free( &rsa ); pem_free( &pem ); } From 0e06c0fdb49b75b03ff06b1d7aada5861c70ff5d Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 11:21:30 +0200 Subject: [PATCH 05/19] Assigned error codes to the error defines --- include/polarssl/error.h | 27 ++++++++++++++------------- include/polarssl/x509write.h | 7 ++++--- library/error.c | 15 ++++++++++++++- library/x509write.c | 6 +++--- scripts/generate_errors.pl | 3 ++- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/include/polarssl/error.h b/include/polarssl/error.h index 889e4bebc..4c9ef7c47 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -73,19 +73,20 @@ * PBKDF2 1 0x007C-0x007C * * High-level module nr (3 bits - 0x1...-0x8...) - * Name ID Nr of Errors - * PEM 1 9 - * PKCS#12 1 4 (Started from top) - * X509 2 25 - * PK 2 3 (Started from top) - * DHM 3 6 - * PKCS5 3 4 (Started from top) - * RSA 4 9 - * ECP 4 4 (Started from top) - * MD 5 4 - * CIPHER 6 5 - * SSL 6 6 (Started from top) - * SSL 7 31 + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 25 + * PK 2 3 (Started from top) + * DHM 3 6 + * PKCS5 3 4 (Started from top) + * RSA 4 9 + * ECP 4 4 (Started from top) + * MD 5 4 + * X509WRITE 5 3 (Started from top) + * CIPHER 6 5 + * SSL 6 6 (Started from top) + * SSL 7 31 * * Module dependent error code (5 bits 0x.08.-0x.F8.) */ diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index c95172f57..2933b2f5c 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -31,9 +31,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 +#define POLARSSL_ERR_X509WRITE_UNKNOWN_OID -0x5F80 /**< Requested OID is unknown. */ +#define POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA -0x5F00 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_X509WRITE_MALLOC_FAILED -0x5E80 /**< Failed to allocate memory. */ + #ifdef __cplusplus extern "C" { diff --git a/library/error.c b/library/error.c index 0ea3c297c..86586dde2 100644 --- a/library/error.c +++ b/library/error.c @@ -149,6 +149,10 @@ #include "polarssl/x509.h" #endif +#if defined(POLARSSL_X509_WRITE_C) +#include "polarssl/x509write.h" +#endif + #if defined(POLARSSL_XTEA_C) #include "polarssl/xtea.h" #endif @@ -251,7 +255,7 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(POLARSSL_ERR_PK_MALLOC_FAILED) ) snprintf( buf, buflen, "PK - Memory alloation failed" ); if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) ) - snprintf( buf, buflen, "PK - Type mismatch, eg attempt to use a RSA key as EC, or to modify key type" ); + snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) ) snprintf( buf, buflen, "PK - Bad input parameters to function" ); #endif /* POLARSSL_PK_C */ @@ -432,6 +436,15 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "X509 - Elliptic curve is unsupported (only NIST curves are supported)" ); #endif /* POLARSSL_X509_PARSE_C */ +#if defined(POLARSSL_X509_WRITE_C) + if( use_ret == -(POLARSSL_ERR_X509WRITE_UNKNOWN_OID) ) + snprintf( buf, buflen, "X509WRITE - Requested OID is unknown" ); + if( use_ret == -(POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "X509WRITE - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_X509WRITE_MALLOC_FAILED) ) + snprintf( buf, buflen, "X509WRITE - Failed to allocate memory" ); +#endif /* POLARSSL_X509_WRITE_C */ + if( strlen( buf ) == 0 ) snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); } diff --git a/library/x509write.c b/library/x509write.c index 0e6e4bf6a..337f4c25c 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -105,7 +105,7 @@ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) oid = OID_AT_STATE; else { - ret = POLARSSL_ERR_X509_WRITE_UNKNOWN_OID; + ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID; goto exit; } @@ -117,7 +117,7 @@ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) { if( c - s > 127 ) { - ret = POLARSSL_ERR_X509_WRITE_BAD_INPUT_DATA; + ret = POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA; goto exit; } @@ -125,7 +125,7 @@ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) if( cur == NULL ) { - ret = POLARSSL_ERR_X509_WRITE_MALLOC_FAILED; + ret = POLARSSL_ERR_X509WRITE_MALLOC_FAILED; goto exit; } diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 7257ae670..5b9549402 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -13,7 +13,7 @@ my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "MD2", "MD4", "MD5", "SHA1", "SHA256", "SHA512", "GCM" ); my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL", - "PK", "PKCS12", "PKCS5" ); + "PK", "PKCS12", "PKCS5", "X509WRITE" ); my $line_separator = $/; undef $/; @@ -49,6 +49,7 @@ while (my $line = ) my $define_name = $module_name; $define_name = "X509_PARSE" if ($define_name eq "X509"); + $define_name = "X509_WRITE" if ($define_name eq "X509WRITE"); $define_name = "ASN1_PARSE" if ($define_name eq "ASN1"); $define_name = "SSL_TLS" if ($define_name eq "SSL"); From f677466d9ac9f01b769eccac80c596a9386e035b Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 11:47:51 +0200 Subject: [PATCH 06/19] Doxygen documentation added to x509write.h --- include/polarssl/x509write.h | 112 ++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 2933b2f5c..acff33dde 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -31,15 +31,38 @@ #include "rsa.h" +/** + * \addtogroup x509_module + * \{ + */ + +/** + * \name X509 Write Error codes + * \{ + */ #define POLARSSL_ERR_X509WRITE_UNKNOWN_OID -0x5F80 /**< Requested OID is unknown. */ #define POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA -0x5F00 /**< Failed to allocate memory. */ #define POLARSSL_ERR_X509WRITE_MALLOC_FAILED -0x5E80 /**< Failed to allocate memory. */ - +/* \} name */ +/* \} addtogroup x509_module */ #ifdef __cplusplus extern "C" { #endif +/** + * \addtogroup x509_module + * \{ + */ + +/** + * \name Structures for writing X.509 CSRs (Certificate Signing Request) + * \{ + */ + +/** + * Container for CSR named objects + */ typedef struct _x509_req_name { char oid[128]; @@ -49,6 +72,9 @@ typedef struct _x509_req_name } x509_req_name; +/** + * Container for a CSR + */ typedef struct _x509_csr { rsa_context *rsa; @@ -57,14 +83,98 @@ typedef struct _x509_csr } x509_csr; +/* \} addtogroup x509_module */ + +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ void x509write_csr_init( x509_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ); + +/** + * \brief Set the RSA key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param rsa RSA key to include + */ void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_ald MD algorithm to use + */ void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ void x509write_csr_free( x509_csr *ctx ); +/** + * \brief Write a RSA public key to a PKCS#1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a RSA key to a PKCS#1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param rsa CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ); #ifdef __cplusplus From ef0ba55a78f4df6d5b8c352bd1d984919cb747b3 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 11:48:10 +0200 Subject: [PATCH 07/19] Removed old X509 write data from x509.h --- include/polarssl/x509.h | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 331553527..45c60ad42 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -289,42 +289,6 @@ x509_crl; /** \} name Structures for parsing X.509 certificates and CRLs */ /** \} addtogroup x509_module */ -/** - * \name Structures for writing X.509 certificates. - * XvP: commented out as they are not used. - * - typedef struct _x509_node x509_node; - * - typedef struct _x509_raw x509_raw; - */ -/* -typedef struct _x509_node -{ - unsigned char *data; - unsigned char *p; - unsigned char *end; - - size_t len; -} -x509_node; - -typedef struct _x509_raw -{ - x509_node raw; - x509_node tbs; - - x509_node version; - x509_node serial; - x509_node tbs_signalg; - x509_node issuer; - x509_node validity; - x509_node subject; - x509_node subpubkey; - - x509_node signalg; - x509_node sign; -} -x509_raw; -*/ - /** * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key * \{ From 598e4505382ca23456096fc6abe092d100799361 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 14:46:39 +0200 Subject: [PATCH 08/19] Added asn1_write_bitstring() and asn1_write_octet_string() --- include/polarssl/asn1write.h | 4 +++ library/asn1write.c | 51 +++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 459b28256..6e4a25798 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -48,6 +48,10 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start, char *text ); int asn1_write_ia5_string( unsigned char **p, unsigned char *start, char *text ); +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); #ifdef __cplusplus } diff --git a/library/asn1write.c b/library/asn1write.c index b1d68392f..fc85bf990 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -216,9 +216,9 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start, return( len ); } - + int asn1_write_ia5_string( unsigned char **p, unsigned char *start, - char *text ) + char *text ) { int ret; size_t len = 0; @@ -238,6 +238,51 @@ int asn1_write_ia5_string( unsigned char **p, unsigned char *start, return( len ); } - + +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0, size; + + size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + + // Calculate byte length + // + if( *p - start < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = size * 8 - bits; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); + + return( len ); +} + +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + if( *p - start < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + return( len ); +} #endif From fde42701861f55befe62e7382a5fccb199dea6c5 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 14:47:27 +0200 Subject: [PATCH 09/19] Added support for writing key_usage extension --- include/polarssl/oid.h | 5 +++++ include/polarssl/x509write.h | 12 ++++++++++- library/x509write.c | 39 ++++++++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index ebb5bad98..025a15f0a 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -227,6 +227,11 @@ #define OID_PKCS5_PBE_SHA1_DES_CBC OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ #define OID_PKCS5_PBE_SHA1_RC2_CBC OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ +/* + * PKCS#8 OIDs + */ +#define OID_PKCS9_CSR_EXT_REQ OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + /* * PKCS#12 PBE OIDs */ diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index acff33dde..aa4d05352 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -29,7 +29,7 @@ #include "config.h" -#include "rsa.h" +#include "x509.h" /** * \addtogroup x509_module @@ -80,6 +80,7 @@ typedef struct _x509_csr rsa_context *rsa; x509_req_name *subject; md_type_t md_alg; + unsigned char key_usage; } x509_csr; @@ -124,6 +125,15 @@ void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ); */ void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage bitstring to set + */ +void x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); + /** * \brief Free the contents of a CSR context * diff --git a/library/x509write.c b/library/x509write.c index 337f4c25c..adeb55123 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -148,6 +148,11 @@ exit: return( ret ); } +void x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +{ + ctx->key_usage = key_usage; +} + int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; @@ -301,13 +306,43 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; - size_t sub_len = 0, pub_len = 0, sig_len = 0; + size_t sub_len = 0, pub_len = 0, sig_len = 0, ext_len = 0; size_t len = 0; x509_req_name *cur = ctx->subject; c = tmp_buf + 2048 - 1; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, 0 ) ); + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * extnValue OCTET STRING } + */ + if( ctx->key_usage ) + { + ASN1_CHK_ADD( ext_len, asn1_write_bitstring( &c, tmp_buf, &ctx->key_usage, 6 ) ); + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_OCTET_STRING ) ); + ASN1_CHK_ADD( ext_len, asn1_write_oid( &c, tmp_buf, OID_KEY_USAGE ) ); + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + } + + if( ext_len ) + { + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); + + ASN1_CHK_ADD( ext_len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ ) ); + + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + } + + len += ext_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, ext_len ) ); 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, &ctx->rsa->E ) ); From 8adf13bd923c25625413fcb1f914655fe69f07be Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 25 Aug 2013 14:50:09 +0200 Subject: [PATCH 10/19] Added pem2der utility application --- programs/.gitignore | 1 + programs/Makefile | 6 +- programs/util/CMakeLists.txt | 5 +- programs/util/pem2der.c | 288 +++++++++++++++++++++++++++++++++++ 4 files changed, 298 insertions(+), 2 deletions(-) create mode 100644 programs/util/pem2der.c diff --git a/programs/.gitignore b/programs/.gitignore index e9f4e54ef..2b7510f6e 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -35,6 +35,7 @@ test/o_p_test test/selftest test/ssl_cert_test test/ssl_test +util/pem2der util/strerror x509/cert_app x509/cert_req diff --git a/programs/Makefile b/programs/Makefile index 1c2b5fc80..ea024fae6 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -39,7 +39,7 @@ APPS = aes/aescrypt2 aes/crypt_and_hash \ test/ssl_cert_test test/benchmark \ test/selftest test/ssl_test \ test/ecp-bench \ - util/strerror \ + util/pem2der util/strerror \ x509/cert_app x509/crl_app \ x509/cert_req @@ -195,6 +195,10 @@ test/o_p_test: test/o_p_test.c ../library/libpolarssl.a echo " CC test/o_p_test.c" $(CC) $(CFLAGS) $(OFLAGS) test/o_p_test.c $(LDFLAGS) -o $@ -lssl -lcrypto +util/pem2der: util/pem2der.c ../library/libpolarssl.a + echo " CC util/pem2der.c" + $(CC) $(CFLAGS) $(OFLAGS) util/pem2der.c $(LDFLAGS) -o $@ + util/strerror: util/strerror.c ../library/libpolarssl.a echo " CC util/strerror.c" $(CC) $(CFLAGS) $(OFLAGS) util/strerror.c $(LDFLAGS) -o $@ diff --git a/programs/util/CMakeLists.txt b/programs/util/CMakeLists.txt index c0f2e4cea..aedd94f58 100644 --- a/programs/util/CMakeLists.txt +++ b/programs/util/CMakeLists.txt @@ -5,6 +5,9 @@ set(libs add_executable(strerror strerror.c) target_link_libraries(strerror ${libs}) -install(TARGETS strerror +add_executable(pem2der pem2der.c) +target_link_libraries(pem2der ${libs}) + +install(TARGETS strerror pem2der DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/util/pem2der.c b/programs/util/pem2der.c new file mode 100644 index 000000000..0315f02ea --- /dev/null +++ b/programs/util/pem2der.c @@ -0,0 +1,288 @@ +/* + * Convert PEM to DER + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include +#include +#include + +#include "polarssl/config.h" + +#include "polarssl/error.h" +#include "polarssl/base64.h" + +#define DFL_FILENAME "file.pem" +#define DFL_OUTPUT_FILENAME "file.der" + +/* + * global options + */ +struct options +{ + char *filename; /* filename of the input file */ + char *output_file; /* where to store the output */ +} opt; + +int convert_pem_to_der( const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + const unsigned char *s1, *s2, *end = input + ilen; + size_t len = 0; + + s1 = (unsigned char *) strstr( (char *) input, "-----BEGIN" ); + if( s1 == NULL ) + return( -1 ); + + s2 = (unsigned char *) strstr( (char *) input, "-----END" ); + if( s2 == NULL ) + return( -1 ); + + s1 += 10; + while( s1 < end && *s1 != '-' ) + s1++; + while( s1 < end && *s1 == '-' ) + s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + + if( s2 <= s1 || s2 > end ) + return( -1 ); + + ret = base64_decode( NULL, &len, (const unsigned char *) s1, s2 - s1 ); + if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) + return( ret ); + + if( len > *olen ) + return( -1 ); + + if( ( ret = base64_decode( output, &len, (const unsigned char *) s1, + s2 - s1 ) ) != 0 ) + { + return( ret ); + } + + *olen = len; + + return( 0 ); +} + +/* + * 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 *) malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( -1 ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + free( *buf ); + return( -1 ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Write buffer to a file + */ +static int write_file( const char *path, unsigned char *buf, size_t n ) +{ + FILE *f; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( -1 ); + + if( fwrite( buf, 1, n, f ) != n ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + return( 0 ); +} + +#define USAGE \ + "\n usage: pem2der param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: file.pem\n" \ + " output_file=%%s default: file.der\n" \ + "\n" + +#if !defined(POLARSSL_BASE64_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BASE64_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else +int main( int argc, char *argv[] ) +{ + int ret = 0; + unsigned char *pem_buffer = NULL; + unsigned char der_buffer[4096]; + char buf[1024]; + size_t pem_size, der_size = sizeof(der_buffer); + int i, j, n; + char *p, *q; + + /* + * Set to sane values + */ + memset( buf, 0, sizeof(buf) ); + memset( der_buffer, 0, sizeof(der_buffer) ); + + if( argc == 0 ) + { + usage: + printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + opt.output_file = DFL_OUTPUT_FILENAME; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + n = strlen( p ); + for( j = 0; j < n; j++ ) + { + if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) + argv[i][j] |= 0x20; + } + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else + goto usage; + } + + /* + * 1.1. Load the PEM file + */ + printf( "\n . Loading the PEM file ..." ); + fflush( stdout ); + + ret = load_file( opt.filename, &pem_buffer, &pem_size ); + + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! load_file returned %d - %s\n\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 1.2. Convert from PEM to DER + */ + printf( " . Converting from PEM to DER ..." ); + fflush( stdout ); + + if( ( ret = convert_pem_to_der( pem_buffer, pem_size, der_buffer, &der_size ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! convert_pem_to_der %d - %s\n\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 1.3. Write the DER file + */ + printf( " . Writing the DER file ..." ); + fflush( stdout ); + + ret = write_file( opt.output_file, der_buffer, der_size ); + + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! write_file returned %d - %s\n\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + +exit: + free( pem_buffer ); + +#if defined(_WIN32) + printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( ret ); +} +#endif /* POLARSSL_BASE64_C && POLARSSL_FS_IO */ From 6db915b5a98710b5f07cf3f02bf1ca685b0a13c7 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 12:05:02 +0200 Subject: [PATCH 11/19] Added asn1_write_raw_buffer() --- include/polarssl/asn1write.h | 2 ++ library/asn1write.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 6e4a25798..9b98afe2e 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -52,6 +52,8 @@ int asn1_write_bitstring( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t bits ); int asn1_write_octet_string( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t size ); +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); #ifdef __cplusplus } diff --git a/library/asn1write.c b/library/asn1write.c index fc85bf990..f08e105d2 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -272,7 +272,7 @@ int asn1_write_octet_string( unsigned char **p, unsigned char *start, int ret; size_t len = 0; - if( *p - start < (int) size + 1 ) + if( *p - start < (int) size ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); len = size; @@ -285,4 +285,19 @@ int asn1_write_octet_string( unsigned char **p, unsigned char *start, return( len ); } +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p - start < (int) size ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( len ); +} + #endif From e5eae76bf015d1ec613adfdae3fceb7e86fc48a5 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 12:05:14 +0200 Subject: [PATCH 12/19] Generalized the x509write_csr_set_key_usage() function and key_usage storage --- include/polarssl/asn1.h | 35 ++++++++++++- include/polarssl/x509.h | 18 +++---- include/polarssl/x509write.h | 6 ++- library/asn1parse.c | 28 ++++++++++ library/x509write.c | 99 ++++++++++++++++++++++++++++-------- 5 files changed, 149 insertions(+), 37 deletions(-) diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index 195ebcb84..ec8cbfafc 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -93,7 +93,10 @@ /** Returns the size of the binary string, without the trailing \\0 */ #define OID_SIZE(x) (sizeof(x) - 1) -/** Compares two asn1_buf structures for the same OID */ +/** Compares two asn1_buf structures for the same OID. Only works for + * 'defined' oid_str values (OID_HMAC_SHA1), you cannot use a 'unsigned + * char *oid' here! + */ #define OID_CMP(oid_str, oid_buf) \ ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \ memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0 ) @@ -139,6 +142,17 @@ typedef struct _asn1_sequence } asn1_sequence; +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +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. */ +} +asn1_named_data; + /** * Get the length of an ASN.1 element. * Updates the pointer to immediately behind the length. @@ -286,6 +300,25 @@ int asn1_get_alg_null( unsigned char **p, const unsigned char *end, asn1_buf *alg ); +/** + * Find a specific named_data entry in a sequence or list based on the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ); + +/** + * Free a asn1_named_data entry + * + * \param entry The named data entry to free + */ +void asn1_free_named_data( asn1_named_data *entry ); + #ifdef __cplusplus } #endif diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 45c60ad42..dc15bb648 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -146,7 +146,7 @@ extern "C" { #endif -/** +/** * \addtogroup x509_module * \{ */ @@ -154,8 +154,8 @@ extern "C" { * \name Structures for parsing X.509 certificates and CRLs * \{ */ - -/** + +/** * Type-length-value structure that allows for ASN1 using DER. */ typedef asn1_buf x509_buf; @@ -166,16 +166,10 @@ typedef asn1_buf x509_buf; typedef asn1_bitstring x509_bitstring; /** - * Container for ASN1 named information objects. + * Container for ASN1 named information objects. * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.). */ -typedef struct _x509_name -{ - x509_buf oid; /**< The object identifier. */ - x509_buf val; /**< The named value. */ - struct _x509_name *next; /**< The next named information object. */ -} -x509_name; +typedef asn1_named_data x509_name; /** * Container for a sequence of ASN.1 items @@ -190,7 +184,7 @@ typedef struct _x509_time } x509_time; -/** +/** * Container for an X.509 certificate. The certificate may be chained. */ typedef struct _x509_cert diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index aa4d05352..671047429 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -80,7 +80,7 @@ typedef struct _x509_csr rsa_context *rsa; x509_req_name *subject; md_type_t md_alg; - unsigned char key_usage; + asn1_named_data *extensions; } x509_csr; @@ -131,8 +131,10 @@ void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); * * \param ctx CSR context to use * \param key_usage key usage bitstring to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED */ -void x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); +int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); /** * \brief Free the contents of a CSR context diff --git a/library/asn1parse.c b/library/asn1parse.c index ff566c9ce..f6b271ec5 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -343,4 +343,32 @@ int asn1_get_alg_null( unsigned char **p, return( 0 ); } +void asn1_free_named_data( asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + polarssl_free( cur->oid.p ); + polarssl_free( cur->val.p ); + + memset( cur, 0, sizeof( asn1_named_data ) ); +} + +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + #endif diff --git a/library/x509write.c b/library/x509write.c index adeb55123..0ca7733b2 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -49,6 +49,7 @@ void x509write_csr_init( x509_csr *ctx ) void x509write_csr_free( x509_csr *ctx ) { x509_req_name *cur; + asn1_named_data *cur_ext; while( ( cur = ctx->subject ) != NULL ) { @@ -56,6 +57,13 @@ void x509write_csr_free( x509_csr *ctx ) polarssl_free( cur ); } + while( ( cur_ext = ctx->extensions ) != NULL ) + { + ctx->extensions = cur_ext->next; + asn1_free_named_data( cur_ext ); + polarssl_free( cur_ext ); + } + memset( ctx, 0, sizeof(x509_csr) ); } @@ -148,9 +156,49 @@ exit: return( ret ); } -void x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) { - ctx->key_usage = key_usage; + asn1_named_data *cur; + unsigned char *c; + int len; + + if( ( cur = asn1_find_named_data( ctx->extensions, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ) ) ) == NULL ) + { + cur = polarssl_malloc( sizeof(asn1_named_data) ); + if( cur == NULL ) + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); + + memset( cur, 0, sizeof(asn1_named_data) ); + + cur->oid.len = OID_SIZE( OID_KEY_USAGE ); + cur->oid.p = polarssl_malloc( cur->oid.len ); + if( cur->oid.p == NULL ) + { + free( cur ); + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); + } + + cur->val.len = 4; + cur->val.p = polarssl_malloc( cur->val.len ); + if( cur->val.p == NULL ) + { + free( cur->oid.p ); + free( cur ); + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); + } + + memcpy( cur->oid.p, OID_KEY_USAGE, OID_SIZE( OID_KEY_USAGE ) ); + + cur->next = ctx->extensions; + ctx->extensions = cur; + } + + c = cur->val.p + cur->val.len; + if( ( len = asn1_write_bitstring( &c, cur->val.p, &key_usage, 6 ) ) < 0 ) +exit(1); + + return( 0 ); } int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) @@ -306,43 +354,50 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; - size_t sub_len = 0, pub_len = 0, sig_len = 0, ext_len = 0; + size_t sub_len = 0, pub_len = 0, sig_len = 0; size_t len = 0; x509_req_name *cur = ctx->subject; + asn1_named_data *cur_ext = ctx->extensions; c = tmp_buf + 2048 - 1; - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * extnValue OCTET STRING } - */ - if( ctx->key_usage ) + while( cur_ext != NULL ) { - ASN1_CHK_ADD( ext_len, asn1_write_bitstring( &c, tmp_buf, &ctx->key_usage, 6 ) ); - ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); + size_t ext_len = 0; + + ASN1_CHK_ADD( ext_len, asn1_write_raw_buffer( &c, tmp_buf, cur_ext->val.p, + cur_ext->val.len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, cur_ext->val.len ) ); ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_OCTET_STRING ) ); - ASN1_CHK_ADD( ext_len, asn1_write_oid( &c, tmp_buf, OID_KEY_USAGE ) ); + + ASN1_CHK_ADD( ext_len, asn1_write_raw_buffer( &c, tmp_buf, cur_ext->oid.p, + cur_ext->oid.len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, cur_ext->oid.len ) ); + ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_OID ) ); + ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + cur_ext = cur_ext->next; + + len += ext_len; } - if( ext_len ) + if( len ) { - ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); - ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + 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 ) ); - ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); - ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); - ASN1_CHK_ADD( ext_len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ ) ); + ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ ) ); - ASN1_CHK_ADD( ext_len, asn1_write_len( &c, tmp_buf, ext_len ) ); - ASN1_CHK_ADD( ext_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + 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 ) ); } - len += ext_len; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, ext_len ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); 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, &ctx->rsa->E ) ); From 1c0e550e213f67e77c7a2e9618baa002a587a897 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 13:41:01 +0200 Subject: [PATCH 13/19] Added support for Netscape Certificate Types in CSR writing Further generalization of extension adding / replacing in the CSR structure --- include/polarssl/x509write.h | 28 +++++++++++- library/x509write.c | 84 +++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 671047429..a8e672add 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -130,12 +130,38 @@ void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) * * \param ctx CSR context to use - * \param key_usage key usage bitstring to set + * \param key_usage key usage flags to set * * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED */ int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); +/** + * \brief Set the Netscape Cert Type flags + * (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_extension( x509_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + /** * \brief Free the contents of a CSR context * diff --git a/library/x509write.c b/library/x509write.c index 0ca7733b2..f609fb454 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -156,14 +156,14 @@ exit: return( ret ); } -int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +int x509write_csr_set_extension( x509_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) { asn1_named_data *cur; - unsigned char *c; - int len; - if( ( cur = asn1_find_named_data( ctx->extensions, OID_KEY_USAGE, - OID_SIZE( OID_KEY_USAGE ) ) ) == NULL ) + if( ( cur = asn1_find_named_data( ctx->extensions, oid, + oid_len ) ) == NULL ) { cur = polarssl_malloc( sizeof(asn1_named_data) ); if( cur == NULL ) @@ -171,32 +171,84 @@ int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) memset( cur, 0, sizeof(asn1_named_data) ); - cur->oid.len = OID_SIZE( OID_KEY_USAGE ); - cur->oid.p = polarssl_malloc( cur->oid.len ); + cur->oid.len = oid_len; + cur->oid.p = polarssl_malloc( oid_len ); if( cur->oid.p == NULL ) { - free( cur ); + polarssl_free( cur ); return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } - cur->val.len = 4; - cur->val.p = polarssl_malloc( cur->val.len ); + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); if( cur->val.p == NULL ) { - free( cur->oid.p ); - free( cur ); + polarssl_free( cur->oid.p ); + polarssl_free( cur ); return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } - memcpy( cur->oid.p, OID_KEY_USAGE, OID_SIZE( OID_KEY_USAGE ) ); + memcpy( cur->oid.p, oid, oid_len ); cur->next = ctx->extensions; ctx->extensions = cur; } - c = cur->val.p + cur->val.len; - if( ( len = asn1_write_bitstring( &c, cur->val.p, &key_usage, 6 ) ) < 0 ) -exit(1); + if( cur->val.len != val_len ) + { + polarssl_free( cur->val.p ); + + 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( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); + } + } + + memcpy( cur->val.p, val, val_len ); + + return( 0 ); +} + +int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 6 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( OID_NS_CERT_TYPE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); return( 0 ); } From 624d03a3f71d96368d2fd3b27a18326ccdb276b8 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 14:12:57 +0200 Subject: [PATCH 14/19] Fixed length of key_usage bitstring to 7 bits --- library/x509write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/x509write.c b/library/x509write.c index f609fb454..12cc0e177 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -221,7 +221,7 @@ int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) c = buf + 4; - if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 6 ) ) != 4 ) + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) return( ret ); ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE, From 57be6e22cf24b08e6a547378ba4c8aca5f3ef933 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 14:13:14 +0200 Subject: [PATCH 15/19] cert_req now supports key_usage and ns_cert_type command line options --- programs/x509/cert_req.c | 96 +++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 3e8be3001..b30db19b7 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -44,6 +44,8 @@ #define DFL_DEBUG_LEVEL 0 #define DFL_OUTPUT_FILENAME "cert.req" #define DFL_SUBJECT_NAME "CN=Cert,O=PolarSSL,C=NL" +#define DFL_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 /* * global options @@ -54,17 +56,10 @@ struct options int debug_level; /* level of debugging */ char *output_file; /* where to store the constructed key file */ char *subject_name; /* subject name for certificate request */ + unsigned char key_usage; /* key usage flags */ + unsigned char ns_cert_type; /* NS cert type */ } opt; -void my_debug( void *ctx, int level, const char *str ) -{ - if( level < opt.debug_level ) - { - fprintf( (FILE *) ctx, "%s", str ); - fflush( (FILE *) ctx ); - } -} - int write_certificate_request( x509_csr *req, char *output_file ) { FILE *f; @@ -114,6 +109,24 @@ int write_certificate_request( x509_csr *req, char *output_file ) " debug_level=%%d default: 0 (disabled)\n" \ " output_file=%%s default: cert.req\n" \ " subject_name=%%s default: CN=Cert,O=PolarSSL,C=NL\n" \ + " key_usage=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " digital_signature\n" \ + " non_repudiation\n" \ + " key_encipherment\n" \ + " data_encipherment\n" \ + " key_agreement\n" \ + " key_certificate_sign\n" \ + " crl_sign\n" \ + " ns_cert_type=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " ssl_client\n" \ + " ssl_server\n" \ + " email\n" \ + " object_signing\n" \ + " ssl_ca\n" \ + " email_ca\n" \ + " object_signing_ca\n" \ "\n" #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ @@ -134,7 +147,7 @@ int main( int argc, char *argv[] ) rsa_context rsa; char buf[1024]; int i, j, n; - char *p, *q; + char *p, *q, *r; x509_csr req; /* @@ -149,6 +162,7 @@ int main( int argc, char *argv[] ) { usage: printf( USAGE ); + ret = 1; goto exit; } @@ -156,6 +170,8 @@ int main( int argc, char *argv[] ) opt.debug_level = DFL_DEBUG_LEVEL; opt.output_file = DFL_OUTPUT_FILENAME; opt.subject_name = DFL_SUBJECT_NAME; + opt.key_usage = DFL_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; for( i = 1; i < argc; i++ ) { @@ -186,10 +202,70 @@ int main( int argc, char *argv[] ) { opt.subject_name = q; } + else if( strcmp( p, "key_usage" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "digital_signature" ) == 0 ) + opt.key_usage |= KU_DIGITAL_SIGNATURE; + else if( strcmp( q, "non_repudiation" ) == 0 ) + opt.key_usage |= KU_NON_REPUDIATION; + else if( strcmp( q, "key_encipherment" ) == 0 ) + opt.key_usage |= KU_KEY_ENCIPHERMENT; + else if( strcmp( q, "data_encipherment" ) == 0 ) + opt.key_usage |= KU_DATA_ENCIPHERMENT; + else if( strcmp( q, "key_agreement" ) == 0 ) + opt.key_usage |= KU_KEY_AGREEMENT; + else if( strcmp( q, "key_cert_sign" ) == 0 ) + opt.key_usage |= KU_KEY_CERT_SIGN; + else if( strcmp( q, "crl_sign" ) == 0 ) + opt.key_usage |= KU_CRL_SIGN; + else + goto usage; + + q = r; + } + } + else if( strcmp( p, "ns_cert_type" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "ssl_client" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_SSL_CLIENT; + else if( strcmp( q, "ssl_server" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_SSL_SERVER; + else if( strcmp( q, "email" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_EMAIL; + else if( strcmp( q, "object_signing" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING; + else if( strcmp( q, "ssl_ca" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_SSL_CA; + else if( strcmp( q, "email_ca" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_EMAIL_CA; + else if( strcmp( q, "object_signing_ca" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING_CA; + else + goto usage; + + q = r; + } + } else goto usage; } + if( opt.key_usage ) + x509write_csr_set_key_usage( &req, opt.key_usage ); + + if( opt.ns_cert_type ) + x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type ); + /* * 1.0. Check the subject name for validity */ From 135f1e9c70154f669b102a8d543ffdb0d8cef77f Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 16:54:13 +0200 Subject: [PATCH 16/19] Move PEM conversion of DER data to x509write module --- include/polarssl/x509write.h | 14 +++++++++ library/x509write.c | 57 ++++++++++++++++++++++++++++++++++++ programs/x509/cert_req.c | 34 +++++---------------- 3 files changed, 79 insertions(+), 26 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index a8e672add..d95408395 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -215,6 +215,20 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); */ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ); +#if defined(POLARSSL_BASE64_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param rsa CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ); +#endif /* POLARSSL_BASE64_C */ + #ifdef __cplusplus } #endif diff --git a/library/x509write.c b/library/x509write.c index 12cc0e177..bf6483ea4 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -33,6 +33,10 @@ #include "polarssl/md.h" #include "polarssl/oid.h" +#if defined(POLARSSL_BASE64_C) +#include "polarssl/base64.h" +#endif + #if defined(POLARSSL_MEMORY_C) #include "polarssl/memory.h" #else @@ -518,4 +522,57 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) return( len ); } +#define CSR_PEM_BEGIN "-----BEGIN CERTIFICATE REQUEST-----\n" +#define CSR_PEM_END "-----END CERTIFICATE REQUEST-----\n" + +#if defined(POLARSSL_BASE64_C) +int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + unsigned char base_buf[4096]; + unsigned char *c, *p = buf; + size_t len = 0, olen = 4096; + + memset( output_buf, 0, 4096 ); + + if( ( ret = x509write_csr_der( ctx, output_buf, 4096 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + 4095 - len; + + if( ( ret = base64_encode( base_buf, &olen, c, len ) ) != 0 ) + return( ret ); + + c = base_buf; + + if( olen + strlen( CSR_PEM_BEGIN ) + strlen( CSR_PEM_END ) + + olen / 64 > size ) + { + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + memcpy( p, CSR_PEM_BEGIN, strlen( CSR_PEM_BEGIN ) ); + p += strlen( CSR_PEM_BEGIN ); + + while( olen ) + { + len = ( olen > 64 ) ? 64 : olen; + memcpy( p, c, len ); + olen -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, CSR_PEM_END, strlen( CSR_PEM_END ) ); + p += strlen( CSR_PEM_END ); + + *p = '\0'; + + return( 0 ); +} +#endif /* POLARSSL_BASE64_C */ + #endif diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index b30db19b7..384ef08d6 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -62,41 +62,23 @@ struct options int write_certificate_request( x509_csr *req, char *output_file ) { + int ret; FILE *f; unsigned char output_buf[4096]; - unsigned char base_buf[4096]; - unsigned char *c; - int ret; - size_t len = 0, olen = 4096; + size_t len = 0; - memset(output_buf, 0, 4096); - ret = x509write_csr_der( req, output_buf, 4096 ); - - if( ret < 0 ) + memset( output_buf, 0, 4096 ); + if( ( ret = x509write_csr_pem( req, output_buf, 4096 ) ) < 0 ) return( ret ); - len = ret; - c = output_buf + 4095 - len; - - if( ( ret = base64_encode( base_buf, &olen, c, len ) ) != 0 ) - return( ret ); - - c = base_buf; + len = strlen( (char *) output_buf ); if( ( f = fopen( output_file, "w" ) ) == NULL ) return( -1 ); - fprintf(f, "-----BEGIN CERTIFICATE REQUEST-----\n"); - while (olen) - { - int use_len = olen; - if (use_len > 64) use_len = 64; - fwrite( c, 1, use_len, f ); - olen -= use_len; - c += use_len; - fprintf(f, "\n"); - } - fprintf(f, "-----END CERTIFICATE REQUEST-----\n"); + if( fwrite( output_buf, 1, len, f ) != len ) + return( -1 ); + fclose(f); return( 0 ); From f3df61ad10c1a88b231046e013733426cd11fc7a Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 17:22:23 +0200 Subject: [PATCH 17/19] Generalized PEM writing in x509write module for RSA keys as well --- include/polarssl/x509write.h | 22 ++++++ library/x509write.c | 104 +++++++++++++++++++++------ programs/pkey/key_app_writer.c | 126 +++++++++++++++++++-------------- 3 files changed, 175 insertions(+), 77 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index d95408395..0e443ee8c 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -216,6 +216,28 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ); #if defined(POLARSSL_BASE64_C) +/** + * \brief Write a RSA public key to a PKCS#1 PEM string + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a RSA key to a PKCS#1 PEM string + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ); + /** * \brief Write a CSR (Certificate Signing Request) to a * PEM string diff --git a/library/x509write.c b/library/x509write.c index bf6483ea4..7e04e1206 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -522,39 +522,36 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) return( len ); } -#define CSR_PEM_BEGIN "-----BEGIN CERTIFICATE REQUEST-----\n" -#define CSR_PEM_END "-----END CERTIFICATE REQUEST-----\n" +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n" #if defined(POLARSSL_BASE64_C) -int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ) +static int x509write_pemify( const char *begin_str, const char *end_str, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t size ) { int ret; - unsigned char output_buf[4096]; unsigned char base_buf[4096]; - unsigned char *c, *p = buf; - size_t len = 0, olen = 4096; + unsigned char *c = base_buf, *p = buf; + size_t len = 0, olen = sizeof(base_buf); - memset( output_buf, 0, 4096 ); - - if( ( ret = x509write_csr_der( ctx, output_buf, 4096 ) ) < 0 ) + if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 ) return( ret ); - len = ret; - c = output_buf + 4095 - len; - - if( ( ret = base64_encode( base_buf, &olen, c, len ) ) != 0 ) - return( ret ); - - c = base_buf; - - if( olen + strlen( CSR_PEM_BEGIN ) + strlen( CSR_PEM_END ) + + if( olen + strlen( begin_str ) + strlen( end_str ) + olen / 64 > size ) { return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); } - memcpy( p, CSR_PEM_BEGIN, strlen( CSR_PEM_BEGIN ) ); - p += strlen( CSR_PEM_BEGIN ); + memcpy( p, begin_str, strlen( begin_str ) ); + p += strlen( begin_str ); while( olen ) { @@ -566,13 +563,76 @@ int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ) *p++ = '\n'; } - memcpy( p, CSR_PEM_END, strlen( CSR_PEM_END ) ); - p += strlen( CSR_PEM_END ); + memcpy( p, end_str, strlen( end_str ) ); + p += strlen( end_str ); *p = '\0'; return( 0 ); } + +int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_pubkey_der( rsa, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_key_der( rsa, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_csr_der( ctx, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} #endif /* POLARSSL_BASE64_C */ #endif diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c index 88cb9071c..d9ab45c94 100644 --- a/programs/pkey/key_app_writer.c +++ b/programs/pkey/key_app_writer.c @@ -1,5 +1,5 @@ /* - * Key reading application + * Key writing application * * Copyright (C) 2006-2013, Brainspark B.V. * @@ -60,11 +60,15 @@ int main( int argc, char *argv[] ) #define OUTPUT_MODE_PRIVATE 1 #define OUTPUT_MODE_PUBLIC 2 +#define OUTPUT_FORMAT_PEM 0 +#define OUTPUT_FORMAT_DER 1 + #define DFL_MODE MODE_NONE #define DFL_FILENAME "keyfile.key" #define DFL_DEBUG_LEVEL 0 -#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE +#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE #define DFL_OUTPUT_FILENAME "keyfile.pem" +#define DFL_OUTPUT_FORMAT OUTPUT_FORMAT_PEM /* * global options @@ -75,79 +79,80 @@ struct options const char *filename; /* filename of the key file */ int output_mode; /* the output mode to use */ const char *output_file; /* where to store the constructed key file */ + int output_format; /* the output format to use */ } opt; -static void write_public_key( rsa_context *rsa, const char *output_file ) +static int write_public_key( rsa_context *rsa, const char *output_file ) { + int ret; FILE *f; unsigned char output_buf[16000]; - unsigned char base_buf[16000]; - unsigned char *c; - int ret; - size_t len = 0, olen = 16000; + unsigned char *c = output_buf; + size_t len = 0; memset(output_buf, 0, 16000); - ret = x509_write_pubkey_der( output_buf, 16000, rsa ); - if( ret < 0 ) - return; - - len = ret; - c = output_buf + 15999 - len; - - base64_encode( base_buf, &olen, c, len ); - - c = base_buf; - - f = fopen( output_file, "w" ); - fprintf(f, "-----BEGIN PUBLIC KEY-----\n"); - while (olen) + if( opt.output_format == OUTPUT_FORMAT_PEM ) { - int use_len = olen; - if (use_len > 64) use_len = 64; - fwrite( c, 1, use_len, f ); - olen -= use_len; - c += use_len; - fprintf(f, "\n"); + if( ( ret = x509write_pubkey_pem( rsa, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); } - fprintf(f, "-----END PUBLIC KEY-----\n"); + else + { + if( ( ret = x509write_pubkey_der( rsa, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len - 1; + } + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + return( -1 ); + fclose(f); + + return( 0 ); } -static void write_private_key( rsa_context *rsa, const char *output_file ) +static int write_private_key( rsa_context *rsa, const char *output_file ) { + int ret; FILE *f; unsigned char output_buf[16000]; - unsigned char base_buf[16000]; - unsigned char *c; - int ret; - size_t len = 0, olen = 16000; + unsigned char *c = output_buf; + size_t len = 0; memset(output_buf, 0, 16000); - ret = x509_write_key_der( output_buf, 16000, rsa ); - if( ret < 0 ) - return; - - len = ret; - c = output_buf + 15999 - len; - - base64_encode( base_buf, &olen, c, len ); - - c = base_buf; - - f = fopen( output_file, "w" ); - fprintf(f, "-----BEGIN RSA PRIVATE KEY-----\n"); - while (olen) + if( opt.output_format == OUTPUT_FORMAT_PEM ) { - int use_len = olen; - if (use_len > 64) use_len = 64; - fwrite( c, 1, use_len, f ); - olen -= use_len; - c += use_len; - fprintf(f, "\n"); + if( ( ret = x509write_key_pem( rsa, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); } - fprintf(f, "-----END RSA PRIVATE KEY-----\n"); + else + { + if( ( ret = x509write_key_der( rsa, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len - 1; + } + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + return( -1 ); + fclose(f); + + return( 0 ); } #define USAGE \ @@ -156,7 +161,8 @@ static void write_private_key( rsa_context *rsa, const char *output_file ) " mode=private|public default: none\n" \ " filename=%%s default: keyfile.key\n" \ " output_mode=private|public default: none\n" \ - " output_file=%%s defeult: keyfile.pem\n" \ + " output_file=%%s default: keyfile.pem\n" \ + " output_format=pem|der default: pem\n" \ "\n" int main( int argc, char *argv[] ) @@ -184,6 +190,7 @@ int main( int argc, char *argv[] ) opt.filename = DFL_FILENAME; opt.output_mode = DFL_OUTPUT_MODE; opt.output_file = DFL_OUTPUT_FILENAME; + opt.output_format = DFL_OUTPUT_FORMAT; for( i = 1; i < argc; i++ ) { @@ -210,6 +217,15 @@ int main( int argc, char *argv[] ) else goto usage; } + else if( strcmp( p, "output_format" ) == 0 ) + { + if( strcmp( q, "pem" ) == 0 ) + opt.output_format = OUTPUT_FORMAT_PEM; + else if( strcmp( q, "der" ) == 0 ) + opt.output_format = OUTPUT_FORMAT_DER; + else + goto usage; + } else if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else if( strcmp( p, "output_file" ) == 0 ) From 7accbced87fb635f90ebc58a1979351bfd1d4beb Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 17:34:53 +0200 Subject: [PATCH 18/19] Doxygen documentation added to asn1write.h --- include/polarssl/asn1write.h | 141 ++++++++++++++++++++++++++++++++++- library/asn1write.c | 4 +- 2 files changed, 142 insertions(+), 3 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 9b98afe2e..43408e29d 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -35,23 +35,162 @@ extern "C" { #endif +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ); + #if defined(POLARSSL_BIGNUM_C) +/** + * \brief Write a big number (ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ); #endif + +/** + * \brief Write a NULL tag (ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ int asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * + * \return the length written or a negative error code + */ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ); -int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, const char *algorithm_oid ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * Note: Uses NULL as algorithm parameter + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * + * \return the length written or a negative error code + */ +int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid ); + +/** + * \brief Write an int tag (ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ int asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * + * \return the length written or a negative error code + */ int asn1_write_printable_string( unsigned char **p, unsigned char *start, char *text ); + +/** + * \brief Write an IA5 string tag (ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * + * \return the length written or a negative error code + */ int asn1_write_ia5_string( unsigned char **p, unsigned char *start, char *text ); + +/** + * \brief Write a bitstring tag (ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ int asn1_write_bitstring( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ int asn1_write_octet_string( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t size ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t size ); diff --git a/library/asn1write.c b/library/asn1write.c index f08e105d2..07a3fbb4c 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -142,7 +142,7 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ) } int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *algorithm_oid ) + const char *oid ) { int ret; size_t null_len = 0; @@ -155,7 +155,7 @@ int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, // Write OID // - ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, algorithm_oid ) ); + ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) ); len = oid_len + null_len; ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) ); From 9852d00de6083b3d695b883377adc06d11218a87 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 17:56:37 +0200 Subject: [PATCH 19/19] Moved asn1write funtions to use asn1_write_raw_buffer() --- include/polarssl/asn1write.h | 29 +++++++-------- library/asn1write.c | 71 +++++++++++------------------------- 2 files changed, 36 insertions(+), 64 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 43408e29d..4659b24c1 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -59,6 +59,20 @@ int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); */ int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ); +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + #if defined(POLARSSL_BIGNUM_C) /** * \brief Write a big number (ASN1_INTEGER) in ASN.1 format @@ -179,21 +193,6 @@ int asn1_write_bitstring( unsigned char **p, unsigned char *start, */ int asn1_write_octet_string( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t size ); - -/** - * \brief Write raw buffer data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer - * - * \return the length written or a negative error code - */ -int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); - #ifdef __cplusplus } #endif diff --git a/library/asn1write.c b/library/asn1write.c index 07a3fbb4c..463c730fb 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -72,6 +72,21 @@ int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) return( 1 ); } +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p - start < (int) size ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( len ); +} + #if defined(POLARSSL_BIGNUM_C) int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ) { @@ -125,15 +140,8 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ) int ret; size_t len = 0; - // Write OID - // - len = strlen( oid ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, oid, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, strlen( oid ) ) ); ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) ); @@ -201,15 +209,8 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start, int ret; size_t len = 0; - // Write string - // - len = strlen( text ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, text, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, strlen( text ) ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) ); @@ -223,15 +224,8 @@ int asn1_write_ia5_string( unsigned char **p, unsigned char *start, int ret; size_t len = 0; - // Write string - // - len = strlen( text ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, text, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, strlen( text ) ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) ); @@ -272,32 +266,11 @@ int asn1_write_octet_string( unsigned char **p, unsigned char *start, int ret; size_t len = 0; - if( *p - start < (int) size ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, buf, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, buf, size ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); return( len ); } - -int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ) -{ - size_t len = 0; - - if( *p - start < (int) size ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, buf, len ); - - return( len ); -} - #endif