From f3df61ad10c1a88b231046e013733426cd11fc7a Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 17:22:23 +0200 Subject: [PATCH] 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 d954083954..0e443ee8c4 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 bf6483ea4a..7e04e12068 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 88cb9071c2..d9ab45c941 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 )