From 9397dcb0e8ec49f96cf4a12ed48427fc5352b863 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Fri, 6 Sep 2013 09:55:26 +0200 Subject: [PATCH 01/42] Base X509 certificate writing functinality --- include/polarssl/x509write.h | 155 +++++++++++++ library/x509write.c | 380 ++++++++++++++++++++++++++----- programs/.gitignore | 1 + programs/x509/CMakeLists.txt | 5 +- programs/x509/cert_write.c | 423 +++++++++++++++++++++++++++++++++++ 5 files changed, 908 insertions(+), 56 deletions(-) create mode 100644 programs/x509/cert_write.c diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 0e443ee8c4..8600b428f9 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -84,6 +84,31 @@ typedef struct _x509_csr } x509_csr; +#define X509_CRT_VERSION_1 0 +#define X509_CRT_VERSION_2 1 +#define X509_CRT_VERSION_3 2 + +#define X509_RFC5280_MAX_SERIAL_LEN 32 +#define X509_RFC5280_UTC_TIME_LEN 15 + +/** + * Container for writing a certificate (CRT) + */ +typedef struct _x509write_cert +{ + int version; + mpi serial; + rsa_context *subject_key; + rsa_context *issuer_key; + x509_req_name *subject; + x509_req_name *issuer; + md_type_t md_alg; + char not_before[X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[X509_RFC5280_UTC_TIME_LEN + 1]; + asn1_named_data *extensions; +} +x509write_cert; + /* \} addtogroup x509_module */ /** @@ -169,6 +194,125 @@ int x509write_csr_set_extension( x509_csr *ctx, */ void x509write_csr_free( x509_csr *ctx ); +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void x509write_crt_init( x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (X509_CRT_VERSION_1, X509_CRT_VERSION_2 or + * X509_CRT_VERSION_3) + */ +void x509write_crt_set_version( x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_validity( x509write_cert *ctx, char *not_before, + char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=NL,O=Offspark,CN=PolarSSL CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * 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 CRT 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_crt_set_subject_name( x509write_cert *ctx, char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param rsa RSA public key to include + */ +void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param rsa RSA key to sign with + */ +void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_ald MD algorithm to use + */ +void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void x509write_crt_free( x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 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 crt certificate 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_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ); + /** * \brief Write a RSA public key to a PKCS#1 DER structure * Note: data is written at the end of the buffer! Use the @@ -216,6 +360,17 @@ 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 built up certificate to a X509 PEM string + * + * \param crt certificate 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_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size ); + /** * \brief Write a RSA public key to a PKCS#1 PEM string * diff --git a/library/x509write.c b/library/x509write.c index 7e04e12068..1428c67cbf 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -45,55 +45,19 @@ #define polarssl_free free #endif -void x509write_csr_init( x509_csr *ctx ) -{ - memset( ctx, 0, sizeof(x509_csr) ); -} - -void x509write_csr_free( x509_csr *ctx ) -{ - x509_req_name *cur; - asn1_named_data *cur_ext; - - while( ( cur = ctx->subject ) != NULL ) - { - ctx->subject = cur->next; - 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) ); -} - -void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ) -{ - ctx->md_alg = md_alg; -} - -void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ) -{ - ctx->rsa = rsa; -} - -int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) +static int x509write_string_to_names( x509_req_name **head, char *name ) { int ret = 0; - char *s = subject_name, *c = s; + char *s = name, *c = s; char *end = s + strlen( s ); char *oid = NULL; int in_tag = 1; x509_req_name *cur; - while( ctx->subject ) + while( *head != NULL ) { - cur = ctx->subject; - ctx->subject = ctx->subject->next; + cur = *head; + *head = cur->next; polarssl_free( cur ); } @@ -143,8 +107,8 @@ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) memset( cur, 0, sizeof(x509_req_name) ); - cur->next = ctx->subject; - ctx->subject = cur; + cur->next = *head; + *head = cur; strncpy( cur->oid, oid, strlen( oid ) ); strncpy( cur->name, s, c - s ); @@ -160,6 +124,47 @@ exit: return( ret ); } +void x509write_csr_init( x509_csr *ctx ) +{ + memset( ctx, 0, sizeof(x509_csr) ); +} + +void x509write_csr_free( x509_csr *ctx ) +{ + x509_req_name *cur; + asn1_named_data *cur_ext; + + while( ( cur = ctx->subject ) != NULL ) + { + ctx->subject = cur->next; + 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) ); +} + +void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ) +{ + ctx->rsa = rsa; +} + +int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) +{ + return x509write_string_to_names( &ctx->subject, subject_name ); +} + int x509write_csr_set_extension( x509_csr *ctx, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len ) @@ -257,6 +262,94 @@ int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ) return( 0 ); } +void x509write_crt_init( x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof(x509write_cert) ); + + mpi_init( &ctx->serial ); + ctx->version = X509_CRT_VERSION_3; +} + +void x509write_crt_free( x509write_cert *ctx ) +{ + x509_req_name *cur; + asn1_named_data *cur_ext; + + mpi_free( &ctx->serial ); + + while( ( cur = ctx->subject ) != NULL ) + { + ctx->subject = cur->next; + polarssl_free( cur ); + } + + while( ( cur = ctx->issuer ) != NULL ) + { + ctx->issuer = cur->next; + 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) ); +} + +void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa ) +{ + ctx->subject_key = rsa; +} + +void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa ) +{ + ctx->issuer_key = rsa; +} + +int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name ) +{ + return x509write_string_to_names( &ctx->subject, subject_name ); +} + +int x509write_crt_set_issuer_name( x509write_cert *ctx, char *issuer_name ) +{ + return x509write_string_to_names( &ctx->issuer, issuer_name ); +} + +int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial ) +{ + int ret; + + if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_crt_set_validity( x509write_cert *ctx, char *not_before, + char *not_after ) +{ + if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 || + strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; @@ -344,6 +437,18 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) return( len ); } +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ static int x509_write_name( unsigned char **p, unsigned char *start, char *oid, char *name ) { @@ -376,6 +481,25 @@ static int x509_write_name( unsigned char **p, unsigned char *start, char *oid, return( len ); } +static int x509_write_names( unsigned char **p, unsigned char *start, + x509_req_name *first ) +{ + int ret; + size_t len = 0; + x509_req_name *cur = first; + + while( cur != NULL ) + { + ASN1_CHK_ADD( len, x509_write_name( p, start, cur->oid, cur->name ) ); + cur = cur->next; + } + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return( len ); +} + static int x509_write_sig( unsigned char **p, unsigned char *start, const char *oid, unsigned char *sig, size_t size ) { @@ -402,6 +526,21 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, return( len ); } +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *time, size_t size ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time, + size ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) ); + + return( len ); +} + int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) { int ret; @@ -410,9 +549,8 @@ 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 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; @@ -482,16 +620,10 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - while( cur != NULL ) - { - ASN1_CHK_ADD( sub_len, x509_write_name( &c, tmp_buf, cur->oid, cur->name ) ); - - cur = cur->next; - } - - len += sub_len; - 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 ) ); + /* + * Subject ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } @@ -522,6 +654,123 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) return( len ); } +int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) +{ + int ret; + const char *sig_oid; + unsigned char *c, *c2; + 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 len = 0; + asn1_named_data *cur_ext = ctx->extensions; + + c = tmp_buf + 2048 - 1; + + // Generate correct OID + // + ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid ); + if( ret != 0 ) + return( ret ); + + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) ); + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->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 ) ); + + if( c - tmp_buf < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--c = 0; + pub_len += 1; + + 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_BIT_STRING ) ); + + ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) ); + + len += pub_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + /* + * Subject ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, + X509_RFC5280_UTC_TIME_LEN ) ); + + ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, + X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + 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 ) ); + + /* + * Issuer ::= Name + */ + ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, + sig_oid ) ); + + /* + * Serial ::= INTEGER + */ + ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + sub_len = 0; + ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) ); + len += sub_len; + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 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( ctx->md_alg ), c, len, hash ); + + rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); + + c2 = buf + size - 1; + ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) ); + + c2 -= len; + memcpy( c2, c, len ); + + len += sig_len; + ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return( len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" @@ -571,6 +820,27 @@ static int x509write_pemify( const char *begin_str, const char *end_str, return( 0 ); } +int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_crt_der( crt, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; diff --git a/programs/.gitignore b/programs/.gitignore index 2b7510f6e0..b349cd44cc 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -40,3 +40,4 @@ util/strerror x509/cert_app x509/cert_req x509/crl_app +x509/cert_write diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt index d07cff82d7..8aaa4ac24e 100644 --- a/programs/x509/CMakeLists.txt +++ b/programs/x509/CMakeLists.txt @@ -19,6 +19,9 @@ target_link_libraries(crl_app ${libs}) add_executable(cert_req cert_req.c) target_link_libraries(cert_req ${libs}) -install(TARGETS cert_app crl_app cert_req +add_executable(cert_write cert_write.c) +target_link_libraries(cert_write ${libs}) + +install(TARGETS cert_app crl_app cert_req cert_write DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c new file mode 100644 index 0000000000..59c49b2fe3 --- /dev/null +++ b/programs/x509/cert_write.c @@ -0,0 +1,423 @@ +/* + * Certificate generation and signing + * + * 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/rsa.h" +#include "polarssl/x509.h" +#include "polarssl/base64.h" +#include "polarssl/x509write.h" +#include "polarssl/oid.h" + +#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " + "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else + +#define DFL_SUBJECT_KEY "subject.key" +#define DFL_ISSUER_KEY "ca.key" +#define DFL_SUBJECT_PWD "" +#define DFL_ISSUER_PWD "" +#define DFL_OUTPUT_FILENAME "cert.crt" +#define DFL_SUBJECT_NAME "CN=Cert,O=PolarSSL,C=NL" +#define DFL_ISSUER_NAME "CN=CA,O=PolarSSL,C=NL" +#define DFL_NOT_BEFORE "20010101000000" +#define DFL_NOT_AFTER "20301231235959" +#define DFL_SERIAL "1" +#define DFL_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 + +/* + * global options + */ +struct options +{ + char *subject_key; /* filename of the subject key file */ + char *issuer_key; /* filename of the issuer key file */ + char *subject_pwd; /* password for the subject key file */ + char *issuer_pwd; /* password for the issuer key file */ + char *output_file; /* where to store the constructed key file */ + char *subject_name; /* subject name for certificate */ + char *issuer_name; /* issuer name for certificate */ + char *not_before; /* validity period not before */ + char *not_after; /* validity period not after */ + char *serial; /* serial number string */ + unsigned char key_usage; /* key usage flags */ + unsigned char ns_cert_type; /* NS cert type */ +} opt; + +int write_certificate( x509write_cert *crt, char *output_file ) +{ + int ret; + FILE *f; + unsigned char output_buf[4096]; + size_t len = 0; + + memset( output_buf, 0, 4096 ); + if( ( ret = x509write_crt_pem( crt, output_buf, 4096 ) ) < 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( output_buf, 1, len, f ) != len ) + return( -1 ); + + fclose(f); + + return( 0 ); +} + +#define USAGE \ + "\n usage: cert_write param=<>...\n" \ + "\n acceptable parameters:\n" \ + " subject_key=%%s default: subject.key\n" \ + " subject_pwd=%%s default: (empty)\n" \ + " issuer_key=%%s default: ca.key\n" \ + " issuer_pwd=%%s default: (empty)\n" \ + " output_file=%%s default: cert.crt\n" \ + " subject_name=%%s default: CN=Cert,O=PolarSSL,C=NL\n" \ + " issuer_name=%%s default: CN=CA,O=PolarSSL,C=NL\n" \ + " serial=%%s default: 1\n" \ + " not_before=%%s default: 20010101000000\n"\ + " not_after=%%s default: 20301231235959\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" + +int main( int argc, char *argv[] ) +{ + int ret = 0; + rsa_context issuer_rsa, subject_rsa; + char buf[1024]; + int i, j, n; + char *p, *q, *r; + x509write_cert crt; + mpi serial; + + /* + * Set to sane values + */ + x509write_crt_init( &crt ); + x509write_crt_set_md_alg( &crt, POLARSSL_MD_SHA1 ); + rsa_init( &issuer_rsa, RSA_PKCS_V15, 0 ); + rsa_init( &subject_rsa, RSA_PKCS_V15, 0 ); + mpi_init( &serial ); + memset( buf, 0, 1024 ); + + if( argc == 0 ) + { + usage: + printf( USAGE ); + ret = 1; + goto exit; + } + + opt.subject_key = DFL_SUBJECT_KEY; + opt.issuer_key = DFL_ISSUER_KEY; + opt.subject_pwd = DFL_SUBJECT_PWD; + opt.issuer_pwd = DFL_ISSUER_PWD; + opt.output_file = DFL_OUTPUT_FILENAME; + opt.subject_name = DFL_SUBJECT_NAME; + opt.issuer_name = DFL_ISSUER_NAME; + opt.not_before = DFL_NOT_BEFORE; + opt.not_after = DFL_NOT_AFTER; + opt.serial = DFL_SERIAL; + opt.key_usage = DFL_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; + + 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, "subject_key" ) == 0 ) + opt.subject_key = q; + else if( strcmp( p, "issuer_key" ) == 0 ) + opt.issuer_key = q; + else if( strcmp( p, "subject_pwd" ) == 0 ) + opt.subject_pwd = q; + else if( strcmp( p, "issuer_pwd" ) == 0 ) + opt.issuer_pwd = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else if( strcmp( p, "subject_name" ) == 0 ) + { + opt.subject_name = q; + } + else if( strcmp( p, "issuer_name" ) == 0 ) + { + opt.issuer_name = q; + } + else if( strcmp( p, "not_before" ) == 0 ) + { + opt.not_before = q; + } + else if( strcmp( p, "not_after" ) == 0 ) + { + opt.not_after = q; + } + else if( strcmp( p, "serial" ) == 0 ) + { + opt.serial = 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; + } + + // Parse serial to MPI + // + if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! mpi_read_string returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + +/* + 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 names for validity + */ + if( ( ret = x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + if( ( ret = x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + /* + * 1.1. Load the keys + */ + printf( "\n . Loading the subject key ..." ); + fflush( stdout ); + + ret = x509parse_keyfile_rsa( &subject_rsa, opt.subject_key, opt.subject_pwd ); + + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + x509write_crt_set_subject_key( &crt, &subject_rsa ); + + printf( " ok\n" ); + + printf( " . Loading the issuer key ..." ); + fflush( stdout ); + + ret = x509parse_keyfile_rsa( &issuer_rsa, opt.issuer_key, opt.issuer_pwd ); + + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509parse_keyfile_rsa returned -x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + x509write_crt_set_issuer_key( &crt, &issuer_rsa ); + + printf( " ok\n" ); + + printf( " . Setting certificate values ..." ); + fflush( stdout ); + + ret = x509write_crt_set_serial( &crt, &serial ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 1.2. Writing the request + */ + printf( " . Writing the certificate..." ); + fflush( stdout ); + + if( ( ret = write_certificate( &crt, opt.output_file ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + +exit: + x509write_crt_free( &crt ); + rsa_free( &subject_rsa ); + rsa_free( &issuer_rsa ); + mpi_free( &serial ); + +#if defined(_WIN32) + printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && + POLARSSet_serial_X509_WRITE_C && POLARSSL_FS_IO */ From 329def30c5f62f362150abdc8672426cd5db106c Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Fri, 6 Sep 2013 16:34:38 +0200 Subject: [PATCH 02/42] Added asn1_write_bool() --- include/polarssl/asn1write.h | 12 ++++++++++++ library/asn1write.c | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 4659b24c12..808bf3abe6 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -124,6 +124,18 @@ 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 *oid ); +/** + * \brief Write a boolean tag (ASN1_BOOLEAN) 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 boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + /** * \brief Write an int tag (ASN1_INTEGER) and value in ASN.1 format * Note: function works backwards in data buffer diff --git a/library/asn1write.c b/library/asn1write.c index 463c730fba..893841f804 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -173,6 +173,23 @@ int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, return( len ); } +int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 1 : 0; + len++; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BOOLEAN ) ); + + return( len ); +} + int asn1_write_int( unsigned char **p, unsigned char *start, int val ) { int ret; From 15162a054a3296636aeceb54a68a8bfbae1f950e Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Fri, 6 Sep 2013 19:27:21 +0200 Subject: [PATCH 03/42] Writing of X509v3 extensions supported Standard extensions already in: basicConstraints, subjectKeyIdentifier and authorityKeyIdentifier --- include/polarssl/x509write.h | 54 ++++++++ library/x509write.c | 244 ++++++++++++++++++++++++++++------- programs/x509/cert_write.c | 66 ++++++++++ 3 files changed, 317 insertions(+), 47 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 8600b428f9..af4d2a12d5 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -291,6 +291,60 @@ void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa ); */ void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ); +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \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_crt_set_extension( x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_basic_constraints( x509write_cert *ctx, + int is_ca, int max_pathlen ); + +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ); + /** * \brief Free the contents of a CRT write context * diff --git a/library/x509write.c b/library/x509write.c index 1428c67cbf..c2af143396 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -33,6 +33,8 @@ #include "polarssl/md.h" #include "polarssl/oid.h" +#include "polarssl/sha1.h" + #if defined(POLARSSL_BASE64_C) #include "polarssl/base64.h" #endif @@ -124,6 +126,27 @@ exit: return( ret ); } +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start, + rsa_context *rsa ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->E ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( p, start, &rsa->N ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return( len ); +} + void x509write_csr_init( x509_csr *ctx ) { memset( ctx, 0, sizeof(x509_csr) ); @@ -165,14 +188,17 @@ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) return x509write_string_to_names( &ctx->subject, subject_name ); } -int x509write_csr_set_extension( x509_csr *ctx, - const char *oid, size_t oid_len, - const unsigned char *val, size_t val_len ) +/* The first byte of the value in the asn1_named_data structure is reserved + * to store the critical boolean for us + */ +static int x509_set_extension( asn1_named_data **head, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) { asn1_named_data *cur; - if( ( cur = asn1_find_named_data( ctx->extensions, oid, - oid_len ) ) == NULL ) + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) { cur = polarssl_malloc( sizeof(asn1_named_data) ); if( cur == NULL ) @@ -188,8 +214,8 @@ int x509write_csr_set_extension( x509_csr *ctx, return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } - cur->val.len = val_len; - cur->val.p = polarssl_malloc( val_len ); + cur->val.len = val_len + 1; + cur->val.p = polarssl_malloc( val_len + 1 ); if( cur->val.p == NULL ) { polarssl_free( cur->oid.p ); @@ -199,16 +225,16 @@ int x509write_csr_set_extension( x509_csr *ctx, memcpy( cur->oid.p, oid, oid_len ); - cur->next = ctx->extensions; - ctx->extensions = cur; + cur->next = *head; + *head = cur; } - if( cur->val.len != val_len ) + if( cur->val.len != val_len + 1 ) { polarssl_free( cur->val.p ); - cur->val.len = val_len; - cur->val.p = polarssl_malloc( val_len ); + cur->val.len = val_len + 1; + cur->val.p = polarssl_malloc( val_len + 1); if( cur->val.p == NULL ) { polarssl_free( cur->oid.p ); @@ -217,11 +243,20 @@ int x509write_csr_set_extension( x509_csr *ctx, } } - memcpy( cur->val.p, val, val_len ); + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); return( 0 ); } +int x509write_csr_set_extension( x509_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) { unsigned char buf[4]; @@ -350,6 +385,92 @@ int x509write_crt_set_validity( x509write_cert *ctx, char *not_before, return( 0 ); } +int x509write_crt_set_extension( x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ); +} + +int x509write_crt_set_basic_constraints( x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) ); + } + ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) ); + } + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS, + OID_SIZE( OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ); +} + +int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf)); + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) ); + + sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) ); + + return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER, + OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) +{ + int ret; + unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf)); + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) ); + + sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); + c = buf + sizeof(buf) - 20; + len = 20; + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER, + OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; @@ -358,17 +479,7 @@ int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) 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 ) ); - - ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) ); if( c - buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); @@ -541,6 +652,59 @@ static int x509_write_time( unsigned char **p, unsigned char *start, return( len ); } +static int x509_write_extension( unsigned char **p, unsigned char *start, + asn1_named_data *ext ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->val.len - 1 ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + ASN1_CHK_ADD( len, asn1_write_bool( p, start, 1 ) ); + } + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, ext->oid.len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OID ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + return( len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +static int x509_write_extensions( unsigned char **p, unsigned char *start, + asn1_named_data *first ) +{ + int ret; + size_t len = 0; + asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( len ); +} + int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) { int ret; @@ -551,31 +715,10 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_len = 0; size_t len = 0; - asn1_named_data *cur_ext = ctx->extensions; c = tmp_buf + 2048 - 1; - while( cur_ext != NULL ) - { - 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_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; - } + ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); if( len ) { @@ -664,7 +807,6 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) unsigned char tmp_buf[2048]; size_t sub_len = 0, pub_len = 0, sig_len = 0; size_t len = 0; - asn1_named_data *cur_ext = ctx->extensions; c = tmp_buf + 2048 - 1; @@ -674,6 +816,14 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) if( ret != 0 ) return( ret ); + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + 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( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ); /* * SubjectPublicKeyInfo ::= SEQUENCE { diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 59c49b2fe3..7a811d49f5 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -63,6 +63,8 @@ int main( int argc, char *argv[] ) #define DFL_NOT_BEFORE "20010101000000" #define DFL_NOT_AFTER "20301231235959" #define DFL_SERIAL "1" +#define DFL_IS_CA 0 +#define DFL_MAX_PATHLEN -1 #define DFL_KEY_USAGE 0 #define DFL_NS_CERT_TYPE 0 @@ -81,6 +83,8 @@ struct options char *not_before; /* validity period not before */ char *not_after; /* validity period not after */ char *serial; /* serial number string */ + int is_ca; /* is a CA certificate */ + int max_pathlen; /* maximum CA path length */ unsigned char key_usage; /* key usage flags */ unsigned char ns_cert_type; /* NS cert type */ } opt; @@ -122,6 +126,8 @@ int write_certificate( x509write_cert *crt, char *output_file ) " serial=%%s default: 1\n" \ " not_before=%%s default: 20010101000000\n"\ " not_after=%%s default: 20301231235959\n"\ + " is_ca=%%d default: 0 (disabled)\n" \ + " max_pathlen=%%d default: -1 (none)\n" \ " key_usage=%%s default: (empty)\n" \ " Comma-separated-list of values:\n" \ " digital_signature\n" \ @@ -180,6 +186,8 @@ int main( int argc, char *argv[] ) opt.not_before = DFL_NOT_BEFORE; opt.not_after = DFL_NOT_AFTER; opt.serial = DFL_SERIAL; + opt.is_ca = DFL_IS_CA; + opt.max_pathlen = DFL_MAX_PATHLEN; opt.key_usage = DFL_KEY_USAGE; opt.ns_cert_type = DFL_NS_CERT_TYPE; @@ -228,6 +236,18 @@ int main( int argc, char *argv[] ) { opt.serial = q; } + else if( strcmp( p, "is_ca" ) == 0 ) + { + opt.is_ca = atoi( q ); + if( opt.is_ca < 0 || opt.is_ca > 1 ) + goto usage; + } + else if( strcmp( p, "max_pathlen" ) == 0 ) + { + opt.max_pathlen = atoi( q ); + if( opt.max_pathlen < -1 || opt.max_pathlen > 127 ) + goto usage; + } else if( strcmp( p, "key_usage" ) == 0 ) { while( q != NULL ) @@ -389,6 +409,52 @@ int main( int argc, char *argv[] ) printf( " ok\n" ); + printf( " . Adding the Basic Constraints extension ..." ); + fflush( stdout ); + + ret = x509write_crt_set_basic_constraints( &crt, opt.is_ca, + opt.max_pathlen ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + printf( " . Adding the Subject Key Identifier ..." ); + fflush( stdout ); + + ret = x509write_crt_set_subject_key_identifier( &crt ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + printf( " . Adding the Authority Key Identifier ..." ); + fflush( stdout ); + + ret = x509write_crt_set_authority_key_identifier( &crt ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + /* * 1.2. Writing the request */ From 9c208aabc83262515aa4c9a529e09969907f912d Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 8 Sep 2013 15:44:31 +0200 Subject: [PATCH 04/42] Use ASN1_UTC_TIME in some cases --- library/x509write.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index c2af143396..d025abb05f 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -643,11 +643,25 @@ static int x509_write_time( unsigned char **p, unsigned char *start, int ret; size_t len = 0; - ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, - (const unsigned char *) time, - size ) ); - ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) ); + /* + * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) + { + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time + 2, + size - 2 ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) ); + } + else + { + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) time, + size ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) ); + } return( len ); } From 2397cf3ede7d14be50fefe3f6fa9fa7789c36174 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Sun, 8 Sep 2013 15:58:15 +0200 Subject: [PATCH 05/42] First certificate writing test. Full server1.crt reconstruction --- tests/suites/test_suite_x509write.data | 4 ++ tests/suites/test_suite_x509write.function | 66 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 7490b7c171..1be6c84b73 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -25,3 +25,7 @@ x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD4:"data_files/server1.req. Certificate Request check Server1 MD5 depends_on:POLARSSL_MD5_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15 x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req.md5" + +Certificate write check Server1 SHA1 +depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15 +x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:"data_files/server1.crt" diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index d3c801a1d3..10338aa715 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -57,3 +57,69 @@ void x509_csr_check( char *key_file, int md_type, pem_free( &pem ); } /* END_CASE */ + +/* BEGIN_CASE */ +void x509_crt_check( char *subject_key_file, char *subject_pwd, + char *subject_name, char *issuer_key_file, + char *issuer_pwd, char *issuer_name, + char *serial_str, char *not_before, char *not_after, + int md_type, char *cert_check_file ) +{ + rsa_context subject_rsa, issuer_rsa; + pem_context pem; + x509write_cert crt; + unsigned char *c; + unsigned char buf[4000]; + unsigned char check_buf[5000]; + mpi serial; + int ret; + size_t olen = 2000; + FILE *f; + + mpi_init( &serial ); + rsa_init( &subject_rsa, RSA_PKCS_V15, 0 ); + rsa_init( &issuer_rsa, RSA_PKCS_V15, 0 ); + + TEST_ASSERT( x509parse_keyfile_rsa( &subject_rsa, subject_key_file, + subject_pwd ) == 0 ); + TEST_ASSERT( x509parse_keyfile_rsa( &issuer_rsa, issuer_key_file, + issuer_pwd ) == 0 ); + TEST_ASSERT( mpi_read_string( &serial, 10, serial_str ) == 0 ); + + x509write_crt_init( &crt ); + x509write_crt_set_serial( &crt, &serial ); + TEST_ASSERT( x509write_crt_set_validity( &crt, not_before, + not_after ) == 0 ); + x509write_crt_set_md_alg( &crt, md_type ); + TEST_ASSERT( x509write_crt_set_issuer_name( &crt, issuer_name ) == 0 ); + TEST_ASSERT( x509write_crt_set_subject_name( &crt, subject_name ) == 0 ); + x509write_crt_set_subject_key( &crt, &subject_rsa ); + x509write_crt_set_issuer_key( &crt, &issuer_rsa ); + + TEST_ASSERT( x509write_crt_set_basic_constraints( &crt, 0, 0 ) == 0 ); + TEST_ASSERT( x509write_crt_set_subject_key_identifier( &crt ) == 0 ); + TEST_ASSERT( x509write_crt_set_authority_key_identifier( &crt ) == 0 ); + + ret = x509write_crt_der( &crt, buf, sizeof(buf) ); + TEST_ASSERT( ret >= 0 ); + + c = buf + 3999 - ret; + + f = fopen( cert_check_file, "r" ); + TEST_ASSERT( f != NULL ); + TEST_ASSERT( fread( check_buf, 1, sizeof(check_buf), f ) < sizeof(check_buf) ); + fclose( f ); + + pem_init( &pem ); + TEST_ASSERT( pem_read_buffer( &pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----", check_buf, NULL, 0, &olen ) >= 0 ); + + TEST_ASSERT( pem.buflen == (size_t) ret ); + TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); + + x509write_crt_free( &crt ); + rsa_free( &issuer_rsa ); + rsa_free( &subject_rsa ); + pem_free( &pem ); + mpi_free( &serial ); +} +/* END_CASE */ From 59ba59fa30ab90390d0b857c98884177bef16dbc Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 11:26:00 +0200 Subject: [PATCH 06/42] Generalized x509_set_extension() behaviour to asn1_store_named_data() --- include/polarssl/asn1write.h | 22 ++++++++++++ library/asn1write.c | 69 ++++++++++++++++++++++++++++++++++++ library/x509write.c | 45 ++--------------------- 3 files changed, 94 insertions(+), 42 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 808bf3abe6..d65ff79be5 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -205,6 +205,28 @@ 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 Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +asn1_named_data *asn1_store_named_data( asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + #ifdef __cplusplus } #endif diff --git a/library/asn1write.c b/library/asn1write.c index 893841f804..302acc33c8 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -29,6 +29,14 @@ #include "polarssl/asn1write.h" +#if defined(POLARSSL_MEMORY_C) +#include "polarssl/memory.h" +#else +#include +#define polarssl_malloc malloc +#define polarssl_free free +#endif + int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) { if( len < 0x80 ) @@ -290,4 +298,65 @@ int asn1_write_octet_string( unsigned char **p, unsigned char *start, return( len ); } + +asn1_named_data *asn1_store_named_data( asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + if( ( cur = polarssl_malloc( sizeof(asn1_named_data) ) ) == NULL ) + return( NULL ); + + memset( cur, 0, sizeof(asn1_named_data) ); + + cur->oid.len = oid_len; + cur->oid.p = polarssl_malloc( oid_len ); + if( cur->oid.p == NULL ) + { + polarssl_free( cur ); + return( NULL ); + } + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + // Enlarge existing value buffer if needed + // + polarssl_free( cur->val.p ); + cur->val.p = NULL; + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( NULL ); + } + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} #endif diff --git a/library/x509write.c b/library/x509write.c index d025abb05f..8966ecb737 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -198,49 +198,10 @@ static int x509_set_extension( asn1_named_data **head, { asn1_named_data *cur; - if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + if( ( cur = asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == 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_len; - cur->oid.p = polarssl_malloc( oid_len ); - if( cur->oid.p == NULL ) - { - polarssl_free( cur ); - return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); - } - - cur->val.len = val_len + 1; - cur->val.p = polarssl_malloc( val_len + 1 ); - if( cur->val.p == NULL ) - { - polarssl_free( cur->oid.p ); - polarssl_free( cur ); - return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); - } - - memcpy( cur->oid.p, oid, oid_len ); - - cur->next = *head; - *head = cur; - } - - if( cur->val.len != val_len + 1 ) - { - polarssl_free( cur->val.p ); - - cur->val.len = val_len + 1; - cur->val.p = polarssl_malloc( val_len + 1); - if( cur->val.p == NULL ) - { - polarssl_free( cur->oid.p ); - polarssl_free( cur ); - return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); - } + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } cur->val.p[0] = critical; From c547cc992eec438bd3c877bba5d2cba50228d0e8 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 12:01:23 +0200 Subject: [PATCH 07/42] Added generic asn1_free_named_data_list() --- include/polarssl/asn1.h | 8 ++++++++ library/asn1parse.c | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index ec8cbfafc8..86a1bc8c14 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -319,6 +319,14 @@ asn1_named_data *asn1_find_named_data( asn1_named_data *list, */ void asn1_free_named_data( asn1_named_data *entry ); +/** + * Free all entries in a asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void asn1_free_named_data_list( asn1_named_data **head ); + #ifdef __cplusplus } #endif diff --git a/library/asn1parse.c b/library/asn1parse.c index f6b271ec52..957359917f 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -354,6 +354,18 @@ void asn1_free_named_data( asn1_named_data *cur ) memset( cur, 0, sizeof( asn1_named_data ) ); } +void asn1_free_named_data_list( asn1_named_data **head ) +{ + asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + asn1_free_named_data( cur ); + polarssl_free( cur ); + } +} + asn1_named_data *asn1_find_named_data( asn1_named_data *list, const char *oid, size_t len ) { From 5f45e62afe99022e477203bacdb9d667c81c610a Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 12:02:36 +0200 Subject: [PATCH 08/42] Migrated from x509_req_name to asn1_named_data structure --- include/polarssl/asn1write.h | 13 ++-- include/polarssl/x509write.h | 18 +----- library/asn1write.c | 25 ++++---- library/x509write.c | 121 +++++++++++++---------------------- 4 files changed, 67 insertions(+), 110 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index d65ff79be5..6116502041 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -105,10 +105,12 @@ int asn1_write_null( unsigned char **p, unsigned char *start ); * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) * \param oid the OID to write + * \param oid_len length of the OID * * \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_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); /** * \brief Write an AlgorithmIdentifier sequence in ASN.1 format @@ -118,11 +120,12 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ); * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) * \param oid the OID of the algorithm + * \param oid_len length of the OID * * \return the length written or a negative error code */ int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid ); + const char *oid, size_t oid_len ); /** * \brief Write a boolean tag (ASN1_BOOLEAN) and value in ASN.1 format @@ -156,11 +159,12 @@ int asn1_write_int( unsigned char **p, unsigned char *start, int val ); * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) * \param text the text to write + * \param text_len length of the text * * \return the length written or a negative error code */ int asn1_write_printable_string( unsigned char **p, unsigned char *start, - char *text ); + const char *text, size_t text_len ); /** * \brief Write an IA5 string tag (ASN1_IA5_STRING) and @@ -170,11 +174,12 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start, * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) * \param text the text to write + * \param text_len length of the text * * \return the length written or a negative error code */ int asn1_write_ia5_string( unsigned char **p, unsigned char *start, - char *text ); + const char *text, size_t text_len ); /** * \brief Write a bitstring tag (ASN1_BIT_STRING) and diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index af4d2a12d5..2e6fa0c7db 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -60,25 +60,13 @@ extern "C" { * \{ */ -/** - * Container for CSR named objects - */ -typedef struct _x509_req_name -{ - char oid[128]; - char name[128]; - - struct _x509_req_name *next; -} -x509_req_name; - /** * Container for a CSR */ typedef struct _x509_csr { rsa_context *rsa; - x509_req_name *subject; + asn1_named_data *subject; md_type_t md_alg; asn1_named_data *extensions; } @@ -100,8 +88,8 @@ typedef struct _x509write_cert mpi serial; rsa_context *subject_key; rsa_context *issuer_key; - x509_req_name *subject; - x509_req_name *issuer; + asn1_named_data *subject; + asn1_named_data *issuer; md_type_t md_alg; char not_before[X509_RFC5280_UTC_TIME_LEN + 1]; char not_after[X509_RFC5280_UTC_TIME_LEN + 1]; diff --git a/library/asn1write.c b/library/asn1write.c index 302acc33c8..f720a80673 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -143,14 +143,14 @@ int asn1_write_null( unsigned char **p, unsigned char *start ) return( len ); } -int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ) +int asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) { int ret; size_t len = 0; ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, - (const unsigned char *) oid, strlen( oid ) ) ); - + (const unsigned char *) oid, oid_len ) ); ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) ); @@ -158,23 +158,20 @@ 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 *oid ) + const char *oid, size_t oid_len ) { int ret; - size_t null_len = 0; - size_t oid_len = 0; size_t len = 0; // Write NULL // - ASN1_CHK_ADD( null_len, asn1_write_null( p, start ) ); + ASN1_CHK_ADD( len, asn1_write_null( p, start ) ); // Write OID // - ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) ); + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); - len = oid_len + null_len; - ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); @@ -229,13 +226,13 @@ int asn1_write_int( unsigned char **p, unsigned char *start, int val ) } int asn1_write_printable_string( unsigned char **p, unsigned char *start, - char *text ) + const char *text, size_t text_len ) { int ret; size_t len = 0; ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, - (const unsigned char *) text, strlen( text ) ) ); + (const unsigned char *) text, text_len ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) ); @@ -244,13 +241,13 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start, } int asn1_write_ia5_string( unsigned char **p, unsigned char *start, - char *text ) + const char *text, size_t text_len ) { int ret; size_t len = 0; ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, - (const unsigned char *) text, strlen( text ) ) ); + (const unsigned char *) text, text_len ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) ); diff --git a/library/x509write.c b/library/x509write.c index 8966ecb737..5d5d3de008 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -47,15 +47,17 @@ #define polarssl_free free #endif -static int x509write_string_to_names( x509_req_name **head, char *name ) +static int x509write_string_to_names( asn1_named_data **head, char *name ) { int ret = 0; char *s = name, *c = s; char *end = s + strlen( s ); char *oid = NULL; int in_tag = 1; - x509_req_name *cur; + asn1_named_data *cur; + // Clear existing chain if present + // while( *head != NULL ) { cur = *head; @@ -93,28 +95,13 @@ static int x509write_string_to_names( x509_req_name **head, char *name ) if( !in_tag && ( *c == ',' || c == end ) ) { - if( c - s > 127 ) + if( ( cur = asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) s, + c - s ) ) == NULL ) { - ret = POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA; - goto exit; + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } - cur = polarssl_malloc( sizeof(x509_req_name) ); - - if( cur == NULL ) - { - ret = POLARSSL_ERR_X509WRITE_MALLOC_FAILED; - goto exit; - } - - memset( cur, 0, sizeof(x509_req_name) ); - - cur->next = *head; - *head = cur; - - strncpy( cur->oid, oid, strlen( oid ) ); - strncpy( cur->name, s, c - s ); - s = c + 1; in_tag = 1; } @@ -154,21 +141,8 @@ 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 ) - { - ctx->subject = cur->next; - polarssl_free( cur ); - } - - while( ( cur_ext = ctx->extensions ) != NULL ) - { - ctx->extensions = cur_ext->next; - asn1_free_named_data( cur_ext ); - polarssl_free( cur_ext ); - } + asn1_free_named_data_list( &ctx->subject ); + asn1_free_named_data_list( &ctx->extensions ); memset( ctx, 0, sizeof(x509_csr) ); } @@ -268,29 +242,11 @@ void x509write_crt_init( x509write_cert *ctx ) void x509write_crt_free( x509write_cert *ctx ) { - x509_req_name *cur; - asn1_named_data *cur_ext; - mpi_free( &ctx->serial ); - while( ( cur = ctx->subject ) != NULL ) - { - ctx->subject = cur->next; - polarssl_free( cur ); - } - - while( ( cur = ctx->issuer ) != NULL ) - { - ctx->issuer = cur->next; - polarssl_free( cur ); - } - - while( ( cur_ext = ctx->extensions ) != NULL ) - { - ctx->extensions = cur_ext->next; - asn1_free_named_data( cur_ext ); - polarssl_free( cur_ext ); - } + asn1_free_named_data_list( &ctx->subject ); + asn1_free_named_data_list( &ctx->issuer ); + asn1_free_named_data_list( &ctx->extensions ); memset( ctx, 0, sizeof(x509_csr) ); } @@ -456,7 +412,8 @@ int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA ) ); + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, + OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); @@ -521,30 +478,34 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) * * AttributeValue ::= ANY DEFINED BY AttributeType */ -static int x509_write_name( unsigned char **p, unsigned char *start, char *oid, - char *name ) +static int x509_write_name( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + const unsigned char *name, size_t name_len ) { int ret; - size_t string_len = 0; - size_t oid_len = 0; size_t len = 0; // Write PrintableString for all except OID_PKCS9_EMAIL // - if( OID_SIZE( OID_PKCS9_EMAIL ) == strlen( oid ) && - memcmp( oid, OID_PKCS9_EMAIL, strlen( oid ) ) == 0 ) + if( OID_SIZE( OID_PKCS9_EMAIL ) == oid_len && + memcmp( oid, OID_PKCS9_EMAIL, oid_len ) == 0 ) { - ASN1_CHK_ADD( string_len, asn1_write_ia5_string( p, start, name ) ); + ASN1_CHK_ADD( len, asn1_write_ia5_string( p, start, + (const char *) name, + name_len ) ); } else - ASN1_CHK_ADD( string_len, asn1_write_printable_string( p, start, name ) ); + { + ASN1_CHK_ADD( len, asn1_write_printable_string( p, start, + (const char *) name, + name_len ) ); + } // Write OID // - ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) ); + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); - len = oid_len + string_len; - ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + string_len ) ); + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); @@ -554,15 +515,17 @@ static int x509_write_name( unsigned char **p, unsigned char *start, char *oid, } static int x509_write_names( unsigned char **p, unsigned char *start, - x509_req_name *first ) + asn1_named_data *first ) { int ret; size_t len = 0; - x509_req_name *cur = first; + asn1_named_data *cur = first; while( cur != NULL ) { - ASN1_CHK_ADD( len, x509_write_name( p, start, cur->oid, cur->name ) ); + ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, + cur->oid.len, + cur->val.p, cur->val.len ) ); cur = cur->next; } @@ -593,7 +556,8 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, // Write OID // - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid ) ); + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid, + strlen( oid ) ) ); return( len ); } @@ -703,7 +667,8 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) 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( 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, + OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); 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 ) ); @@ -732,7 +697,8 @@ int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) 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_BIT_STRING ) ); - ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) ); + ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, + OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); len += pub_len; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); @@ -820,7 +786,8 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) 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_BIT_STRING ) ); - ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, OID_PKCS1_RSA ) ); + ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, + OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); len += pub_len; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); @@ -857,7 +824,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) * Signature ::= AlgorithmIdentifier */ ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, - sig_oid ) ); + sig_oid, strlen( sig_oid ) ) ); /* * Serial ::= INTEGER From cd358036847b50c39f1689c9f44a17f74ac9e17e Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 12:08:11 +0200 Subject: [PATCH 09/42] Changes x509_csr to x509write_csr --- include/polarssl/x509write.h | 25 ++++++++++---------- library/x509write.c | 27 +++++++++++----------- programs/x509/cert_req.c | 4 ++-- tests/suites/test_suite_x509write.function | 2 +- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 2e6fa0c7db..ece231965a 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -63,14 +63,14 @@ extern "C" { /** * Container for a CSR */ -typedef struct _x509_csr +typedef struct _x509write_csr { rsa_context *rsa; asn1_named_data *subject; md_type_t md_alg; asn1_named_data *extensions; } -x509_csr; +x509write_csr; #define X509_CRT_VERSION_1 0 #define X509_CRT_VERSION_2 1 @@ -104,7 +104,7 @@ x509write_cert; * * \param ctx CSR context to initialize */ -void x509write_csr_init( x509_csr *ctx ); +void x509write_csr_init( x509write_csr *ctx ); /** * \brief Set the subject name for a CSR @@ -118,7 +118,7 @@ void x509write_csr_init( x509_csr *ctx ); * \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 ); +int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name ); /** * \brief Set the RSA key for a CSR (public key will be included, @@ -127,7 +127,7 @@ int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ); * \param ctx CSR context to use * \param rsa RSA key to include */ -void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ); +void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa ); /** * \brief Set the MD algorithm to use for the signature @@ -136,7 +136,7 @@ void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ); * \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 ); +void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ); /** * \brief Set the Key Usage Extension flags @@ -147,7 +147,7 @@ void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); * * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED */ -int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); +int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ); /** * \brief Set the Netscape Cert Type flags @@ -158,7 +158,8 @@ int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); * * \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 ); +int x509write_csr_set_ns_cert_type( x509write_csr *ctx, + unsigned char ns_cert_type ); /** * \brief Generic function to add to or replace an extension in the CSR @@ -171,7 +172,7 @@ int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ); * * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED */ -int x509write_csr_set_extension( x509_csr *ctx, +int x509write_csr_set_extension( x509write_csr *ctx, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len ); @@ -180,7 +181,7 @@ int x509write_csr_set_extension( x509_csr *ctx, * * \param ctx CSR context to free */ -void x509write_csr_free( x509_csr *ctx ); +void x509write_csr_free( x509write_csr *ctx ); /** * \brief Initialize a CRT writing context @@ -399,7 +400,7 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); * \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 ); +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ); #if defined(POLARSSL_BASE64_C) /** @@ -445,7 +446,7 @@ int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ); * * \return 0 successful, or a specific error code */ -int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ); +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size ); #endif /* POLARSSL_BASE64_C */ #ifdef __cplusplus diff --git a/library/x509write.c b/library/x509write.c index 5d5d3de008..818a83a0a8 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -134,30 +134,30 @@ static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start, return( len ); } -void x509write_csr_init( x509_csr *ctx ) +void x509write_csr_init( x509write_csr *ctx ) { - memset( ctx, 0, sizeof(x509_csr) ); + memset( ctx, 0, sizeof(x509write_csr) ); } -void x509write_csr_free( x509_csr *ctx ) +void x509write_csr_free( x509write_csr *ctx ) { asn1_free_named_data_list( &ctx->subject ); asn1_free_named_data_list( &ctx->extensions ); - memset( ctx, 0, sizeof(x509_csr) ); + memset( ctx, 0, sizeof(x509write_csr) ); } -void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ) +void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ) { ctx->md_alg = md_alg; } -void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ) +void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa ) { ctx->rsa = rsa; } -int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ) +int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name ) { return x509write_string_to_names( &ctx->subject, subject_name ); } @@ -184,7 +184,7 @@ static int x509_set_extension( asn1_named_data **head, return( 0 ); } -int x509write_csr_set_extension( x509_csr *ctx, +int x509write_csr_set_extension( x509write_csr *ctx, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len ) { @@ -192,7 +192,7 @@ int x509write_csr_set_extension( x509_csr *ctx, 0, val, val_len ); } -int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage ) { unsigned char buf[4]; unsigned char *c; @@ -212,7 +212,8 @@ int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) return( 0 ); } -int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ) +int x509write_csr_set_ns_cert_type( x509write_csr *ctx, + unsigned char ns_cert_type ) { unsigned char buf[4]; unsigned char *c; @@ -248,7 +249,7 @@ void x509write_crt_free( x509write_cert *ctx ) asn1_free_named_data_list( &ctx->issuer ); asn1_free_named_data_list( &ctx->extensions ); - memset( ctx, 0, sizeof(x509_csr) ); + memset( ctx, 0, sizeof(x509write_csr) ); } void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ) @@ -644,7 +645,7 @@ static int x509_write_extensions( unsigned char **p, unsigned char *start, return( len ); } -int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) { int ret; const char *sig_oid; @@ -975,7 +976,7 @@ int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ) return( 0 ); } -int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ) +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size ) { int ret; unsigned char output_buf[4096]; diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 384ef08d64..17a969ac5c 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -60,7 +60,7 @@ struct options unsigned char ns_cert_type; /* NS cert type */ } opt; -int write_certificate_request( x509_csr *req, char *output_file ) +int write_certificate_request( x509write_csr *req, char *output_file ) { int ret; FILE *f; @@ -130,7 +130,7 @@ int main( int argc, char *argv[] ) char buf[1024]; int i, j, n; char *p, *q, *r; - x509_csr req; + x509write_csr req; /* * Set to sane values diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 10338aa715..53fb3ed6f0 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -16,7 +16,7 @@ void x509_csr_check( char *key_file, int md_type, { rsa_context rsa; pem_context pem; - x509_csr req; + x509write_csr req; unsigned char *c; unsigned char buf[4000]; unsigned char check_buf[4000]; From 52be08c299ffd42ee06f29200ea9b752b44f9ea8 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 12:37:54 +0200 Subject: [PATCH 10/42] Added support for writing Key Usage and NS Cert Type extensions --- include/polarssl/x509write.h | 23 +++++++++++++++++++ library/x509write.c | 41 ++++++++++++++++++++++++++++++++++ programs/x509/cert_write.c | 43 ++++++++++++++++++++++++++++++------ 3 files changed, 100 insertions(+), 7 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index ece231965a..075b8adad3 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -334,6 +334,29 @@ int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ); */ int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ); +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_crt_set_key_usage( x509write_cert *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 CRT 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_crt_set_ns_cert_type( x509write_cert *ctx, + unsigned char ns_cert_type ); + /** * \brief Free the contents of a CRT write context * diff --git a/library/x509write.c b/library/x509write.c index 818a83a0a8..c57e56a0b0 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -389,6 +389,47 @@ int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) 0, buf + sizeof(buf) - len, len ); } +int x509write_crt_set_key_usage( x509write_cert *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, 7 ) ) != 4 ) + return( ret ); + + ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + 1, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_crt_set_ns_cert_type( x509write_cert *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_crt_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( OID_NS_CERT_TYPE ), + 0, buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 7a811d49f5..dc9f00a991 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -317,13 +317,6 @@ int main( int argc, char *argv[] ) goto exit; } -/* - 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 names for validity */ @@ -455,6 +448,42 @@ int main( int argc, char *argv[] ) printf( " ok\n" ); + if( opt.key_usage ) + { + printf( " . Adding the Key Usage extension ..." ); + fflush( stdout ); + + ret = x509write_crt_set_key_usage( &crt, opt.key_usage ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + } + + if( opt.ns_cert_type ) + { + printf( " . Adding the NS Cert Type extension ..." ); + fflush( stdout ); + + ret = x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); + } + /* * 1.2. Writing the request */ From cdda0975076b6ec1b2dd8f92f65b6d6721bb5ac5 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 12:51:29 +0200 Subject: [PATCH 11/42] Fixed doxygen documentation in asn1.h (added \brief) --- include/polarssl/asn1.h | 53 ++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index 86a1bc8c14..45fd6cd877 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -154,8 +154,8 @@ typedef struct _asn1_named_data asn1_named_data; /** - * Get the length of an ASN.1 element. - * Updates the pointer to immediately behind the length. + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. * * \param p The position in the ASN.1 data * \param end End of data @@ -170,8 +170,8 @@ int asn1_get_len( unsigned char **p, size_t *len ); /** - * Get the tag and length of the tag. Check for the requested tag. - * Updates the pointer to immediately behind the tag and length. + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. * * \param p The position in the ASN.1 data * \param end End of data @@ -186,8 +186,8 @@ int asn1_get_tag( unsigned char **p, size_t *len, int tag ); /** - * Retrieve a boolean ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. * * \param p The position in the ASN.1 data * \param end End of data @@ -200,8 +200,8 @@ int asn1_get_bool( unsigned char **p, int *val ); /** - * Retrieve an integer ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. * * \param p The position in the ASN.1 data * \param end End of data @@ -214,8 +214,8 @@ int asn1_get_int( unsigned char **p, int *val ); /** - * Retrieve a bitstring ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. * * \param p The position in the ASN.1 data * \param end End of data @@ -227,8 +227,9 @@ int asn1_get_bitstring( unsigned char **p, const unsigned char *end, asn1_bitstring *bs); /** - * Retrieve a bitstring ASN.1 tag without unused bits and its value. - * Updates the pointer to the beginning of the bit/octet string. + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. * * \param p The position in the ASN.1 data * \param end End of data @@ -240,8 +241,8 @@ int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, size_t *len ); /** - * Parses and splits an ASN.1 "SEQUENCE OF " - * Updated the pointer to immediately behind the full sequence tag. + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. * * \param p The position in the ASN.1 data * \param end End of data @@ -257,8 +258,8 @@ int asn1_get_sequence_of( unsigned char **p, #if defined(POLARSSL_BIGNUM_C) /** - * Retrieve a MPI value from an integer ASN.1 tag. - * Updates the pointer to immediately behind the full tag. + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. * * \param p The position in the ASN.1 data * \param end End of data @@ -272,8 +273,9 @@ int asn1_get_mpi( unsigned char **p, #endif /** - * Retrieve an AlgorithmIdentifier ASN.1 sequence. - * Updates the pointer to immediately behind the full AlgorithmIdentifier. + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. * * \param p The position in the ASN.1 data * \param end End of data @@ -287,8 +289,10 @@ int asn1_get_alg( unsigned char **p, asn1_buf *alg, asn1_buf *params ); /** - * Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no params. - * Updates the pointer to immediately behind the full AlgorithmIdentifier. + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. * * \param p The position in the ASN.1 data * \param end End of data @@ -301,7 +305,8 @@ int asn1_get_alg_null( unsigned char **p, asn1_buf *alg ); /** - * Find a specific named_data entry in a sequence or list based on the OID. + * \brief 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 @@ -313,15 +318,15 @@ asn1_named_data *asn1_find_named_data( asn1_named_data *list, const char *oid, size_t len ); /** - * Free a asn1_named_data entry + * \brief Free a asn1_named_data entry * * \param entry The named data entry to free */ void asn1_free_named_data( asn1_named_data *entry ); /** - * Free all entries in a asn1_named_data list - * Head will be set to NULL + * \brief Free all entries in a asn1_named_data list + * Head will be set to NULL * * \param head Pointer to the head of the list of named data entries to free */ From d4bf870ff5d26772d7f019e698529534f8a1f577 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 13:59:11 +0200 Subject: [PATCH 12/42] Allow spaces after the comma when converting X509 names --- library/x509write.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/x509write.c b/library/x509write.c index c57e56a0b0..aed66240e6 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -102,6 +102,9 @@ static int x509write_string_to_names( asn1_named_data **head, char *name ) return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } + while( c < end && *(c + 1) == ' ' ) + c++; + s = c + 1; in_tag = 1; } From 1014e9577583dfd53494b338d8527e5722f7adba Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 13:59:42 +0200 Subject: [PATCH 13/42] Use issuer_name from the issuer_certificate in cert_write app --- programs/x509/cert_write.c | 62 +++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index dc9f00a991..9c3766c93e 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -53,6 +53,7 @@ int main( int argc, char *argv[] ) } #else +#define DFL_ISSUER_CRT "" #define DFL_SUBJECT_KEY "subject.key" #define DFL_ISSUER_KEY "ca.key" #define DFL_SUBJECT_PWD "" @@ -73,6 +74,7 @@ int main( int argc, char *argv[] ) */ struct options { + char *issuer_crt; /* filename of the issuer certificate */ char *subject_key; /* filename of the subject key file */ char *issuer_key; /* filename of the issuer key file */ char *subject_pwd; /* password for the subject key file */ @@ -118,6 +120,9 @@ int write_certificate( x509write_cert *crt, char *output_file ) "\n acceptable parameters:\n" \ " subject_key=%%s default: subject.key\n" \ " subject_pwd=%%s default: (empty)\n" \ + " issuer_crt=%%s default: (empty)\n" \ + " If issuer_crt is specified, issuer_name is\n" \ + " ignored!\n" \ " issuer_key=%%s default: ca.key\n" \ " issuer_pwd=%%s default: (empty)\n" \ " output_file=%%s default: cert.crt\n" \ @@ -151,6 +156,7 @@ int write_certificate( x509write_cert *crt, char *output_file ) int main( int argc, char *argv[] ) { int ret = 0; + x509_cert issuer_crt; rsa_context issuer_rsa, subject_rsa; char buf[1024]; int i, j, n; @@ -166,6 +172,7 @@ int main( int argc, char *argv[] ) rsa_init( &issuer_rsa, RSA_PKCS_V15, 0 ); rsa_init( &subject_rsa, RSA_PKCS_V15, 0 ); mpi_init( &serial ); + memset( &issuer_crt, 0, sizeof(x509_cert) ); memset( buf, 0, 1024 ); if( argc == 0 ) @@ -176,6 +183,7 @@ int main( int argc, char *argv[] ) goto exit; } + opt.issuer_crt = DFL_ISSUER_CRT; opt.subject_key = DFL_SUBJECT_KEY; opt.issuer_key = DFL_ISSUER_KEY; opt.subject_pwd = DFL_SUBJECT_PWD; @@ -214,6 +222,8 @@ int main( int argc, char *argv[] ) opt.subject_pwd = q; else if( strcmp( p, "issuer_pwd" ) == 0 ) opt.issuer_pwd = q; + else if( strcmp( p, "issuer_crt" ) == 0 ) + opt.issuer_crt = q; else if( strcmp( p, "output_file" ) == 0 ) opt.output_file = q; else if( strcmp( p, "subject_name" ) == 0 ) @@ -306,6 +316,8 @@ int main( int argc, char *argv[] ) goto usage; } + printf("\n"); + // Parse serial to MPI // if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) @@ -317,6 +329,40 @@ int main( int argc, char *argv[] ) goto exit; } + // Parse issuer certificate if present + // + if( strlen( opt.issuer_crt ) ) + { + /* + * 1.0. Load the certificates + */ + printf( " . Loading the issuer certificate ..." ); + fflush( stdout ); + + if( ( ret = x509parse_crtfile( &issuer_crt, opt.issuer_crt ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509parse_crtfile returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = x509parse_dn_gets( buf, sizeof(buf), &issuer_crt.issuer ); + if( ret < 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509parse_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + opt.issuer_name = buf; + + printf( " ok\n" ); + } + /* * 1.0. Check the names for validity */ @@ -341,7 +387,7 @@ int main( int argc, char *argv[] ) /* * 1.1. Load the keys */ - printf( "\n . Loading the subject key ..." ); + printf( " . Loading the subject key ..." ); fflush( stdout ); ret = x509parse_keyfile_rsa( &subject_rsa, opt.subject_key, opt.subject_pwd ); @@ -373,6 +419,20 @@ int main( int argc, char *argv[] ) goto exit; } + // Check if key and issuer certificate match + // + if( strlen( opt.issuer_crt ) ) + { + if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) || + mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N, &issuer_rsa.N ) != 0 || + mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E, &issuer_rsa.E ) != 0 ) + { + printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); + ret = -1; + goto exit; + } + } + x509write_crt_set_issuer_key( &crt, &issuer_rsa ); printf( " ok\n" ); From 8693274219074a62e6fcf4b317605b97526fe458 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 14:09:42 +0200 Subject: [PATCH 14/42] Small typo in usage of cert_req app --- programs/x509/cert_req.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 17a969ac5c..1e402fc963 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -85,7 +85,7 @@ int write_certificate_request( x509write_csr *req, char *output_file ) } #define USAGE \ - "\n usage: key_app param=<>...\n" \ + "\n usage: cert_req param=<>...\n" \ "\n acceptable parameters:\n" \ " filename=%%s default: keyfile.key\n" \ " debug_level=%%d default: 0 (disabled)\n" \ From f9f377e6527f1175891e8a624cb3cbf70eb416c3 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 15:35:10 +0200 Subject: [PATCH 15/42] CSR Parsing (without attributes / extensions) implemented --- include/polarssl/x509.h | 85 ++++++++- library/x509parse.c | 329 +++++++++++++++++++++++++++++++++++ programs/.gitignore | 1 + programs/x509/CMakeLists.txt | 5 +- programs/x509/req_app.c | 152 ++++++++++++++++ 5 files changed, 562 insertions(+), 10 deletions(-) create mode 100644 programs/x509/req_app.c diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index e68789ce9a..0c302962cc 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -151,7 +151,7 @@ extern "C" { * \{ */ /** - * \name Structures for parsing X.509 certificates and CRLs + * \name Structures for parsing X.509 certificates, CRLs and CSRs * \{ */ @@ -227,12 +227,12 @@ typedef struct _x509_cert md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */; - struct _x509_cert *next; /**< Next certificate in the CA-chain. */ + struct _x509_cert *next; /**< Next certificate in the CA-chain. */ } x509_cert; -/** - * Certificate revocation list entry. +/** + * Certificate revocation list entry. * Contains the CA-specific serial numbers and revocation dates. */ typedef struct _x509_crl_entry @@ -249,8 +249,8 @@ typedef struct _x509_crl_entry } x509_crl_entry; -/** - * Certificate revocation list structure. +/** + * Certificate revocation list structure. * Every CRL may have multiple entries. */ typedef struct _x509_crl @@ -265,7 +265,7 @@ typedef struct _x509_crl x509_name issuer; /**< The parsed issuer data (named information object). */ - x509_time this_update; + x509_time this_update; x509_time next_update; x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ @@ -277,10 +277,32 @@ typedef struct _x509_crl md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */; - struct _x509_crl *next; + struct _x509_crl *next; } x509_crl; -/** \} name Structures for parsing X.509 certificates and CRLs */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct _x509_csr +{ + x509_buf raw; /**< The raw CSR data (DER). */ + x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; + + x509_buf subject_raw; /**< The raw subject data (DER). */ + x509_name subject; /**< The parsed subject data (named information object). */ + + pk_context pk; /**< Container for the public key context. */ + + x509_buf sig_oid; + x509_buf sig; + md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */ + pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */; +} +x509_csr; +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ /** \} addtogroup x509_module */ /** @@ -362,6 +384,18 @@ int x509parse_crtpath( x509_cert *chain, const char *path ); */ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ); +/** \ingroup x509_module */ +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ); + /** \ingroup x509_module */ /** * \brief Load one or more CRLs and add them @@ -374,6 +408,17 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ); */ int x509parse_crlfile( x509_crl *chain, const char *path ); +/** \ingroup x509_module */ +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int x509parse_csrfile( x509_csr *csr, const char *path ); + #if defined(POLARSSL_RSA_C) /** \ingroup x509_module */ /** @@ -563,6 +608,21 @@ int x509parse_cert_info( char *buf, size_t size, const char *prefix, int x509parse_crl_info( char *buf, size_t size, const char *prefix, const x509_crl *crl ); +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509parse_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ); + /** * \brief Give an known OID, return its descriptive string. * @@ -680,6 +740,13 @@ void x509_free( x509_cert *crt ); */ void x509_crl_free( x509_crl *crl ); +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void x509_csr_free( x509_csr *csr ); + /** \} name Functions to clear a certificate, CRL or private RSA key */ diff --git a/library/x509parse.c b/library/x509parse.c index c175df4c4a..2290b7b4cd 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -131,6 +131,29 @@ static int x509_crl_get_version( unsigned char **p, return( 0 ); } +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( POLARSSL_ERR_X509_CERT_INVALID_VERSION + ret ); + } + + return( 0 ); +} + /* * CertificateSerialNumber ::= INTEGER */ @@ -1624,6 +1647,214 @@ int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ) return( POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT ); } +/* + * Parse a CSR + */ +int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end; +#if defined(POLARSSL_PEM_C) + size_t use_len; + pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL ) + return( POLARSSL_ERR_X509_INVALID_INPUT ); + + memset( csr, 0, sizeof( x509_csr ) ); + +#if defined(POLARSSL_PEM_C) + pem_init( &pem ); + ret = pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + + /* + * Steal PEM buffer + */ + p = pem.buf; + pem.buf = NULL; + len = pem.buflen; + pem_free( &pem ); + } + else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + pem_free( &pem ); + return( ret ); + } + else + { + /* + * nope, copy the raw DER data + */ + p = (unsigned char *) polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + buflen = 0; + } +#else + p = (unsigned char *) polarssl_malloc( len = buflen ); + + if( p == NULL ) + return( POLARSSL_ERR_X509_MALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + buflen = 0; +#endif + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + csr->version++; + + if( csr->version != 1 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION ); + } + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); + } + + if( ( ret = x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = x509_get_pubkey( &p, end, &csr->pk ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + */ + if( ( ret = asn1_get_tag( &p, end, &len, + ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + ret ); + } + // TODO Parse Attributes / extension requests + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = x509_get_alg_null( &p, end, &csr->sig_oid ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = x509_get_sig_alg( &csr->sig_oid, &csr->sig_md, + &csr->sig_pk ) ) != 0 ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG ); + } + + if( ( ret = x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + x509_csr_free( csr ); + return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT + + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + /* * Parse one or more CRLs and add them to the chained list */ @@ -2072,6 +2303,26 @@ cleanup: return( ret ); } +/* + * Load a CSR into the structure + */ +int x509parse_csrfile( x509_csr *csr, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if ( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = x509parse_csr( csr, buf, n ); + + memset( buf, 0, n + 1 ); + polarssl_free( buf ); + + return( ret ); +} + /* * Load one or more CRLs and add them to the chained list */ @@ -3284,6 +3535,53 @@ int x509parse_crl_info( char *buf, size_t size, const char *prefix, return( (int) ( size - n ) ); } +/* + * Return an informational string about the CSR. + */ +int x509parse_csr_info( char *buf, size_t size, const char *prefix, + const x509_csr *csr ) +{ + int ret; + size_t n; + char *p; + const char *desc; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%ssubject name : ", prefix ); + SAFE_SNPRINTF(); + ret = x509parse_dn_gets( p, n, &csr->subject ); + SAFE_SNPRINTF(); + + ret = snprintf( p, n, "\n%ssigned using : ", prefix ); + SAFE_SNPRINTF(); + + ret = oid_get_sig_alg_desc( &csr->sig_oid, &desc ); + if( ret != 0 ) + ret = snprintf( p, n, "???" ); + else + ret = snprintf( p, n, "%s", desc ); + SAFE_SNPRINTF(); + + if( ( ret = x509_key_size_helper( key_size_str, BEFORE_COLON, + pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) pk_get_size( &csr->pk ) ); + SAFE_SNPRINTF(); + + return( (int) ( size - n ) ); +} + /* * Return 0 if the x509_time is still valid, or 1 otherwise. */ @@ -3921,6 +4219,37 @@ void x509_crl_free( x509_crl *crl ) while( crl_cur != NULL ); } +/* + * Unallocate all CSR data + */ +void x509_csr_free( x509_csr *csr ) +{ + x509_name *name_cur; + x509_name *name_prv; + + if( csr == NULL ) + return; + + pk_free( &csr->pk ); + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + memset( name_prv, 0, sizeof( x509_name ) ); + polarssl_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + memset( csr->raw.p, 0, csr->raw.len ); + polarssl_free( csr->raw.p ); + } + + memset( csr, 0, sizeof( x509_csr ) ); +} + #if defined(POLARSSL_SELF_TEST) #include "polarssl/certs.h" diff --git a/programs/.gitignore b/programs/.gitignore index b349cd44cc..32ca900dad 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -41,3 +41,4 @@ x509/cert_app x509/cert_req x509/crl_app x509/cert_write +x509/req_app diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt index 8aaa4ac24e..fe46da5dbe 100644 --- a/programs/x509/CMakeLists.txt +++ b/programs/x509/CMakeLists.txt @@ -16,12 +16,15 @@ target_link_libraries(cert_app ${libs}) add_executable(crl_app crl_app.c) target_link_libraries(crl_app ${libs}) +add_executable(req_app req_app.c) +target_link_libraries(req_app ${libs}) + add_executable(cert_req cert_req.c) target_link_libraries(cert_req ${libs}) add_executable(cert_write cert_write.c) target_link_libraries(cert_write ${libs}) -install(TARGETS cert_app crl_app cert_req cert_write +install(TARGETS cert_app crl_app req_app cert_req cert_write DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c new file mode 100644 index 0000000000..8c0e3fed50 --- /dev/null +++ b/programs/x509/req_app.c @@ -0,0 +1,152 @@ +/* + * Certificate request reading application + * + * 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/x509.h" + +#define DFL_FILENAME "cert.req" +#define DFL_DEBUG_LEVEL 0 + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the certificate request */ +} opt; + +#define USAGE \ + "\n usage: req_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: cert.req\n" \ + "\n" + +#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " + "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else +int main( int argc, char *argv[] ) +{ + int ret = 0; + unsigned char buf[100000]; + x509_csr csr; + int i, j, n; + char *p, *q; + + /* + * Set to sane values + */ + memset( &csr, 0, sizeof( x509_csr ) ); + + if( argc == 0 ) + { + usage: + printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + + for( i = 1; i < argc; i++ ) + { + n = strlen( argv[i] ); + + for( j = 0; j < n; j++ ) + { + if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) + argv[i][j] |= 0x20; + } + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else + goto usage; + } + + /* + * 1.1. Load the CSR + */ + printf( "\n . Loading the CSR ..." ); + fflush( stdout ); + + ret = x509parse_csrfile( &csr, opt.filename ); + + if( ret != 0 ) + { + printf( " failed\n ! x509parse_csr returned %d\n\n", ret ); + x509_csr_free( &csr ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 1.2 Print the CSR + */ + printf( " . CSR information ...\n" ); + ret = x509parse_csr_info( (char *) buf, sizeof( buf ) - 1, " ", &csr ); + if( ret == -1 ) + { + printf( " failed\n ! x509parse_csr_info returned %d\n\n", ret ); + x509_csr_free( &csr ); + goto exit; + } + + printf( "%s\n", buf ); + +exit: + x509_csr_free( &csr ); + +#if defined(_WIN32) + printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( ret ); +} +#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && POLARSSL_X509_PARSE_C && + POLARSSL_FS_IO */ From e2673fb34baaa6ae7b013ebee06b888b60754403 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 15:52:07 +0200 Subject: [PATCH 16/42] cert_write app now parses presented CSR for subject name and key --- programs/x509/cert_write.c | 90 ++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 9c3766c93e..0c2999732f 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -54,6 +54,7 @@ int main( int argc, char *argv[] ) #else #define DFL_ISSUER_CRT "" +#define DFL_REQUEST_FILE "" #define DFL_SUBJECT_KEY "subject.key" #define DFL_ISSUER_KEY "ca.key" #define DFL_SUBJECT_PWD "" @@ -75,6 +76,7 @@ int main( int argc, char *argv[] ) struct options { char *issuer_crt; /* filename of the issuer certificate */ + char *request_file; /* filename of the certificate request */ char *subject_key; /* filename of the subject key file */ char *issuer_key; /* filename of the issuer key file */ char *subject_pwd; /* password for the subject key file */ @@ -118,6 +120,9 @@ int write_certificate( x509write_cert *crt, char *output_file ) #define USAGE \ "\n usage: cert_write param=<>...\n" \ "\n acceptable parameters:\n" \ + " request_file=%%s default: (empty)\n" \ + " If request_file is specified, subject_key,\n" \ + " subject_pwd and subject_name are ignored!\n" \ " subject_key=%%s default: subject.key\n" \ " subject_pwd=%%s default: (empty)\n" \ " issuer_crt=%%s default: (empty)\n" \ @@ -159,8 +164,11 @@ int main( int argc, char *argv[] ) x509_cert issuer_crt; rsa_context issuer_rsa, subject_rsa; char buf[1024]; + char issuer_name[128]; + char subject_name[128]; int i, j, n; char *p, *q, *r; + x509_csr csr; x509write_cert crt; mpi serial; @@ -172,6 +180,7 @@ int main( int argc, char *argv[] ) rsa_init( &issuer_rsa, RSA_PKCS_V15, 0 ); rsa_init( &subject_rsa, RSA_PKCS_V15, 0 ); mpi_init( &serial ); + memset( &csr, 0, sizeof(x509_csr) ); memset( &issuer_crt, 0, sizeof(x509_cert) ); memset( buf, 0, 1024 ); @@ -184,6 +193,8 @@ int main( int argc, char *argv[] ) } opt.issuer_crt = DFL_ISSUER_CRT; + opt.request_file = DFL_REQUEST_FILE; + opt.request_file = DFL_REQUEST_FILE; opt.subject_key = DFL_SUBJECT_KEY; opt.issuer_key = DFL_ISSUER_KEY; opt.subject_pwd = DFL_SUBJECT_PWD; @@ -214,7 +225,9 @@ int main( int argc, char *argv[] ) argv[i][j] |= 0x20; } - if( strcmp( p, "subject_key" ) == 0 ) + if( strcmp( p, "request_file" ) == 0 ) + opt.request_file = q; + else if( strcmp( p, "subject_key" ) == 0 ) opt.subject_key = q; else if( strcmp( p, "issuer_key" ) == 0 ) opt.issuer_key = q; @@ -334,7 +347,7 @@ int main( int argc, char *argv[] ) if( strlen( opt.issuer_crt ) ) { /* - * 1.0. Load the certificates + * 1.0.a. Load the certificates */ printf( " . Loading the issuer certificate ..." ); fflush( stdout ); @@ -348,7 +361,8 @@ int main( int argc, char *argv[] ) goto exit; } - ret = x509parse_dn_gets( buf, sizeof(buf), &issuer_crt.issuer ); + ret = x509parse_dn_gets( issuer_name, sizeof(issuer_name), + &issuer_crt.issuer ); if( ret < 0 ) { #ifdef POLARSSL_ERROR_C @@ -358,7 +372,51 @@ int main( int argc, char *argv[] ) goto exit; } - opt.issuer_name = buf; + opt.issuer_name = issuer_name; + + printf( " ok\n" ); + } + + // Parse certificate request if present + // + if( strlen( opt.request_file ) ) + { + /* + * 1.0.b. Load the CSR + */ + printf( " . Loading the certificate request ..." ); + fflush( stdout ); + + if( ( ret = x509parse_csrfile( &csr, opt.request_file ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509parse_csrfile returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = x509parse_dn_gets( subject_name, sizeof(subject_name), + &csr.subject ); + if( ret < 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509parse_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + opt.subject_name = subject_name; + + if( ( ret = rsa_copy( &subject_rsa, pk_rsa( csr.pk ) ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! rsa_copy returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } printf( " ok\n" ); } @@ -387,23 +445,27 @@ int main( int argc, char *argv[] ) /* * 1.1. Load the keys */ - printf( " . Loading the subject key ..." ); - fflush( stdout ); - - ret = x509parse_keyfile_rsa( &subject_rsa, opt.subject_key, opt.subject_pwd ); - - if( ret != 0 ) + if( !strlen( opt.request_file ) ) { + printf( " . Loading the subject key ..." ); + fflush( stdout ); + + ret = x509parse_keyfile_rsa( &subject_rsa, opt.subject_key, + opt.subject_pwd ); + if( ret != 0 ) + { #ifdef POLARSSL_ERROR_C - error_strerror( ret, buf, 1024 ); + error_strerror( ret, buf, 1024 ); #endif - printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); - goto exit; + printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + printf( " ok\n" ); } x509write_crt_set_subject_key( &crt, &subject_rsa ); - printf( " ok\n" ); printf( " . Loading the issuer key ..." ); fflush( stdout ); From eba3ccf785824b700af91fd488df3e99cb0489b0 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 15:55:12 +0200 Subject: [PATCH 17/42] Typo in config.h --- include/polarssl/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 648539b2da..08a136b510 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -401,11 +401,11 @@ /** * \def POLARSSL_ERROR_STRERROR_DUMMY * - * Enable a dummy error function to make use of error_strerror() in + * Enable a dummy error function to make use of polarssl_strerror() in * third party libraries easier. * * Disable if you run into name conflicts and want to really remove the - * error_strerror() + * polarssl_strerror() */ #define POLARSSL_ERROR_STRERROR_DUMMY From 80d44fee2ef59f3a7ecec4048afcb4fdb3ecd122 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 15:59:20 +0200 Subject: [PATCH 18/42] Moved 'define handling code' to top --- programs/x509/cert_app.c | 37 +++++++++++++++++++------------------ programs/x509/cert_req.c | 25 +++++++++++++------------ programs/x509/crl_app.c | 25 +++++++++++++------------ programs/x509/req_app.c | 25 +++++++++++++------------ 4 files changed, 58 insertions(+), 54 deletions(-) diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index 40d76d8e80..0096735bda 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -39,6 +39,25 @@ #include "polarssl/ssl.h" #include "polarssl/x509.h" +#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) || \ + !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \ + !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) || \ + !defined(POLARSSL_CTR_DRBG_C) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or " + "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or " + "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or " + "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or " + "POLARSSL_CTR_DRBG_C not defined.\n"); + return( 0 ); +} +#else + #define MODE_NONE 0 #define MODE_FILE 1 #define MODE_SSL 2 @@ -130,24 +149,6 @@ static int my_verify( void *data, x509_cert *crt, int depth, int *flags ) " permissive=%%d default: 0 (disabled)\n" \ "\n" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) || \ - !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_CLI_C) || \ - !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) || \ - !defined(POLARSSL_CTR_DRBG_C) -int main( int argc, char *argv[] ) -{ - ((void) argc); - ((void) argv); - - printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or " - "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_CLI_C and/or " - "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or " - "POLARSSL_CTR_DRBG_C not defined.\n"); - return( 0 ); -} -#else int main( int argc, char *argv[] ) { int ret = 0, server_fd; diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 1e402fc963..29a0da1449 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -40,6 +40,19 @@ #include "polarssl/x509write.h" #include "polarssl/oid.h" +#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " + "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else + #define DFL_FILENAME "keyfile.key" #define DFL_DEBUG_LEVEL 0 #define DFL_OUTPUT_FILENAME "cert.req" @@ -111,18 +124,6 @@ int write_certificate_request( x509write_csr *req, char *output_file ) " object_signing_ca\n" \ "\n" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) -int main( int argc, char *argv[] ) -{ - ((void) argc); - ((void) argv); - - printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); - return( 0 ); -} -#else int main( int argc, char *argv[] ) { int ret = 0; diff --git a/programs/x509/crl_app.c b/programs/x509/crl_app.c index b98e743dd0..c9c3ef0d86 100644 --- a/programs/x509/crl_app.c +++ b/programs/x509/crl_app.c @@ -35,6 +35,19 @@ #include "polarssl/x509.h" +#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " + "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else + #define DFL_FILENAME "crl.pem" #define DFL_DEBUG_LEVEL 0 @@ -52,18 +65,6 @@ struct options " filename=%%s default: crl.pem\n" \ "\n" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) -int main( int argc, char *argv[] ) -{ - ((void) argc); - ((void) argv); - - printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); - return( 0 ); -} -#else int main( int argc, char *argv[] ) { int ret = 0; diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c index 8c0e3fed50..e2faab43b5 100644 --- a/programs/x509/req_app.c +++ b/programs/x509/req_app.c @@ -35,6 +35,19 @@ #include "polarssl/x509.h" +#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ + !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " + "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else + #define DFL_FILENAME "cert.req" #define DFL_DEBUG_LEVEL 0 @@ -52,18 +65,6 @@ struct options " filename=%%s default: cert.req\n" \ "\n" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) -int main( int argc, char *argv[] ) -{ - ((void) argc); - ((void) argv); - - printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); - return( 0 ); -} -#else int main( int argc, char *argv[] ) { int ret = 0; From 4122f3eacfe9f4cc706c0d3b4717838b3a6f67d0 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 16:01:46 +0200 Subject: [PATCH 19/42] Removed POLARSSL_ERROR_C define and added as requirement defing for cert_req and cert_write apps --- programs/x509/cert_req.c | 12 ++++------- programs/x509/cert_write.c | 42 ++++---------------------------------- 2 files changed, 8 insertions(+), 46 deletions(-) diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 29a0da1449..6cc05c825f 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -41,14 +41,16 @@ #include "polarssl/oid.h" #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) + !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) || \ + !defined(POLARSSL_ERROR_C) int main( int argc, char *argv[] ) { ((void) argc); ((void) argv); printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO not defined.\n"); + "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or " + "POLARSSL_ERROR_C not defined.\n"); return( 0 ); } #else @@ -254,9 +256,7 @@ int main( int argc, char *argv[] ) */ 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 ! x509write_csr_set_subject_name returned %d - %s\n\n", ret, buf ); goto exit; } @@ -271,9 +271,7 @@ int main( int argc, char *argv[] ) if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); goto exit; } @@ -290,9 +288,7 @@ int main( int argc, char *argv[] ) 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; } diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 0c2999732f..91d448a618 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -41,14 +41,16 @@ #include "polarssl/oid.h" #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO) + !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO) || \ + !defined(POLARSSL_ERROR_C) int main( int argc, char *argv[] ) { ((void) argc); ((void) argv); printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO not defined.\n"); + "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO and/or " + "POLARSSL_ERROR_C not defined.\n"); return( 0 ); } #else @@ -335,9 +337,7 @@ int main( int argc, char *argv[] ) // if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! mpi_read_string returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -354,9 +354,7 @@ int main( int argc, char *argv[] ) if( ( ret = x509parse_crtfile( &issuer_crt, opt.issuer_crt ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_crtfile returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -365,9 +363,7 @@ int main( int argc, char *argv[] ) &issuer_crt.issuer ); if( ret < 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -389,9 +385,7 @@ int main( int argc, char *argv[] ) if( ( ret = x509parse_csrfile( &csr, opt.request_file ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_csrfile returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -400,9 +394,7 @@ int main( int argc, char *argv[] ) &csr.subject ); if( ret < 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -411,9 +403,7 @@ int main( int argc, char *argv[] ) if( ( ret = rsa_copy( &subject_rsa, pk_rsa( csr.pk ) ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! rsa_copy returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -426,18 +416,14 @@ int main( int argc, char *argv[] ) */ if( ( ret = x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } if( ( ret = x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -454,9 +440,7 @@ int main( int argc, char *argv[] ) opt.subject_pwd ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -474,9 +458,7 @@ int main( int argc, char *argv[] ) if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509parse_keyfile_rsa returned -x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -505,9 +487,7 @@ int main( int argc, char *argv[] ) ret = x509write_crt_set_serial( &crt, &serial ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -515,9 +495,7 @@ int main( int argc, char *argv[] ) ret = x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -531,9 +509,7 @@ int main( int argc, char *argv[] ) opt.max_pathlen ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -546,9 +522,7 @@ int main( int argc, char *argv[] ) ret = x509write_crt_set_subject_key_identifier( &crt ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -561,9 +535,7 @@ int main( int argc, char *argv[] ) ret = x509write_crt_set_authority_key_identifier( &crt ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -578,9 +550,7 @@ int main( int argc, char *argv[] ) ret = x509write_crt_set_key_usage( &crt, opt.key_usage ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -596,9 +566,7 @@ int main( int argc, char *argv[] ) ret = x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -614,9 +582,7 @@ int main( int argc, char *argv[] ) if( ( ret = write_certificate( &crt, opt.output_file ) ) != 0 ) { -#ifdef POLARSSL_ERROR_C error_strerror( ret, buf, 1024 ); -#endif printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf ); goto exit; } From b2d7f235927bf40636b4e72c95081857348ddb54 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 9 Sep 2013 16:24:18 +0200 Subject: [PATCH 20/42] Ability to selfsign certificates added to cert_write app --- programs/x509/cert_write.c | 143 ++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 64 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 91d448a618..f0939c8f2b 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -67,6 +67,7 @@ int main( int argc, char *argv[] ) #define DFL_NOT_BEFORE "20010101000000" #define DFL_NOT_AFTER "20301231235959" #define DFL_SERIAL "1" +#define DFL_SELFSIGN 0 #define DFL_IS_CA 0 #define DFL_MAX_PATHLEN -1 #define DFL_KEY_USAGE 0 @@ -89,6 +90,7 @@ struct options char *not_before; /* validity period not before */ char *not_after; /* validity period not after */ char *serial; /* serial number string */ + int selfsign; /* selfsign the certificate */ int is_ca; /* is a CA certificate */ int max_pathlen; /* maximum CA path length */ unsigned char key_usage; /* key usage flags */ @@ -127,14 +129,20 @@ int write_certificate( x509write_cert *crt, char *output_file ) " subject_pwd and subject_name are ignored!\n" \ " subject_key=%%s default: subject.key\n" \ " subject_pwd=%%s default: (empty)\n" \ + " subject_name=%%s default: CN=Cert,O=PolarSSL,C=NL\n" \ + "\n" \ " issuer_crt=%%s default: (empty)\n" \ " If issuer_crt is specified, issuer_name is\n" \ " ignored!\n" \ + " issuer_name=%%s default: CN=CA,O=PolarSSL,C=NL\n" \ + "\n" \ + " selfsign=%%d default: 0 (false)\n" \ + " If selfsign is enabled, issuer_name and\n" \ + " issuer_key are required (issuer_crt and\n" \ + " subject_* are ignored\n" \ " issuer_key=%%s default: ca.key\n" \ " issuer_pwd=%%s default: (empty)\n" \ " output_file=%%s default: cert.crt\n" \ - " subject_name=%%s default: CN=Cert,O=PolarSSL,C=NL\n" \ - " issuer_name=%%s default: CN=CA,O=PolarSSL,C=NL\n" \ " serial=%%s default: 1\n" \ " not_before=%%s default: 20010101000000\n"\ " not_after=%%s default: 20301231235959\n"\ @@ -164,7 +172,9 @@ int main( int argc, char *argv[] ) { int ret = 0; x509_cert issuer_crt; - rsa_context issuer_rsa, subject_rsa; + rsa_context loaded_issuer_rsa, loaded_subject_rsa; + rsa_context *issuer_rsa = &loaded_issuer_rsa, + *subject_rsa = &loaded_subject_rsa; char buf[1024]; char issuer_name[128]; char subject_name[128]; @@ -179,8 +189,8 @@ int main( int argc, char *argv[] ) */ x509write_crt_init( &crt ); x509write_crt_set_md_alg( &crt, POLARSSL_MD_SHA1 ); - rsa_init( &issuer_rsa, RSA_PKCS_V15, 0 ); - rsa_init( &subject_rsa, RSA_PKCS_V15, 0 ); + rsa_init( &loaded_issuer_rsa, RSA_PKCS_V15, 0 ); + rsa_init( &loaded_subject_rsa, RSA_PKCS_V15, 0 ); mpi_init( &serial ); memset( &csr, 0, sizeof(x509_csr) ); memset( &issuer_crt, 0, sizeof(x509_cert) ); @@ -207,6 +217,7 @@ int main( int argc, char *argv[] ) opt.not_before = DFL_NOT_BEFORE; opt.not_after = DFL_NOT_AFTER; opt.serial = DFL_SERIAL; + opt.selfsign = DFL_SELFSIGN; opt.is_ca = DFL_IS_CA; opt.max_pathlen = DFL_MAX_PATHLEN; opt.key_usage = DFL_KEY_USAGE; @@ -261,6 +272,12 @@ int main( int argc, char *argv[] ) { opt.serial = q; } + else if( strcmp( p, "selfsign" ) == 0 ) + { + opt.selfsign = atoi( q ); + if( opt.selfsign < 0 || opt.selfsign > 1 ) + goto usage; + } else if( strcmp( p, "is_ca" ) == 0 ) { opt.is_ca = atoi( q ); @@ -344,7 +361,7 @@ int main( int argc, char *argv[] ) // Parse issuer certificate if present // - if( strlen( opt.issuer_crt ) ) + if( !opt.selfsign && strlen( opt.issuer_crt ) ) { /* * 1.0.a. Load the certificates @@ -375,7 +392,7 @@ int main( int argc, char *argv[] ) // Parse certificate request if present // - if( strlen( opt.request_file ) ) + if( !opt.selfsign && strlen( opt.request_file ) ) { /* * 1.0.b. Load the CSR @@ -400,17 +417,68 @@ int main( int argc, char *argv[] ) } opt.subject_name = subject_name; + subject_rsa = pk_rsa( csr.pk ); - if( ( ret = rsa_copy( &subject_rsa, pk_rsa( csr.pk ) ) ) != 0 ) + printf( " ok\n" ); + } + + /* + * 1.1. Load the keys + */ + if( !opt.selfsign && !strlen( opt.request_file ) ) + { + printf( " . Loading the subject key ..." ); + fflush( stdout ); + + ret = x509parse_keyfile_rsa( &loaded_subject_rsa, opt.subject_key, + opt.subject_pwd ); + if( ret != 0 ) { error_strerror( ret, buf, 1024 ); - printf( " failed\n ! rsa_copy returned -0x%02x - %s\n\n", -ret, buf ); + printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); } + printf( " . Loading the issuer key ..." ); + fflush( stdout ); + + ret = x509parse_keyfile_rsa( &loaded_issuer_rsa, opt.issuer_key, + opt.issuer_pwd ); + if( ret != 0 ) + { + error_strerror( ret, buf, 1024 ); + printf( " failed\n ! x509parse_keyfile_rsa returned -x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + // Check if key and issuer certificate match + // + if( strlen( opt.issuer_crt ) ) + { + if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) || + mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N, &issuer_rsa->N ) != 0 || + mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E, &issuer_rsa->E ) != 0 ) + { + printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); + ret = -1; + goto exit; + } + } + + printf( " ok\n" ); + + if( opt.selfsign ) + { + opt.issuer_name = opt.subject_name; + subject_rsa = issuer_rsa; + } + + x509write_crt_set_subject_key( &crt, subject_rsa ); + x509write_crt_set_issuer_key( &crt, issuer_rsa ); + /* * 1.0. Check the names for validity */ @@ -428,59 +496,6 @@ int main( int argc, char *argv[] ) goto exit; } - /* - * 1.1. Load the keys - */ - if( !strlen( opt.request_file ) ) - { - printf( " . Loading the subject key ..." ); - fflush( stdout ); - - ret = x509parse_keyfile_rsa( &subject_rsa, opt.subject_key, - opt.subject_pwd ); - if( ret != 0 ) - { - error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); - goto exit; - } - - printf( " ok\n" ); - } - - x509write_crt_set_subject_key( &crt, &subject_rsa ); - - - printf( " . Loading the issuer key ..." ); - fflush( stdout ); - - ret = x509parse_keyfile_rsa( &issuer_rsa, opt.issuer_key, opt.issuer_pwd ); - - if( ret != 0 ) - { - error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509parse_keyfile_rsa returned -x%02x - %s\n\n", -ret, buf ); - goto exit; - } - - // Check if key and issuer certificate match - // - if( strlen( opt.issuer_crt ) ) - { - if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) || - mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N, &issuer_rsa.N ) != 0 || - mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E, &issuer_rsa.E ) != 0 ) - { - printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); - ret = -1; - goto exit; - } - } - - x509write_crt_set_issuer_key( &crt, &issuer_rsa ); - - printf( " ok\n" ); - printf( " . Setting certificate values ..." ); fflush( stdout ); @@ -591,8 +606,8 @@ int main( int argc, char *argv[] ) exit: x509write_crt_free( &crt ); - rsa_free( &subject_rsa ); - rsa_free( &issuer_rsa ); + rsa_free( &loaded_subject_rsa ); + rsa_free( &loaded_issuer_rsa ); mpi_free( &serial ); #if defined(_WIN32) From 1c3853b953508716d9375fc784570f6a1da57c0f Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Tue, 10 Sep 2013 11:43:44 +0200 Subject: [PATCH 21/42] oid_get_oid_by_*() now give back oid length as well --- include/polarssl/oid.h | 6 ++++-- library/oid.c | 11 +++++++---- library/rsa.c | 3 +-- library/x509write.c | 19 +++++++++++++------ 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index 025a15f0a9..b0e781fc1f 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -409,11 +409,12 @@ int oid_get_sig_alg_desc( const asn1_buf *oid, const char **desc ); * \param md_alg message digest algorithm * \param pk_alg public key algorithm * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID * * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND */ int oid_get_oid_by_sig_alg( pk_type_t pk_alg, md_type_t md_alg, - const char **oid_str ); + const char **oid, size_t *olen ); /** * \brief Translate hash algorithm OID into md_type @@ -441,10 +442,11 @@ int oid_get_extended_key_usage( const asn1_buf *oid, const char **desc ); * * \param md_alg message digest algorithm * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID * * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND */ -int oid_get_oid_by_md( md_type_t md_alg, const char **oid_str ); +int oid_get_oid_by_md( md_type_t md_alg, const char **oid, size_t *olen ); #if defined(POLARSSL_CIPHER_C) /** diff --git a/library/oid.c b/library/oid.c index c5608c3a1f..f37bbf6e72 100644 --- a/library/oid.c +++ b/library/oid.c @@ -93,12 +93,13 @@ int FN_NAME( const asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ * attribute from a oid_descriptor_t wrapper. */ #define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ -int FN_NAME( ATTR1_TYPE ATTR1, const char **oid_str ) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ { \ const TYPE_T *cur = LIST; \ while( cur->descriptor.asn1 != NULL ) { \ if( cur->ATTR1 == ATTR1 ) { \ - *oid_str = cur->descriptor.asn1; \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ return( 0 ); \ } \ cur++; \ @@ -112,12 +113,14 @@ int FN_NAME( ATTR1_TYPE ATTR1, const char **oid_str ) \ */ #define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ ATTR2_TYPE, ATTR2) \ -int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid_str ) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ { \ const TYPE_T *cur = LIST; \ while( cur->descriptor.asn1 != NULL ) { \ if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ - *oid_str = cur->descriptor.asn1; \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ return( 0 ); \ } \ cur++; \ diff --git a/library/rsa.c b/library/rsa.c index c39a338a3b..10fd04099d 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -907,10 +907,9 @@ int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, if( md_info == NULL ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - if( oid_get_oid_by_md( md_alg, &oid ) != 0 ) + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - oid_size = strlen( oid ); nb_pad -= 10 + oid_size; hashlen = md_get_size( md_info ); diff --git a/library/x509write.c b/library/x509write.c index aed66240e6..f4f3c4dcce 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -581,7 +581,8 @@ static int x509_write_names( unsigned char **p, unsigned char *start, } static int x509_write_sig( unsigned char **p, unsigned char *start, - const char *oid, unsigned char *sig, size_t size ) + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) { int ret; size_t len = 0; @@ -602,7 +603,7 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, // Write OID // ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid, - strlen( oid ) ) ); + oid_len ) ); return( len ); } @@ -693,6 +694,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) { int ret; const char *sig_oid; + size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; @@ -768,10 +770,12 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) // Generate correct OID // - ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid ); + ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid, + &sig_oid_len ); c2 = buf + size - 1; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) ); + ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, + sig, ctx->rsa->len ) ); c2 -= len; memcpy( c2, c, len ); @@ -787,6 +791,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) { int ret; const char *sig_oid; + size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; @@ -798,7 +803,8 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) // Generate correct OID // - ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid ); + ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid, + &sig_oid_len ); if( ret != 0 ) return( ret ); @@ -893,7 +899,8 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); c2 = buf + size - 1; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->issuer_key->len ) ); + ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, + sig, ctx->issuer_key->len ) ); c2 -= len; memcpy( c2, c, len ); From da7317ed00d52124036728f7cb9f2a33c6b76959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 10 Sep 2013 15:52:52 +0200 Subject: [PATCH 22/42] Use asn1_free_named_data_list() when relevant --- library/x509write.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index f4f3c4dcce..6435388852 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -56,14 +56,8 @@ static int x509write_string_to_names( asn1_named_data **head, char *name ) int in_tag = 1; asn1_named_data *cur; - // Clear existing chain if present - // - while( *head != NULL ) - { - cur = *head; - *head = cur->next; - polarssl_free( cur ); - } + /* Clear existing chain if present */ + asn1_free_named_data_list( head ); while( c <= end ) { From 85dfe08b31275aca89e886369285d8d2e18a3c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 10 Sep 2013 15:59:02 +0200 Subject: [PATCH 23/42] Merge duplicated else/#else branch --- library/x509parse.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/library/x509parse.c b/library/x509parse.c index 2290b7b4cd..fc84e6164d 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -1697,6 +1697,7 @@ int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) return( ret ); } else +#endif { /* * nope, copy the raw DER data @@ -1710,16 +1711,6 @@ int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ) buflen = 0; } -#else - p = (unsigned char *) polarssl_malloc( len = buflen ); - - if( p == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - buflen = 0; -#endif csr->raw.p = p; csr->raw.len = len; @@ -1926,6 +1917,7 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) return( ret ); } else +#endif { /* * nope, copy the raw DER data @@ -1939,16 +1931,6 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ) buflen = 0; } -#else - p = (unsigned char *) polarssl_malloc( len = buflen ); - - if( p == NULL ) - return( POLARSSL_ERR_X509_MALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - buflen = 0; -#endif crl->raw.p = p; crl->raw.len = len; From 5353a03eb96d6831c4576e83c6f1c803972b4069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 12:14:26 +0200 Subject: [PATCH 24/42] x509write_csr using PK internally (WIP) --- include/polarssl/x509write.h | 2 +- library/x509write.c | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 075b8adad3..661acf6bf5 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -65,7 +65,7 @@ extern "C" { */ typedef struct _x509write_csr { - rsa_context *rsa; + pk_context *key; asn1_named_data *subject; md_type_t md_alg; asn1_named_data *extensions; diff --git a/library/x509write.c b/library/x509write.c index 6435388852..39a37ba179 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -149,9 +149,16 @@ void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ) ctx->md_alg = md_alg; } +// TODO: take a pk_context +// TODO: return int void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa ) { - ctx->rsa = rsa; + // temporary + ctx->key = polarssl_malloc( sizeof( pk_context ) ); + + // TODO: check errors + pk_init_ctx( ctx->key, pk_info_from_type( POLARSSL_PK_RSA ) ); + rsa_copy( pk_rsa( *ctx->key ), rsa ); } int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name ) @@ -718,8 +725,9 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) 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 ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) ); + // TODO: use x509_write_rsa_pubkey() (pb: pub_len) + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &pk_rsa( *ctx->key )->E ) ); + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &pk_rsa( *ctx->key )->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 ) ); @@ -760,16 +768,22 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) md( md_info_from_type( ctx->md_alg ), c, len, hash ); - rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); + if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + + // TODO: use pk_sign() + rsa_pkcs1_sign( pk_rsa( *ctx->key ), NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); // Generate correct OID // + // TODO: use pk_info->type ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid, &sig_oid_len ); + // TODO: use pk_get_len() c2 = buf + size - 1; ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, - sig, ctx->rsa->len ) ); + sig, pk_rsa( *ctx->key )->len ) ); c2 -= len; memcpy( c2, c, len ); From 6dcf0bfcf4b0d91e50a1ee6d1228e85d21a29ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 13:09:04 +0200 Subject: [PATCH 25/42] Use x509write_pubkey_der() when applicable --- library/x509write.c | 56 ++++++--------------------------------------- 1 file changed, 7 insertions(+), 49 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index 39a37ba179..35dc5bfe71 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -725,33 +725,10 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) 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 ) ); - // TODO: use x509_write_rsa_pubkey() (pb: pub_len) - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &pk_rsa( *ctx->key )->E ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &pk_rsa( *ctx->key )->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 ) ); - - 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; - - 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_BIT_STRING ) ); - - ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, - OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); - + ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ), + tmp_buf, c - tmp_buf + 1 ) ); + c -= pub_len; len += pub_len; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Subject ::= Name @@ -826,31 +803,12 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ); /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } + * SubjectPublicKeyInfo */ - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->E ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->subject_key->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 ) ); - - if( c - tmp_buf < 1 ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - *--c = 0; - pub_len += 1; - - 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_BIT_STRING ) ); - - ASN1_CHK_ADD( pub_len, asn1_write_algorithm_identifier( &c, tmp_buf, - OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); - + ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key, + tmp_buf, c - tmp_buf + 1 ) ); + c -= pub_len; len += pub_len; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, pub_len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Subject ::= Name From 27d87fa6c4063264b34ef73f9ed39a46a67ac8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 17:33:28 +0200 Subject: [PATCH 26/42] Fix many off-by-one errors --- library/x509write.c | 24 +++++++++++----------- tests/suites/test_suite_x509write.function | 14 ++++++------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index 35dc5bfe71..7499bf7758 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -440,7 +440,7 @@ int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) unsigned char *c; size_t len = 0; - c = buf + size - 1; + c = buf + size; ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) ); @@ -473,7 +473,7 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) unsigned char *c; size_t len = 0; - c = buf + size - 1; + c = buf + size; ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); @@ -703,7 +703,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) size_t pub_len = 0, sig_len = 0; size_t len = 0; - c = tmp_buf + 2048 - 1; + c = tmp_buf + sizeof( tmp_buf ); ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); @@ -726,7 +726,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ), - tmp_buf, c - tmp_buf + 1 ) ); + tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; @@ -758,7 +758,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) &sig_oid_len ); // TODO: use pk_get_len() - c2 = buf + size - 1; + c2 = buf + size; ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, pk_rsa( *ctx->key )->len ) ); @@ -784,7 +784,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) size_t sub_len = 0, pub_len = 0, sig_len = 0; size_t len = 0; - c = tmp_buf + 2048 - 1; + c = tmp_buf + sizeof( tmp_buf ); // Generate correct OID // @@ -806,7 +806,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) * SubjectPublicKeyInfo */ ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key, - tmp_buf, c - tmp_buf + 1 ) ); + tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; @@ -864,7 +864,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); - c2 = buf + size - 1; + c2 = buf + size; ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, ctx->issuer_key->len ) ); @@ -942,7 +942,7 @@ int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size ) } if( ( ret = x509write_pemify( PEM_BEGIN_CRT, PEM_END_CRT, - output_buf + sizeof(output_buf) - 1 - ret, + output_buf + sizeof(output_buf) - ret, ret, buf, size ) ) != 0 ) { return( ret ); @@ -963,7 +963,7 @@ int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ) } if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - 1 - ret, + output_buf + sizeof(output_buf) - ret, ret, buf, size ) ) != 0 ) { return( ret ); @@ -984,7 +984,7 @@ int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ) } if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY, - output_buf + sizeof(output_buf) - 1 - ret, + output_buf + sizeof(output_buf) - ret, ret, buf, size ) ) != 0 ) { return( ret ); @@ -1005,7 +1005,7 @@ int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size ) } if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR, - output_buf + sizeof(output_buf) - 1 - ret, + output_buf + sizeof(output_buf) - ret, ret, buf, size ) ) != 0 ) { return( ret ); diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 53fb3ed6f0..b45395fd1e 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -21,7 +21,7 @@ void x509_csr_check( char *key_file, int md_type, unsigned char buf[4000]; unsigned char check_buf[4000]; int ret; - size_t olen = 2000; + size_t olen = sizeof( check_buf ); FILE *f; char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1"; @@ -36,21 +36,21 @@ void x509_csr_check( char *key_file, int md_type, x509write_csr_set_rsa_key( &req, &rsa ); TEST_ASSERT( x509write_csr_set_subject_name( &req, subject_name ) == 0 ); - ret = x509write_csr_der( &req, buf, 4000 ); + ret = x509write_csr_der( &req, buf, sizeof( buf ) ); TEST_ASSERT( ret >= 0 ); - c = buf + 3999 - ret; + c = buf + sizeof( buf ) - ret; f = fopen( cert_req_check_file, "r" ); TEST_ASSERT( f != NULL ); - fread( check_buf, 1, 4000, f ); + fread( check_buf, 1, sizeof( check_buf ), f ); fclose( f ); pem_init( &pem ); pem_read_buffer( &pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", check_buf, NULL, 0, &olen ); - TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); TEST_ASSERT( pem.buflen == (size_t) ret ); + TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); x509write_csr_free( &req ); rsa_free( &rsa ); @@ -73,7 +73,7 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, unsigned char check_buf[5000]; mpi serial; int ret; - size_t olen = 2000; + size_t olen = sizeof( check_buf ); FILE *f; mpi_init( &serial ); @@ -103,7 +103,7 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, ret = x509write_crt_der( &crt, buf, sizeof(buf) ); TEST_ASSERT( ret >= 0 ); - c = buf + 3999 - ret; + c = buf + sizeof( buf ) - ret; f = fopen( cert_check_file, "r" ); TEST_ASSERT( f != NULL ); From d4eb5b51969ac43c5d52605c06cab278ba8191b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 18:16:20 +0200 Subject: [PATCH 27/42] Add references --- library/x509write.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/x509write.c b/library/x509write.c index 7499bf7758..5c968412fa 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -23,6 +23,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + #include "polarssl/config.h" #if defined(POLARSSL_X509_WRITE_C) From 8053da40579c6ce3933bdfa6515d6ef4f98b6c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 22:28:30 +0200 Subject: [PATCH 28/42] x509write_csr() now fully using PK internally --- include/polarssl/pk.h | 9 +++++++++ library/pk.c | 11 +++++++++++ library/x509write.c | 38 ++++++++++++++++++++++---------------- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h index 4ff4747ca5..3bf68f3111 100644 --- a/include/polarssl/pk.h +++ b/include/polarssl/pk.h @@ -365,6 +365,15 @@ int pk_debug( const pk_context *ctx, pk_debug_item *items ); */ const char * pk_get_name( const pk_context *ctx ); +/** + * \brief Get the key typee + * + * \param ctx Context to use + * + * \return Type on success, or POLARSSL_PK_NONE + */ +pk_type_t pk_get_type( const pk_context *ctx ); + #ifdef __cplusplus } #endif diff --git a/library/pk.c b/library/pk.c index 77f5034048..80eccc911b 100644 --- a/library/pk.c +++ b/library/pk.c @@ -273,4 +273,15 @@ const char * pk_get_name( const pk_context *ctx ) return( ctx->pk_info->name ); } +/* + * Access the PK type + */ +pk_type_t pk_get_type( const pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( POLARSSL_PK_NONE ); + + return( ctx->pk_info->type ); +} + #endif /* POLARSSL_PK_C */ diff --git a/library/x509write.c b/library/x509write.c index 5c968412fa..7c4ca33d5f 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -707,9 +707,12 @@ int x509write_csr_der( x509write_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 pub_len = 0, sig_len = 0; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; + /* + * Prepare data to be signed in tmp_buf + */ c = tmp_buf + sizeof( tmp_buf ); ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); @@ -732,6 +735,8 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) 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 ) ); + if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ), tmp_buf, c - tmp_buf ) ); c -= pub_len; @@ -750,29 +755,30 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) 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 ) ); + /* + * Prepare signature + */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); - if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + NULL, NULL ) ) != 0 || + ( ret = oid_get_oid_by_sig_alg( pk_get_type( ctx->key ), ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } - // TODO: use pk_sign() - rsa_pkcs1_sign( pk_rsa( *ctx->key ), NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); - - // Generate correct OID - // - // TODO: use pk_info->type - ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid, - &sig_oid_len ); - - // TODO: use pk_get_len() + /* + * Write data to output buffer + */ c2 = buf + size; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, - sig, pk_rsa( *ctx->key )->len ) ); + ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); c2 -= len; memcpy( c2, c, len ); - len += sig_len; + len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); From ee73179b2f3bd61e1b8c18962badd9ad1e2d374e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 22:48:40 +0200 Subject: [PATCH 29/42] Adapt x509write_csr prototypes for PK --- include/polarssl/x509write.h | 28 +++++++-- library/x509write.c | 25 ++++---- programs/pkey/ecdsa.c | 9 ++- programs/x509/cert_req.c | 72 +++++++++++++++------- tests/suites/test_suite_x509write.function | 19 +++--- 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 661acf6bf5..5e0d82ad13 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -121,13 +121,13 @@ void x509write_csr_init( x509write_csr *ctx ); int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name ); /** - * \brief Set the RSA key for a CSR (public key will be included, + * \brief Set the 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 + * \param key Asymetric key to include */ -void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa ); +void x509write_csr_set_key( x509write_csr *ctx, pk_context *key ); /** * \brief Set the MD algorithm to use for the signature @@ -419,11 +419,20 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); * \param rsa CSR to write away * \param buf buffer to write to * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. */ -int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ); +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); #if defined(POLARSSL_BASE64_C) /** @@ -466,10 +475,19 @@ int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ); * \param rsa CSR to write away * \param buf buffer to write to * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter * * \return 0 successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for couermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. */ -int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size ); +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); #endif /* POLARSSL_BASE64_C */ #ifdef __cplusplus diff --git a/library/x509write.c b/library/x509write.c index 7c4ca33d5f..e1f68dc6f1 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -156,16 +156,9 @@ void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg ) ctx->md_alg = md_alg; } -// TODO: take a pk_context -// TODO: return int -void x509write_csr_set_rsa_key( x509write_csr *ctx, rsa_context *rsa ) +void x509write_csr_set_key( x509write_csr *ctx, pk_context *key ) { - // temporary - ctx->key = polarssl_malloc( sizeof( pk_context ) ); - - // TODO: check errors - pk_init_ctx( ctx->key, pk_info_from_type( POLARSSL_PK_RSA ) ); - rsa_copy( pk_rsa( *ctx->key ), rsa ); + ctx->key = key; } int x509write_csr_set_subject_name( x509write_csr *ctx, char *subject_name ) @@ -698,7 +691,9 @@ static int x509_write_extensions( unsigned char **p, unsigned char *start, return( len ); } -int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) +int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; const char *sig_oid; @@ -761,7 +756,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size ) md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, - NULL, NULL ) ) != 0 || + f_rng, p_rng ) ) != 0 || ( ret = oid_get_oid_by_sig_alg( pk_get_type( ctx->key ), ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { @@ -1006,13 +1001,15 @@ int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ) return( 0 ); } -int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size ) +int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; unsigned char output_buf[4096]; - if( ( ret = x509write_csr_der( ctx, output_buf, - sizeof(output_buf) ) ) < 0 ) + if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) { return( ret ); } diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c index 8d52b6726b..7e500bba12 100644 --- a/programs/pkey/ecdsa.c +++ b/programs/pkey/ecdsa.c @@ -51,7 +51,7 @@ #endif #endif /* !defined(ECPARAMS) */ -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ECDSA_C) || \ +#if !defined(POLARSSL_ECDSA_C) || \ !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \ !defined(ECPARAMS) int main( int argc, char *argv[] ) @@ -59,9 +59,9 @@ int main( int argc, char *argv[] ) ((void) argc); ((void) argv); - printf("POLARSSL_BIGNUM_C and/or POLARSSL_ECDSA_C and/or " + printf("POLARSSL_ECDSA_C and/or " "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C not defined," - "and/or not EC domain parameter available\n" ); + "and/or no EC domain parameter available\n" ); return( 0 ); } #else @@ -194,6 +194,5 @@ exit: return( ret ); } -#endif /* POLARSSL_BIGNUM_C && POLARSSL_ECDSA_C && - POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C && +#endif /* POLARSSL_ECDSA_C && POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C && ECPARAMS */ diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index 6cc05c825f..b98f23368b 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -33,24 +33,22 @@ #include "polarssl/config.h" -#include "polarssl/error.h" -#include "polarssl/rsa.h" -#include "polarssl/x509.h" -#include "polarssl/base64.h" #include "polarssl/x509write.h" -#include "polarssl/oid.h" +#include "polarssl/error.h" +#include "polarssl/entropy.h" +#include "polarssl/ctr_drbg.h" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) || \ +#if !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) || \ + !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \ !defined(POLARSSL_ERROR_C) int main( int argc, char *argv[] ) { ((void) argc); ((void) argv); - printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or " - "POLARSSL_ERROR_C not defined.\n"); + printf( "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or " + "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or " + "POLARSSL_ERROR_C not defined.\n"); return( 0 ); } #else @@ -75,7 +73,9 @@ struct options unsigned char ns_cert_type; /* NS cert type */ } opt; -int write_certificate_request( x509write_csr *req, char *output_file ) +int write_certificate_request( x509write_csr *req, char *output_file, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; FILE *f; @@ -83,7 +83,7 @@ int write_certificate_request( x509write_csr *req, char *output_file ) size_t len = 0; memset( output_buf, 0, 4096 ); - if( ( ret = x509write_csr_pem( req, output_buf, 4096 ) ) < 0 ) + if( ( ret = x509write_csr_pem( req, output_buf, 4096, f_rng, p_rng ) ) < 0 ) return( ret ); len = strlen( (char *) output_buf ); @@ -129,18 +129,21 @@ int write_certificate_request( x509write_csr *req, char *output_file ) int main( int argc, char *argv[] ) { int ret = 0; - rsa_context rsa; + pk_context key; char buf[1024]; int i, j, n; char *p, *q, *r; x509write_csr req; + entropy_context entropy; + ctr_drbg_context ctr_drbg; + const char *pers = "csr example app"; /* * Set to sane values */ x509write_csr_init( &req ); x509write_csr_set_md_alg( &req, POLARSSL_MD_SHA1 ); - memset( &rsa, 0, sizeof( rsa_context ) ); + pk_init( &key ); memset( buf, 0, 1024 ); if( argc == 0 ) @@ -251,9 +254,30 @@ int main( int argc, char *argv[] ) if( opt.ns_cert_type ) x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type ); + /* + * 0. Seed the PRNG + */ + printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + entropy_init( &entropy ); + if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + error_strerror( ret, buf, 1024 ); + printf( " failed\n ! ctr_drbg_init returned %d - %s\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + /* * 1.0. Check the subject name for validity */ + printf( " . Checking subjet name..." ); + fflush( stdout ); + if( ( ret = x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 ) { error_strerror( ret, buf, 1024 ); @@ -261,22 +285,24 @@ int main( int argc, char *argv[] ) goto exit; } + printf( " ok\n" ); + /* * 1.1. Load the key */ - printf( "\n . Loading the private key ..." ); + printf( " . Loading the private key ..." ); fflush( stdout ); - ret = x509parse_keyfile_rsa( &rsa, opt.filename, NULL ); + ret = x509parse_keyfile( &key, opt.filename, NULL ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_keyfile returned %d - %s\n\n", ret, buf ); goto exit; } - x509write_csr_set_rsa_key( &req, &rsa ); + x509write_csr_set_key( &req, &key ); printf( " ok\n" ); @@ -286,7 +312,8 @@ int main( int argc, char *argv[] ) printf( " . Writing the certificate request ..." ); fflush( stdout ); - if( ( ret = write_certificate_request( &req, opt.output_file ) ) != 0 ) + if( ( ret = write_certificate_request( &req, opt.output_file, + ctr_drbg_random, &ctr_drbg ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! write_certifcate_request %d - %s\n\n", ret, buf ); @@ -297,7 +324,7 @@ int main( int argc, char *argv[] ) exit: x509write_csr_free( &req ); - rsa_free( &rsa ); + pk_free( &key ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); @@ -306,5 +333,6 @@ exit: return( ret ); } -#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && - POLARSSL_X509_PARSE_C && POLARSSL_FS_IO */ +#endif /* POLARSSL_X509_PARSE_C && POLARSSL_FS_IO && + POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C && + POLARSSL_ERROR_C */ diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index b45395fd1e..bfe07c6a28 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -14,7 +14,7 @@ void x509_csr_check( char *key_file, int md_type, char *cert_req_check_file ) { - rsa_context rsa; + pk_context key; pem_context pem; x509write_csr req; unsigned char *c; @@ -24,19 +24,20 @@ void x509_csr_check( char *key_file, int md_type, size_t olen = sizeof( check_buf ); FILE *f; char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1"; + rnd_pseudo_info rnd_info; - memset( &rsa, 0, sizeof(rsa_context) ); - ret = x509parse_keyfile_rsa( &rsa, key_file, NULL ); - TEST_ASSERT( ret == 0 ); - if( ret != 0 ) - return; + memset( &rnd_info, 0x2a, sizeof( rnd_pseudo_info ) ); + + pk_init( &key ); + TEST_ASSERT( x509parse_keyfile( &key, key_file, NULL ) == 0 ); x509write_csr_init( &req ); x509write_csr_set_md_alg( &req, md_type ); - x509write_csr_set_rsa_key( &req, &rsa ); + x509write_csr_set_key( &req, &key ); TEST_ASSERT( x509write_csr_set_subject_name( &req, subject_name ) == 0 ); - ret = x509write_csr_der( &req, buf, sizeof( buf ) ); + ret = x509write_csr_der( &req, buf, sizeof( buf ), + rnd_pseudo_rand, &rnd_info ); TEST_ASSERT( ret >= 0 ); c = buf + sizeof( buf ) - ret; @@ -53,8 +54,8 @@ void x509_csr_check( char *key_file, int md_type, TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); x509write_csr_free( &req ); - rsa_free( &rsa ); pem_free( &pem ); + pk_free( &key ); } /* END_CASE */ From 33250b046180aa27124410d3914cba53cec51652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 11 Sep 2013 23:46:51 +0200 Subject: [PATCH 30/42] Add test for x509write_pubkey_pem() --- tests/data_files/server1.pubkey | 9 +++++++ tests/suites/test_suite_x509write.data | 4 +++ tests/suites/test_suite_x509write.function | 30 ++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/data_files/server1.pubkey diff --git a/tests/data_files/server1.pubkey b/tests/data_files/server1.pubkey new file mode 100644 index 0000000000..93c669c616 --- /dev/null +++ b/tests/data_files/server1.pubkey @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJl +LhVhXom/uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA +0INq1UFDd185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMP +QPhtgSVfCrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZ +vq1lLGTrlZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokL +BNsupk9wbp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJU +sQIDAQAB +-----END PUBLIC KEY----- diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 1be6c84b73..5a6597665a 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -29,3 +29,7 @@ x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req. Certificate write check Server1 SHA1 depends_on:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15 x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20110212144406":"20210212144406":POLARSSL_MD_SHA1:"data_files/server1.crt" + +Public key write check RSA +depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C +x509_pubkey_check:"data_files/server1.pubkey" diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index bfe07c6a28..d051903885 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -124,3 +124,33 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, mpi_free( &serial ); } /* END_CASE */ + +/* BEGIN_CASE */ +void x509_pubkey_check( char *key_file ) +{ + pk_context key; + unsigned char buf[5000]; + unsigned char check_buf[5000]; + int ret; + size_t olen = sizeof( check_buf ); + FILE *f; + + memset( buf, 0, sizeof( buf ) ); + memset( check_buf, 0, sizeof( check_buf ) ); + + pk_init( &key ); + TEST_ASSERT( x509parse_public_keyfile( &key, key_file ) == 0 ); + + ret = x509write_pubkey_pem( pk_rsa( key ), buf, sizeof( buf ) - 1); + TEST_ASSERT( ret >= 0 ); + + f = fopen( key_file, "r" ); + TEST_ASSERT( f != NULL ); + fread( check_buf, 1, sizeof( check_buf ) - 1, f ); + fclose( f ); + + TEST_ASSERT( strncmp( (char *) buf, (char *) check_buf, sizeof( buf ) ) == 0 ); + + pk_free( &key ); +} +/* END_CASE */ From e1f821a6eb228fe5fb14d98ee92f1092e75072c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 00:59:40 +0200 Subject: [PATCH 31/42] Adapt x509write_pubkey interface to use PK key_app_writer will be fixed later --- include/polarssl/x509write.h | 12 +++++------ library/x509write.c | 23 +++++++++++++++------- tests/suites/test_suite_x509write.function | 3 +-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 5e0d82ad13..159747889d 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -380,19 +380,19 @@ void x509write_crt_free( x509write_cert *ctx ); int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ); /** - * \brief Write a RSA public key to a PKCS#1 DER structure + * \brief Write a public key 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 RSA to write away + * \param key public key 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 ); +int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ); /** * \brief Write a RSA key to a PKCS#1 DER structure @@ -447,15 +447,15 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size ); /** - * \brief Write a RSA public key to a PKCS#1 PEM string + * \brief Write a public key to a PEM string * - * \param rsa RSA to write away + * \param key public key 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 ); +int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ); /** * \brief Write a RSA key to a PKCS#1 PEM string diff --git a/library/x509write.c b/library/x509write.c index e1f68dc6f1..3aeb795265 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -434,11 +434,17 @@ int x509write_crt_set_ns_cert_type( x509write_cert *ctx, return( 0 ); } -int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) +int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) { int ret; unsigned char *c; size_t len = 0; + rsa_context *rsa; + + if( !pk_can_do( key, POLARSSL_PK_RSA ) ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + + rsa = pk_rsa( *key ); c = buf + size; @@ -730,9 +736,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, 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 ) ); - if( !pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - ASN1_CHK_ADD( pub_len, x509write_pubkey_der( pk_rsa( *ctx->key ), + ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; @@ -792,6 +796,11 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) size_t sub_len = 0, pub_len = 0, sig_len = 0; size_t len = 0; + // temporary compatibility hack + pk_context subject_key; + subject_key.pk_info = pk_info_from_type( POLARSSL_PK_RSA ); + subject_key.pk_ctx = ctx->subject_key; + c = tmp_buf + sizeof( tmp_buf ); // Generate correct OID @@ -813,7 +822,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) /* * SubjectPublicKeyInfo */ - ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key, + ASN1_CHK_ADD( pub_len, x509write_pubkey_der( &subject_key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; @@ -959,12 +968,12 @@ int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size ) return( 0 ); } -int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ) +int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ) { int ret; unsigned char output_buf[4096]; - if( ( ret = x509write_pubkey_der( rsa, output_buf, + if( ( ret = x509write_pubkey_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) { return( ret ); diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index d051903885..09dfff874d 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -132,7 +132,6 @@ void x509_pubkey_check( char *key_file ) unsigned char buf[5000]; unsigned char check_buf[5000]; int ret; - size_t olen = sizeof( check_buf ); FILE *f; memset( buf, 0, sizeof( buf ) ); @@ -141,7 +140,7 @@ void x509_pubkey_check( char *key_file ) pk_init( &key ); TEST_ASSERT( x509parse_public_keyfile( &key, key_file ) == 0 ); - ret = x509write_pubkey_pem( pk_rsa( key ), buf, sizeof( buf ) - 1); + ret = x509write_pubkey_pem( &key, buf, sizeof( buf ) - 1); TEST_ASSERT( ret >= 0 ); f = fopen( key_file, "r" ); From 3837daec9eeb63889b22e79454dce1b8154f1a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 01:39:07 +0200 Subject: [PATCH 32/42] Add EC support to x509write_pubkey --- include/polarssl/asn1write.h | 2 +- include/polarssl/ecp.h | 1 + include/polarssl/oid.h | 16 ++++- library/oid.c | 3 + library/x509write.c | 95 +++++++++++++++++++++++--- tests/suites/test_suite_x509write.data | 4 ++ 6 files changed, 111 insertions(+), 10 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 6116502041..1eb7e69ed0 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -29,7 +29,7 @@ #include "asn1.h" -#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret +#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else g += ret; } while( 0 ) #ifdef __cplusplus extern "C" { diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h index ad31bff66d..c7689c1ab6 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -133,6 +133,7 @@ ecp_keypair; */ #define POLARSSL_ECP_MAX_BITS 521 #define POLARSSL_ECP_MAX_BYTES ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 ) +#define POLARSSL_ECP_MAX_PT_LEN ( 2 * POLARSSL_ECP_MAX_BYTES + 1 ) /* * Maximum window size (actually, NAF width) used for point multipliation. diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index b0e781fc1f..6981237f7f 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -370,8 +370,9 @@ int oid_get_attr_short_name( const asn1_buf *oid, const char **short_name ); */ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); +#if defined(POLARSSL_ECP_C) /** - * \brief Translate ECParameters OID into an EC group identifier + * \brief Translate NamedCurve OID into an EC group identifier * * \param oid OID to use * \param grp_id place to store group id @@ -380,6 +381,19 @@ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); */ int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id ); +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_ec_grp( ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* POLARSSL_ECP_C */ + #if defined(POLARSSL_MD_C) /** * \brief Translate SignatureAlgorithm OID into md_type and pk_type diff --git a/library/oid.c b/library/oid.c index f37bbf6e72..1aaf8e8873 100644 --- a/library/oid.c +++ b/library/oid.c @@ -369,6 +369,7 @@ static const oid_pk_alg_t oid_pk_alg[] = FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg); FN_OID_GET_ATTR1(oid_get_pk_alg, oid_pk_alg_t, pk_alg, pk_type_t, pk_alg); +#if defined(POLARSSL_ECP_C) /* * For namedCurve (RFC 5480) */ @@ -407,6 +408,8 @@ static const oid_ecp_grp_t oid_ecp_grp[] = FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp); FN_OID_GET_ATTR1(oid_get_ec_grp, oid_ecp_grp_t, grp_id, ecp_group_id, grp_id); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, ecp_group_id, grp_id); +#endif /* POLARSSL_ECP_C */ #if defined(POLARSSL_CIPHER_C) /* diff --git a/library/x509write.c b/library/x509write.c index 3aeb795265..6be1bc48e9 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -117,6 +117,7 @@ exit: return( ret ); } +#if defined(POLARSSL_RSA_C) /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n @@ -137,6 +138,56 @@ static int x509_write_rsa_pubkey( unsigned char **p, unsigned char *start, return( len ); } +#endif /* POLARSSL_RSA_C */ + +#if defined(POLARSSL_ECP_C) +/* + * EC public key is an EC point + */ +static int x509_write_ec_pubkey( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[POLARSSL_ECP_MAX_PT_LEN]; + + if( ( ret = ecp_point_write_binary( &ec->grp, &ec->Q, + POLARSSL_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p - start < (int) len ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int x509_write_ec_algparam( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); + + return( len ); +} +#endif /* POLARSSL_ECP_C */ void x509write_csr_init( x509write_csr *ctx ) { @@ -439,16 +490,20 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) int ret; unsigned char *c; size_t len = 0; - rsa_context *rsa; - - if( !pk_can_do( key, POLARSSL_PK_RSA ) ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - - rsa = pk_rsa( *key ); c = buf + size; - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, rsa ) ); +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, pk_rsa( *key ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + ASN1_CHK_ADD( len, x509_write_ec_pubkey( &c, buf, pk_ec( *key ) ) ); + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); if( c - buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); @@ -464,8 +519,32 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + size_t alg_len = 0; + + ASN1_CHK_ADD( alg_len, x509_write_ec_algparam( &c, buf, + pk_ec( *key ) ) ); + + ASN1_CHK_ADD( alg_len, asn1_write_oid( &c, buf, + OID_EC_ALG_UNRESTRICTED, OID_SIZE( OID_EC_ALG_UNRESTRICTED ) ) ); + + ASN1_CHK_ADD( alg_len, asn1_write_len( &c, buf, alg_len ) ); + ASN1_CHK_ADD( alg_len, asn1_write_tag( &c, buf, + ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + len += alg_len; + } + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 5a6597665a..22d338c416 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -33,3 +33,7 @@ x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1 Public key write check RSA depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C x509_pubkey_check:"data_files/server1.pubkey" + +Public key write check EC +depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C +x509_pubkey_check:"data_files/ec_pub.pem" From edda9041fc8d062922234b51bced3d454eda49ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 02:17:54 +0200 Subject: [PATCH 33/42] Adapt asn1_write_algorithm_identifier() to params --- include/polarssl/asn1write.h | 6 ++++-- include/polarssl/oid.h | 16 ++++++++++++-- library/asn1write.c | 12 +++++------ library/oid.c | 1 + library/x509write.c | 42 ++++++++++++++---------------------- 5 files changed, 41 insertions(+), 36 deletions(-) diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 1eb7e69ed0..d7f7b521a2 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -115,17 +115,19 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, /** * \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 * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added * * \return the length written or a negative error code */ int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ); + const char *oid, size_t oid_len, + size_t par_len ); /** * \brief Write a boolean tag (ASN1_BOOLEAN) and value in ASN.1 format diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index 6981237f7f..ba0ce7d39f 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -370,6 +370,18 @@ int oid_get_attr_short_name( const asn1_buf *oid, const char **short_name ); */ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND + */ +int oid_get_oid_by_pk_alg( pk_type_t pk_alg, + const char **oid, size_t *olen ); + #if defined(POLARSSL_ECP_C) /** * \brief Translate NamedCurve OID into an EC group identifier @@ -382,9 +394,9 @@ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg ); int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id ); /** - * \brief Translate EC group identifier into NamedCurve OID + * \brief Translate EC group identifier into NamedCurve OID * - * \param grp_id EC group identifier + * \param grp_id EC group identifier * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * diff --git a/library/asn1write.c b/library/asn1write.c index f720a80673..d4c1d8d027 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -158,17 +158,17 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, } int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ) + const char *oid, size_t oid_len, + size_t par_len ) { int ret; size_t len = 0; - // Write NULL - // - ASN1_CHK_ADD( len, asn1_write_null( p, start ) ); + if( par_len == 0 ) + ASN1_CHK_ADD( len, asn1_write_null( p, start ) ); + else + len += par_len; - // Write OID - // ASN1_CHK_ADD( len, asn1_write_oid( p, start, oid, oid_len ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); diff --git a/library/oid.c b/library/oid.c index 1aaf8e8873..81b313e338 100644 --- a/library/oid.c +++ b/library/oid.c @@ -368,6 +368,7 @@ static const oid_pk_alg_t oid_pk_alg[] = FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg); FN_OID_GET_ATTR1(oid_get_pk_alg, oid_pk_alg_t, pk_alg, pk_type_t, pk_alg); +FN_OID_GET_OID_BY_ATTR1(oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, pk_type_t, pk_alg); #if defined(POLARSSL_ECP_C) /* diff --git a/library/x509write.c b/library/x509write.c index 6be1bc48e9..4eaeb5106f 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -172,8 +172,8 @@ static int x509_write_ec_pubkey( unsigned char **p, unsigned char *start, * namedCurve OBJECT IDENTIFIER * } */ -static int x509_write_ec_algparam( unsigned char **p, unsigned char *start, - ecp_keypair *ec ) +static int x509_write_ec_param( unsigned char **p, unsigned char *start, + ecp_keypair *ec ) { int ret; size_t len = 0; @@ -489,7 +489,8 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) { int ret; unsigned char *c; - size_t len = 0; + size_t len = 0, par_len = 0, oid_len; + const char *oid; c = buf + size; @@ -519,32 +520,21 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); -#if defined(POLARSSL_RSA_C) - if( pk_get_type( key ) == POLARSSL_PK_RSA ) - ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, - OID_PKCS1_RSA, OID_SIZE( OID_PKCS1_RSA ) ) ); - else -#endif + if( ( ret = oid_get_oid_by_pk_alg( pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + #if defined(POLARSSL_ECP_C) if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) { - size_t alg_len = 0; - - ASN1_CHK_ADD( alg_len, x509_write_ec_algparam( &c, buf, - pk_ec( *key ) ) ); - - ASN1_CHK_ADD( alg_len, asn1_write_oid( &c, buf, - OID_EC_ALG_UNRESTRICTED, OID_SIZE( OID_EC_ALG_UNRESTRICTED ) ) ); - - ASN1_CHK_ADD( alg_len, asn1_write_len( &c, buf, alg_len ) ); - ASN1_CHK_ADD( alg_len, asn1_write_tag( &c, buf, - ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - - len += alg_len; + ASN1_CHK_ADD( par_len, x509_write_ec_param( &c, buf, pk_ec( *key ) ) ); } - else #endif - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + + ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); @@ -689,7 +679,7 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, // Write OID // ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( p, start, oid, - oid_len ) ); + oid_len, 0 ) ); return( len ); } @@ -937,7 +927,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) * Signature ::= AlgorithmIdentifier */ ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, - sig_oid, strlen( sig_oid ) ) ); + sig_oid, strlen( sig_oid ), 0 ) ); /* * Serial ::= INTEGER From 0088c69fbf30a1f4d18e83378641f25bb71d1237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 02:38:04 +0200 Subject: [PATCH 34/42] Complete x509write_csr support for EC key No automated test yet (complicated by the fact that ECDSA signatures are not deterministic), tested using cert_req (and openssl for verification). --- library/x509write.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/x509write.c b/library/x509write.c index 4eaeb5106f..e769edbe49 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -779,6 +779,7 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; + pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf @@ -828,9 +829,13 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); + pk_alg = pk_get_type( ctx->key ); + if( pk_alg == POLARSSL_PK_ECKEY ) + pk_alg = POLARSSL_PK_ECDSA; + if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 || - ( ret = oid_get_oid_by_sig_alg( pk_get_type( ctx->key ), ctx->md_alg, + ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); From 7f1f0926e4306274173243ba29417477df9ad928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 03:31:34 +0200 Subject: [PATCH 35/42] Add test for x509write_key --- library/x509write.c | 21 ---------------- tests/suites/test_suite_x509write.data | 4 +++ tests/suites/test_suite_x509write.function | 29 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index e769edbe49..937b899fc0 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -563,27 +563,6 @@ int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - // TODO: Make NON RSA Specific variant later on -/* *--c = 0; - len += 1; - - len += asn1_write_len( &c, len); - len += asn1_write_tag( &c, ASN1_BIT_STRING ); - - len += asn1_write_oid( &c, OID_PKCS1_RSA ); - - len += asn1_write_int( &c, 0 ); - - len += asn1_write_len( &c, len); - len += asn1_write_tag( &c, ASN1_CONSTRUCTED | ASN1_SEQUENCE );*/ - -/* for(i = 0; i < len; ++i) - { - if (i % 16 == 0 ) printf("\n"); - printf("%02x ", c[i]); - } - printf("\n");*/ - return( len ); } diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 22d338c416..0c300d5439 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -37,3 +37,7 @@ x509_pubkey_check:"data_files/server1.pubkey" Public key write check EC depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C x509_pubkey_check:"data_files/ec_pub.pem" + +Private key write check RSA +depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C +x509_key_check:"data_files/server1.key" diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 09dfff874d..13931036bd 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -153,3 +153,32 @@ void x509_pubkey_check( char *key_file ) pk_free( &key ); } /* END_CASE */ + +/* BEGIN_CASE */ +void x509_key_check( char *key_file ) +{ + pk_context key; + unsigned char buf[5000]; + unsigned char check_buf[5000]; + int ret; + FILE *f; + + memset( buf, 0, sizeof( buf ) ); + memset( check_buf, 0, sizeof( check_buf ) ); + + pk_init( &key ); + TEST_ASSERT( x509parse_keyfile( &key, key_file, NULL ) == 0 ); + + ret = x509write_key_pem( pk_rsa( key ), buf, sizeof( buf ) - 1); + TEST_ASSERT( ret >= 0 ); + + f = fopen( key_file, "r" ); + TEST_ASSERT( f != NULL ); + fread( check_buf, 1, sizeof( check_buf ) - 1, f ); + fclose( f ); + + TEST_ASSERT( strncmp( (char *) buf, (char *) check_buf, sizeof( buf ) ) == 0 ); + + pk_free( &key ); +} +/* END_CASE */ From 6de63e480d77857c271f56d72d8d53ad43ac4837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 04:59:34 +0200 Subject: [PATCH 36/42] Add EC support to x509write_key --- include/polarssl/x509write.h | 12 +-- library/x509parse.c | 2 +- library/x509write.c | 119 +++++++++++++++++---- tests/suites/test_suite_x509write.function | 2 +- 4 files changed, 108 insertions(+), 27 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 159747889d..a063695c8b 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -395,19 +395,19 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ); int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ); /** - * \brief Write a RSA key to a PKCS#1 DER structure + * \brief Write a private key to a PKCS#1 or SEC1 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 key private 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 ); +int x509write_key_der( pk_context *pk, unsigned char *buf, size_t size ); /** * \brief Write a CSR (Certificate Signing Request) to a @@ -458,15 +458,15 @@ int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size ); int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ); /** - * \brief Write a RSA key to a PKCS#1 PEM string + * \brief Write a private key to a PKCS#1 or SEC1 PEM string * - * \param rsa RSA to write away + * \param key private 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 ); +int x509write_key_pem( pk_context *key, unsigned char *buf, size_t size ); /** * \brief Write a CSR (Certificate Signing Request) to a diff --git a/library/x509parse.c b/library/x509parse.c index fc84e6164d..b3725a7c27 100644 --- a/library/x509parse.c +++ b/library/x509parse.c @@ -2521,7 +2521,7 @@ static int x509parse_key_sec1_der( ecp_keypair *eck, unsigned char *end2; /* - * RFC 5915, orf SEC1 Appendix C.4 + * RFC 5915, or SEC1 Appendix C.4 * * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), diff --git a/library/x509write.c b/library/x509write.c index 937b899fc0..d55e24187a 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -542,26 +542,86 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) return( len ); } -int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) +int x509write_key_der( pk_context *key, unsigned char *buf, size_t size ) { int ret; - unsigned char *c; + unsigned char *c = buf + size; size_t len = 0; - c = buf + size; +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + { + rsa_context *rsa = pk_rsa( *key ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); - ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); - ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->QP ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DQ ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->DP ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->Q ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->P ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->D ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 0 ) ); - ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); - ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + } + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + ecp_keypair *ec = pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + ASN1_CHK_ADD( pub_len, x509_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); + ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, ASN1_BIT_STRING ) ); + + ASN1_CHK_ADD( pub_len, asn1_write_len( &c, buf, pub_len ) ); + ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, buf, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + ASN1_CHK_ADD( par_len, x509_write_ec_param( &c, buf, ec ) ); + + ASN1_CHK_ADD( par_len, asn1_write_len( &c, buf, par_len ) ); + ASN1_CHK_ADD( par_len, asn1_write_tag( &c, buf, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey: write as MPI then fix tag */ + ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &ec->d ) ); + *c = ASN1_OCTET_STRING; + + /* version */ + ASN1_CHK_ADD( len, asn1_write_int( &c, buf, 1 ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + } + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); return( len ); } @@ -957,8 +1017,10 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) #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" +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" #if defined(POLARSSL_BASE64_C) static int x509write_pemify( const char *begin_str, const char *end_str, @@ -1042,18 +1104,37 @@ int x509write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ) return( 0 ); } -int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ) +int x509write_key_pem( pk_context *key, unsigned char *buf, size_t size ) { int ret; unsigned char output_buf[4096]; + char *begin, *end; - if( ( ret = x509write_key_der( rsa, output_buf, + if( ( ret = x509write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) { return( ret ); } - if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY, +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + + if( ( ret = x509write_pemify( begin, end, output_buf + sizeof(output_buf) - ret, ret, buf, size ) ) != 0 ) { diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 13931036bd..c2d4e4eee4 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -169,7 +169,7 @@ void x509_key_check( char *key_file ) pk_init( &key ); TEST_ASSERT( x509parse_keyfile( &key, key_file, NULL ) == 0 ); - ret = x509write_key_pem( pk_rsa( key ), buf, sizeof( buf ) - 1); + ret = x509write_key_pem( &key, buf, sizeof( buf ) - 1); TEST_ASSERT( ret >= 0 ); f = fopen( key_file, "r" ); From f38e71afd516ca5e3def416015ec73d18c18b746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 05:21:54 +0200 Subject: [PATCH 37/42] Convert x509write_crt interface to PK --- include/polarssl/x509write.h | 8 ++--- library/x509write.c | 8 ++--- programs/x509/cert_write.c | 38 ++++++++++++---------- tests/suites/test_suite_x509write.function | 18 +++++----- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index a063695c8b..40db9e7677 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -259,17 +259,17 @@ int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name ); * \brief Set the subject public key for the certificate * * \param ctx CRT context to use - * \param rsa RSA public key to include + * \param key public key to include */ -void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa ); +void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ); /** * \brief Set the issuer key used for signing the certificate * * \param ctx CRT context to use - * \param rsa RSA key to sign with + * \param key private key to sign with */ -void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa ); +void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ); /** * \brief Set the MD algorithm to use for the signature diff --git a/library/x509write.c b/library/x509write.c index d55e24187a..d8000f0157 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -312,14 +312,14 @@ void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ) ctx->md_alg = md_alg; } -void x509write_crt_set_subject_key( x509write_cert *ctx, rsa_context *rsa ) +void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ) { - ctx->subject_key = rsa; + ctx->subject_key = pk_rsa( *key ); } -void x509write_crt_set_issuer_key( x509write_cert *ctx, rsa_context *rsa ) +void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ) { - ctx->issuer_key = rsa; + ctx->issuer_key = pk_rsa( *key ); } int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name ) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index f0939c8f2b..8943493e9b 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -172,9 +172,9 @@ int main( int argc, char *argv[] ) { int ret = 0; x509_cert issuer_crt; - rsa_context loaded_issuer_rsa, loaded_subject_rsa; - rsa_context *issuer_rsa = &loaded_issuer_rsa, - *subject_rsa = &loaded_subject_rsa; + pk_context loaded_issuer_key, loaded_subject_key; + pk_context *issuer_key = &loaded_issuer_key, + *subject_key = &loaded_subject_key; char buf[1024]; char issuer_name[128]; char subject_name[128]; @@ -189,8 +189,8 @@ int main( int argc, char *argv[] ) */ x509write_crt_init( &crt ); x509write_crt_set_md_alg( &crt, POLARSSL_MD_SHA1 ); - rsa_init( &loaded_issuer_rsa, RSA_PKCS_V15, 0 ); - rsa_init( &loaded_subject_rsa, RSA_PKCS_V15, 0 ); + pk_init( &loaded_issuer_key ); + pk_init( &loaded_subject_key ); mpi_init( &serial ); memset( &csr, 0, sizeof(x509_csr) ); memset( &issuer_crt, 0, sizeof(x509_cert) ); @@ -417,7 +417,7 @@ int main( int argc, char *argv[] ) } opt.subject_name = subject_name; - subject_rsa = pk_rsa( csr.pk ); + subject_key = &csr.pk; printf( " ok\n" ); } @@ -430,12 +430,12 @@ int main( int argc, char *argv[] ) printf( " . Loading the subject key ..." ); fflush( stdout ); - ret = x509parse_keyfile_rsa( &loaded_subject_rsa, opt.subject_key, - opt.subject_pwd ); + ret = x509parse_keyfile( &loaded_subject_key, opt.subject_key, + opt.subject_pwd ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509parse_keyfile_rsa returned -0x%02x - %s\n\n", -ret, buf ); + printf( " failed\n ! x509parse_keyfile returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -445,12 +445,12 @@ int main( int argc, char *argv[] ) printf( " . Loading the issuer key ..." ); fflush( stdout ); - ret = x509parse_keyfile_rsa( &loaded_issuer_rsa, opt.issuer_key, + ret = x509parse_keyfile( &loaded_issuer_key, opt.issuer_key, opt.issuer_pwd ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509parse_keyfile_rsa returned -x%02x - %s\n\n", -ret, buf ); + printf( " failed\n ! x509parse_keyfile returned -x%02x - %s\n\n", -ret, buf ); goto exit; } @@ -459,8 +459,10 @@ int main( int argc, char *argv[] ) if( strlen( opt.issuer_crt ) ) { if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) || - mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N, &issuer_rsa->N ) != 0 || - mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E, &issuer_rsa->E ) != 0 ) + mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N, + &pk_rsa( *issuer_key )->N ) != 0 || + mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E, + &pk_rsa( *issuer_key )->E ) != 0 ) { printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); ret = -1; @@ -473,11 +475,11 @@ int main( int argc, char *argv[] ) if( opt.selfsign ) { opt.issuer_name = opt.subject_name; - subject_rsa = issuer_rsa; + subject_key = issuer_key; } - x509write_crt_set_subject_key( &crt, subject_rsa ); - x509write_crt_set_issuer_key( &crt, issuer_rsa ); + x509write_crt_set_subject_key( &crt, subject_key ); + x509write_crt_set_issuer_key( &crt, issuer_key ); /* * 1.0. Check the names for validity @@ -606,8 +608,8 @@ int main( int argc, char *argv[] ) exit: x509write_crt_free( &crt ); - rsa_free( &loaded_subject_rsa ); - rsa_free( &loaded_issuer_rsa ); + pk_free( &loaded_subject_key ); + pk_free( &loaded_issuer_key ); mpi_free( &serial ); #if defined(_WIN32) diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index c2d4e4eee4..f916b1cf20 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -66,7 +66,7 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, char *serial_str, char *not_before, char *not_after, int md_type, char *cert_check_file ) { - rsa_context subject_rsa, issuer_rsa; + pk_context subject_key, issuer_key; pem_context pem; x509write_cert crt; unsigned char *c; @@ -78,12 +78,12 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, FILE *f; mpi_init( &serial ); - rsa_init( &subject_rsa, RSA_PKCS_V15, 0 ); - rsa_init( &issuer_rsa, RSA_PKCS_V15, 0 ); + pk_init( &subject_key ); + pk_init( &issuer_key ); - TEST_ASSERT( x509parse_keyfile_rsa( &subject_rsa, subject_key_file, + TEST_ASSERT( x509parse_keyfile( &subject_key, subject_key_file, subject_pwd ) == 0 ); - TEST_ASSERT( x509parse_keyfile_rsa( &issuer_rsa, issuer_key_file, + TEST_ASSERT( x509parse_keyfile( &issuer_key, issuer_key_file, issuer_pwd ) == 0 ); TEST_ASSERT( mpi_read_string( &serial, 10, serial_str ) == 0 ); @@ -94,8 +94,8 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, x509write_crt_set_md_alg( &crt, md_type ); TEST_ASSERT( x509write_crt_set_issuer_name( &crt, issuer_name ) == 0 ); TEST_ASSERT( x509write_crt_set_subject_name( &crt, subject_name ) == 0 ); - x509write_crt_set_subject_key( &crt, &subject_rsa ); - x509write_crt_set_issuer_key( &crt, &issuer_rsa ); + x509write_crt_set_subject_key( &crt, &subject_key ); + x509write_crt_set_issuer_key( &crt, &issuer_key ); TEST_ASSERT( x509write_crt_set_basic_constraints( &crt, 0, 0 ) == 0 ); TEST_ASSERT( x509write_crt_set_subject_key_identifier( &crt ) == 0 ); @@ -118,8 +118,8 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); x509write_crt_free( &crt ); - rsa_free( &issuer_rsa ); - rsa_free( &subject_rsa ); + pk_free( &issuer_key ); + pk_free( &subject_key ); pem_free( &pem ); mpi_free( &serial ); } From 53c642504ee4f5363e6398062beeff48c43876f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 05:39:46 +0200 Subject: [PATCH 38/42] Use PK internally for x509write_crt --- include/polarssl/x509write.h | 4 +-- library/x509write.c | 61 ++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 40db9e7677..3aa76c65a1 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -86,8 +86,8 @@ typedef struct _x509write_cert { int version; mpi serial; - rsa_context *subject_key; - rsa_context *issuer_key; + pk_context *subject_key; + pk_context *issuer_key; asn1_named_data *subject; asn1_named_data *issuer; md_type_t md_alg; diff --git a/library/x509write.c b/library/x509write.c index d8000f0157..2b1688b0e7 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -314,12 +314,12 @@ void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg ) void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key ) { - ctx->subject_key = pk_rsa( *key ); + ctx->subject_key = key; } void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key ) { - ctx->issuer_key = pk_rsa( *key ); + ctx->issuer_key = key; } int x509write_crt_set_subject_name( x509write_cert *ctx, char *subject_name ) @@ -404,8 +404,12 @@ int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ) unsigned char *c = buf + sizeof(buf); size_t len = 0; + if( pk_get_type( ctx->subject_key ) != POLARSSL_PK_RSA ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + memset( buf, 0, sizeof(buf)); - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->subject_key ) ); + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, + pk_rsa( *ctx->subject_key ) ) ); sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); c = buf + sizeof(buf) - 20; @@ -426,8 +430,12 @@ int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) unsigned char *c = buf + sizeof(buf); size_t len = 0; + if( pk_get_type( ctx->issuer_key ) != POLARSSL_PK_RSA ) + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + memset( buf, 0, sizeof(buf)); - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, ctx->issuer_key ) ); + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, + pk_rsa( *ctx->issuer_key ) ) ); sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); c = buf + sizeof(buf) - 20; @@ -906,22 +914,25 @@ int x509write_crt_der( x509write_cert *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_and_oid_len = 0, sig_len; size_t len = 0; + pk_type_t pk_alg; - // temporary compatibility hack - pk_context subject_key; - subject_key.pk_info = pk_info_from_type( POLARSSL_PK_RSA ); - subject_key.pk_ctx = ctx->subject_key; - + /* + * Prepare data to be signed in tmp_buf + */ c = tmp_buf + sizeof( tmp_buf ); - // Generate correct OID - // - ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid, - &sig_oid_len ); - if( ret != 0 ) + /* Signature algorithm needed in TBS, and later for actual signature */ + pk_alg = pk_get_type( ctx->issuer_key ); + if( pk_alg == POLARSSL_PK_ECKEY ) + pk_alg = POLARSSL_PK_ECDSA; + + if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { return( ret ); + } /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension @@ -935,7 +946,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) /* * SubjectPublicKeyInfo */ - ASN1_CHK_ADD( pub_len, x509write_pubkey_der( &subject_key, + ASN1_CHK_ADD( pub_len, x509write_pubkey_der( ctx->subject_key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; @@ -990,18 +1001,28 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) 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 ) ); + /* + * Make signature + */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); - rsa_pkcs1_sign( ctx->issuer_key, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); + if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, + NULL, NULL ) ) != 0 ) + { + return( ret ); + } + /* + * Write data to output buffer + */ c2 = buf + size; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, - sig, ctx->issuer_key->len ) ); + ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, + sig_oid, sig_oid_len, sig, sig_len ) ); c2 -= len; memcpy( c2, c, len ); - len += sig_len; + len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); From 31e59400d2956de434e9960c7e5b0fe225bfa0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 05:59:05 +0200 Subject: [PATCH 39/42] Add missing f_rng/p_rng arguments to x509write_crt --- include/polarssl/x509write.h | 22 +++++++- library/x509write.c | 14 +++-- programs/x509/cert_req.c | 12 +++-- programs/x509/cert_write.c | 60 ++++++++++++++++------ tests/suites/test_suite_x509write.function | 5 +- 5 files changed, 85 insertions(+), 28 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 3aa76c65a1..715a646069 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -373,11 +373,20 @@ void x509write_crt_free( x509write_cert *ctx ); * \param crt certificate to write away * \param buf buffer to write to * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. */ -int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ); +int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** * \brief Write a public key to a DER structure @@ -441,10 +450,19 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, * \param crt certificate to write away * \param buf buffer to write to * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter * * \return 0 successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. */ -int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size ); +int x509write_crt_pem( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** * \brief Write a public key to a PEM string diff --git a/library/x509write.c b/library/x509write.c index 2b1688b0e7..dffdf74544 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -905,7 +905,9 @@ int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, return( len ); } -int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) +int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; const char *sig_oid; @@ -1007,7 +1009,7 @@ int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size ) md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, - NULL, NULL ) ) != 0 ) + f_rng, p_rng ) ) != 0 ) { return( ret ); } @@ -1083,13 +1085,15 @@ static int x509write_pemify( const char *begin_str, const char *end_str, return( 0 ); } -int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size ) +int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; unsigned char output_buf[4096]; - if( ( ret = x509write_crt_der( crt, output_buf, - sizeof(output_buf) ) ) < 0 ) + if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf), + f_rng, p_rng ) ) < 0 ) { return( ret ); } diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index b98f23368b..e65fb97e61 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -34,19 +34,21 @@ #include "polarssl/config.h" #include "polarssl/x509write.h" -#include "polarssl/error.h" #include "polarssl/entropy.h" #include "polarssl/ctr_drbg.h" +#include "polarssl/error.h" -#if !defined(POLARSSL_X509_PARSE_C) || !defined(POLARSSL_FS_IO) || \ - !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \ +#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_X509_PARSE_C) || \ + !defined(POLARSSL_FS_IO) || \ + !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \ !defined(POLARSSL_ERROR_C) int main( int argc, char *argv[] ) { ((void) argc); ((void) argv); - printf( "POLARSSL_X509_PARSE_C and/or POLARSSL_FS_IO and/or " + printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_X509_PARSE_C and/or " + "POLARSSL_FS_IO and/or " "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or " "POLARSSL_ERROR_C not defined.\n"); return( 0 ); @@ -333,6 +335,6 @@ exit: return( ret ); } -#endif /* POLARSSL_X509_PARSE_C && POLARSSL_FS_IO && +#endif /* POLARSSL_X509_WRITE_C && POLARSSL_X509_PARSE_C && POLARSSL_FS_IO && POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C && POLARSSL_ERROR_C */ diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 8943493e9b..37cea589ef 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -33,24 +33,24 @@ #include "polarssl/config.h" -#include "polarssl/error.h" -#include "polarssl/rsa.h" -#include "polarssl/x509.h" -#include "polarssl/base64.h" #include "polarssl/x509write.h" -#include "polarssl/oid.h" +#include "polarssl/entropy.h" +#include "polarssl/ctr_drbg.h" +#include "polarssl/error.h" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO) || \ +#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_X509_PARSE_C) || \ + !defined(POLARSSL_FS_IO) || \ + !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \ !defined(POLARSSL_ERROR_C) int main( int argc, char *argv[] ) { ((void) argc); ((void) argv); - printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO and/or " - "POLARSSL_ERROR_C not defined.\n"); + printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_X509_PARSE_C and/or " + "POLARSSL_FS_IO and/or " + "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or " + "POLARSSL_ERROR_C not defined.\n"); return( 0 ); } #else @@ -97,7 +97,9 @@ struct options unsigned char ns_cert_type; /* NS cert type */ } opt; -int write_certificate( x509write_cert *crt, char *output_file ) +int write_certificate( x509write_cert *crt, char *output_file, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; FILE *f; @@ -105,7 +107,7 @@ int write_certificate( x509write_cert *crt, char *output_file ) size_t len = 0; memset( output_buf, 0, 4096 ); - if( ( ret = x509write_crt_pem( crt, output_buf, 4096 ) ) < 0 ) + if( ( ret = x509write_crt_pem( crt, output_buf, 4096, f_rng, p_rng ) ) < 0 ) return( ret ); len = strlen( (char *) output_buf ); @@ -183,6 +185,9 @@ int main( int argc, char *argv[] ) x509_csr csr; x509write_cert crt; mpi serial; + entropy_context entropy; + ctr_drbg_context ctr_drbg; + const char *pers = "crt example app"; /* * Set to sane values @@ -350,8 +355,29 @@ int main( int argc, char *argv[] ) printf("\n"); + /* + * 0. Seed the PRNG + */ + printf( " . Seeding the random number generator..." ); + fflush( stdout ); + + entropy_init( &entropy ); + if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, + (const unsigned char *) pers, + strlen( pers ) ) ) != 0 ) + { + error_strerror( ret, buf, 1024 ); + printf( " failed\n ! ctr_drbg_init returned %d - %s\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + // Parse serial to MPI // + printf( " . Reading serial number..." ); + fflush( stdout ); + if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) { error_strerror( ret, buf, 1024 ); @@ -359,6 +385,8 @@ int main( int argc, char *argv[] ) goto exit; } + printf( " ok\n" ); + // Parse issuer certificate if present // if( !opt.selfsign && strlen( opt.issuer_crt ) ) @@ -597,7 +625,8 @@ int main( int argc, char *argv[] ) printf( " . Writing the certificate..." ); fflush( stdout ); - if( ( ret = write_certificate( &crt, opt.output_file ) ) != 0 ) + if( ( ret = write_certificate( &crt, opt.output_file, + ctr_drbg_random, &ctr_drbg ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf ); @@ -619,5 +648,6 @@ exit: return( ret ); } -#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && - POLARSSet_serial_X509_WRITE_C && POLARSSL_FS_IO */ +#endif /* POLARSSL_X509_WRITE_C && POLARSSL_X509_PARSE_C && POLARSSL_FS_IO && + POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C && + POLARSSL_ERROR_C */ diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index f916b1cf20..9352c9ea2f 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -76,7 +76,9 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, int ret; size_t olen = sizeof( check_buf ); FILE *f; + rnd_pseudo_info rnd_info; + memset( &rnd_info, 0x2a, sizeof( rnd_pseudo_info ) ); mpi_init( &serial ); pk_init( &subject_key ); pk_init( &issuer_key ); @@ -101,7 +103,8 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, TEST_ASSERT( x509write_crt_set_subject_key_identifier( &crt ) == 0 ); TEST_ASSERT( x509write_crt_set_authority_key_identifier( &crt ) == 0 ); - ret = x509write_crt_der( &crt, buf, sizeof(buf) ); + ret = x509write_crt_der( &crt, buf, sizeof(buf), + rnd_pseudo_rand, &rnd_info ); TEST_ASSERT( ret >= 0 ); c = buf + sizeof( buf ) - ret; From bb323ffc7c04abe5e56ebbe1fdd0b4714c01d0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 06:26:54 +0200 Subject: [PATCH 40/42] Complete EC support in x509write_crt --- library/x509write.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/library/x509write.c b/library/x509write.c index dffdf74544..d4861d77d8 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -189,6 +189,27 @@ static int x509_write_ec_param( unsigned char **p, unsigned char *start, } #endif /* POLARSSL_ECP_C */ +static int x509_write_pubkey( unsigned char **p, unsigned char *start, + const pk_context *key ) +{ + int ret; + size_t len = 0; + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( key ) == POLARSSL_PK_RSA ) + ASN1_CHK_ADD( len, x509_write_rsa_pubkey( p, start, pk_rsa( *key ) ) ); + else +#endif +#if defined(POLARSSL_ECP_C) + if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) + ASN1_CHK_ADD( len, x509_write_ec_pubkey( p, start, pk_ec( *key ) ) ); + else +#endif + return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + + return( len ); +} + void x509write_csr_init( x509write_csr *ctx ) { memset( ctx, 0, sizeof(x509write_csr) ); @@ -404,12 +425,8 @@ int x509write_crt_set_subject_key_identifier( x509write_cert *ctx ) unsigned char *c = buf + sizeof(buf); size_t len = 0; - if( pk_get_type( ctx->subject_key ) != POLARSSL_PK_RSA ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - memset( buf, 0, sizeof(buf)); - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, - pk_rsa( *ctx->subject_key ) ) ); + ASN1_CHK_ADD( len, x509_write_pubkey( &c, buf, ctx->subject_key ) ); sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); c = buf + sizeof(buf) - 20; @@ -430,12 +447,8 @@ int x509write_crt_set_authority_key_identifier( x509write_cert *ctx ) unsigned char *c = buf + sizeof(buf); size_t len = 0; - if( pk_get_type( ctx->issuer_key ) != POLARSSL_PK_RSA ) - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); - memset( buf, 0, sizeof(buf)); - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, - pk_rsa( *ctx->issuer_key ) ) ); + ASN1_CHK_ADD( len, x509_write_pubkey( &c, buf, ctx->issuer_key ) ); sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); c = buf + sizeof(buf) - 20; @@ -502,17 +515,7 @@ int x509write_pubkey_der( pk_context *key, unsigned char *buf, size_t size ) c = buf + size; -#if defined(POLARSSL_RSA_C) - if( pk_get_type( key ) == POLARSSL_PK_RSA ) - ASN1_CHK_ADD( len, x509_write_rsa_pubkey( &c, buf, pk_rsa( *key ) ) ); - else -#endif -#if defined(POLARSSL_ECP_C) - if( pk_get_type( key ) == POLARSSL_PK_ECKEY ) - ASN1_CHK_ADD( len, x509_write_ec_pubkey( &c, buf, pk_ec( *key ) ) ); - else -#endif - return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE ); + ASN1_CHK_ADD( len, x509_write_pubkey( &c, buf, key ) ); if( c - buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); From 26b4d45f49aff3ba955aedee2b4c4a8d008fbb8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 06:56:06 +0200 Subject: [PATCH 41/42] Fix key_app_writer --- programs/pkey/key_app_writer.c | 103 +++++++++++++++++++-------------- programs/x509/cert_req.c | 35 ++++++----- 2 files changed, 79 insertions(+), 59 deletions(-) diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c index d9ab45c941..371b03a53a 100644 --- a/programs/pkey/key_app_writer.c +++ b/programs/pkey/key_app_writer.c @@ -33,21 +33,16 @@ #include "polarssl/config.h" -#include "polarssl/error.h" -#include "polarssl/rsa.h" -#include "polarssl/x509.h" -#include "polarssl/base64.h" #include "polarssl/x509write.h" +#include "polarssl/error.h" -#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ - !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO) +#if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_FS_IO) int main( int argc, char *argv[] ) { ((void) argc); ((void) argv); - printf("POLARSSL_BIGNUM_C and/or POLARSSL_RSA_C and/or " - "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO not defined.\n"); + printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_FS_IO not defined.\n" ); return( 0 ); } #else @@ -82,7 +77,7 @@ struct options int output_format; /* the output format to use */ } opt; -static int write_public_key( rsa_context *rsa, const char *output_file ) +static int write_public_key( pk_context *key, const char *output_file ) { int ret; FILE *f; @@ -94,14 +89,14 @@ static int write_public_key( rsa_context *rsa, const char *output_file ) if( opt.output_format == OUTPUT_FORMAT_PEM ) { - if( ( ret = x509write_pubkey_pem( rsa, output_buf, 16000 ) ) != 0 ) + if( ( ret = x509write_pubkey_pem( key, output_buf, 16000 ) ) != 0 ) return( ret ); len = strlen( (char *) output_buf ); } else { - if( ( ret = x509write_pubkey_der( rsa, output_buf, 16000 ) ) < 0 ) + if( ( ret = x509write_pubkey_der( key, output_buf, 16000 ) ) < 0 ) return( ret ); len = ret; @@ -119,7 +114,7 @@ static int write_public_key( rsa_context *rsa, const char *output_file ) return( 0 ); } -static int write_private_key( rsa_context *rsa, const char *output_file ) +static int write_private_key( pk_context *key, const char *output_file ) { int ret; FILE *f; @@ -130,14 +125,14 @@ static int write_private_key( rsa_context *rsa, const char *output_file ) memset(output_buf, 0, 16000); if( opt.output_format == OUTPUT_FORMAT_PEM ) { - if( ( ret = x509write_key_pem( rsa, output_buf, 16000 ) ) != 0 ) + if( ( ret = x509write_key_pem( key, output_buf, 16000 ) ) != 0 ) return( ret ); len = strlen( (char *) output_buf ); } else { - if( ( ret = x509write_key_der( rsa, output_buf, 16000 ) ) < 0 ) + if( ( ret = x509write_key_der( key, output_buf, 16000 ) ) < 0 ) return( ret ); len = ret; @@ -168,7 +163,7 @@ static int write_private_key( rsa_context *rsa, const char *output_file ) int main( int argc, char *argv[] ) { int ret = 0; - rsa_context rsa; + pk_context key; char buf[1024]; int i; char *p, *q; @@ -176,12 +171,13 @@ int main( int argc, char *argv[] ) /* * Set to sane values */ - memset( &rsa, 0, sizeof( rsa_context ) ); - memset( buf, 0, 1024 ); + pk_init( &key ); + memset( buf, 0, sizeof( buf ) ); if( argc == 0 ) { usage: + ret = 1; printf( USAGE ); goto exit; } @@ -254,15 +250,11 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the private key ..." ); fflush( stdout ); - ret = x509parse_keyfile_rsa( &rsa, opt.filename, NULL ); + ret = x509parse_keyfile( &key, opt.filename, NULL ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C - polarssl_strerror( ret, buf, 1024 ); -#endif - printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); - rsa_free( &rsa ); + printf( " failed\n ! x509parse_key returned %d", ret ); goto exit; } @@ -272,14 +264,23 @@ int main( int argc, char *argv[] ) * 1.2 Print the key */ printf( " . Key information ...\n" ); - mpi_write_file( "N: ", &rsa.N, 16, NULL ); - mpi_write_file( "E: ", &rsa.E, 16, NULL ); - mpi_write_file( "D: ", &rsa.D, 16, NULL ); - mpi_write_file( "P: ", &rsa.P, 16, NULL ); - mpi_write_file( "Q: ", &rsa.Q, 16, NULL ); - mpi_write_file( "DP: ", &rsa.DP, 16, NULL ); - mpi_write_file( "DQ: ", &rsa.DQ, 16, NULL ); - mpi_write_file( "QP: ", &rsa.QP, 16, NULL ); + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( &key ) == POLARSSL_PK_RSA ) + { + rsa_context *rsa = pk_rsa( key ); + mpi_write_file( "N: ", &rsa->N, 16, NULL ); + mpi_write_file( "E: ", &rsa->E, 16, NULL ); + mpi_write_file( "D: ", &rsa->D, 16, NULL ); + mpi_write_file( "P: ", &rsa->P, 16, NULL ); + mpi_write_file( "Q: ", &rsa->Q, 16, NULL ); + mpi_write_file( "DP: ", &rsa->DP, 16, NULL ); + mpi_write_file( "DQ: ", &rsa->DQ, 16, NULL ); + mpi_write_file( "QP: ", &rsa->QP, 16, NULL ); + } + else +#endif + printf("key type not supported yet\n"); } else if( opt.mode == MODE_PUBLIC ) @@ -290,15 +291,11 @@ int main( int argc, char *argv[] ) printf( "\n . Loading the public key ..." ); fflush( stdout ); - ret = x509parse_public_keyfile_rsa( &rsa, opt.filename ); + ret = x509parse_public_keyfile( &key, opt.filename ); if( ret != 0 ) { -#ifdef POLARSSL_ERROR_C - polarssl_strerror( ret, buf, 1024 ); -#endif - printf( " failed\n ! x509parse_public_key_rsa returned %d - %s\n\n", ret, buf ); - rsa_free( &rsa ); + printf( " failed\n ! x509parse_public_key returned %d", ret ); goto exit; } @@ -308,24 +305,43 @@ int main( int argc, char *argv[] ) * 1.2 Print the key */ printf( " . Key information ...\n" ); - mpi_write_file( "N: ", &rsa.N, 16, NULL ); - mpi_write_file( "E: ", &rsa.E, 16, NULL ); + +#if defined(POLARSSL_RSA_C) + if( pk_get_type( &key ) == POLARSSL_PK_RSA ) + { + rsa_context *rsa = pk_rsa( key ); + mpi_write_file( "N: ", &rsa->N, 16, NULL ); + mpi_write_file( "E: ", &rsa->E, 16, NULL ); + } + else +#endif + printf("key type not supported yet\n"); } else goto usage; if( opt.output_mode == OUTPUT_MODE_PUBLIC ) { - write_public_key( &rsa, opt.output_file ); + write_public_key( &key, opt.output_file ); } if( opt.output_mode == OUTPUT_MODE_PRIVATE ) { - write_private_key( &rsa, opt.output_file ); + write_private_key( &key, opt.output_file ); } exit: - rsa_free( &rsa ); + if( ret != 0 && ret != 1) + { +#ifdef POLARSSL_ERROR_C + polarssl_strerror( ret, buf, sizeof( buf ) ); + printf( " - %s\n", buf ); +#else + printf("\n"); +#endif + } + + pk_free( &key ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); @@ -334,5 +350,4 @@ exit: return( ret ); } -#endif /* POLARSSL_BIGNUM_C && POLARSSL_RSA_C && - POLARSSL_X509_WRITE_C && POLARSSL_FS_IO */ +#endif /* POLARSSL_X509_WRITE_C && POLARSSL_FS_IO */ diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index e65fb97e61..c0c014fe34 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -40,8 +40,7 @@ #if !defined(POLARSSL_X509_WRITE_C) || !defined(POLARSSL_X509_PARSE_C) || \ !defined(POLARSSL_FS_IO) || \ - !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \ - !defined(POLARSSL_ERROR_C) + !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) int main( int argc, char *argv[] ) { ((void) argc); @@ -49,8 +48,8 @@ int main( int argc, char *argv[] ) printf( "POLARSSL_X509_WRITE_C and/or POLARSSL_X509_PARSE_C and/or " "POLARSSL_FS_IO and/or " - "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or " - "POLARSSL_ERROR_C not defined.\n"); + "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C " + "not defined.\n"); return( 0 ); } #else @@ -146,7 +145,7 @@ int main( int argc, char *argv[] ) x509write_csr_init( &req ); x509write_csr_set_md_alg( &req, POLARSSL_MD_SHA1 ); pk_init( &key ); - memset( buf, 0, 1024 ); + memset( buf, 0, sizeof( buf ) ); if( argc == 0 ) { @@ -267,8 +266,7 @@ int main( int argc, char *argv[] ) (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { - error_strerror( ret, buf, 1024 ); - printf( " failed\n ! ctr_drbg_init returned %d - %s\n", ret, buf ); + printf( " failed\n ! ctr_drbg_init returned %d", ret ); goto exit; } @@ -282,8 +280,7 @@ int main( int argc, char *argv[] ) if( ( ret = x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 ) { - error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509write_csr_set_subject_name returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509write_csr_set_subject_name returned %d", ret ); goto exit; } @@ -299,8 +296,7 @@ int main( int argc, char *argv[] ) if( ret != 0 ) { - error_strerror( ret, buf, 1024 ); - printf( " failed\n ! x509parse_keyfile returned %d - %s\n\n", ret, buf ); + printf( " failed\n ! x509parse_keyfile returned %d", ret ); goto exit; } @@ -317,14 +313,24 @@ int main( int argc, char *argv[] ) if( ( ret = write_certificate_request( &req, opt.output_file, ctr_drbg_random, &ctr_drbg ) ) != 0 ) { - error_strerror( ret, buf, 1024 ); - printf( " failed\n ! write_certifcate_request %d - %s\n\n", ret, buf ); + printf( " failed\n ! write_certifcate_request %d", ret ); goto exit; } printf( " ok\n" ); exit: + + if( ret != 0 && ret != 1) + { +#ifdef POLARSSL_ERROR_C + polarssl_strerror( ret, buf, sizeof( buf ) ); + printf( " - %s\n", buf ); +#else + printf("\n"); +#endif + } + x509write_csr_free( &req ); pk_free( &key ); @@ -336,5 +342,4 @@ exit: return( ret ); } #endif /* POLARSSL_X509_WRITE_C && POLARSSL_X509_PARSE_C && POLARSSL_FS_IO && - POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C && - POLARSSL_ERROR_C */ + POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C */ From 0237620a78745b272ebd1490839855e869669333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 12 Sep 2013 07:01:31 +0200 Subject: [PATCH 42/42] Fix some dependencies declaration --- include/polarssl/config.h | 2 +- include/polarssl/x509.h | 16 ++++++++++++++-- tests/suites/test_suite_x509write.data | 6 +++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 08a136b510..d19c737e36 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -1385,7 +1385,7 @@ * * Module: library/x509write.c * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_RSA_C + * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_C * * This module is required for X.509 certificate request writing. */ diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 0c302962cc..00e9b0bcec 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -31,8 +31,6 @@ #if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C) #include "asn1.h" -#include "rsa.h" -#include "ecp.h" #include "dhm.h" #include "md.h" #include "pk.h" @@ -339,6 +337,7 @@ int x509parse_crt_der( x509_cert *chain, const unsigned char *buf, size_t buflen */ int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load one or more certificates and add them @@ -370,6 +369,7 @@ int x509parse_crtfile( x509_cert *chain, const char *path ); * if partly successful or a specific X509 or PEM error code */ int x509parse_crtpath( x509_cert *chain, const char *path ); +#endif /* POLARSSL_FS_IO */ /** \ingroup x509_module */ /** @@ -396,6 +396,7 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen ); */ int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load one or more CRLs and add them @@ -418,6 +419,7 @@ int x509parse_crlfile( x509_crl *chain, const char *path ); * \return 0 if successful, or a specific X509 or PEM error code */ int x509parse_csrfile( x509_csr *csr, const char *path ); +#endif /* POLARSSL_FS_IO */ #if defined(POLARSSL_RSA_C) /** \ingroup x509_module */ @@ -436,6 +438,7 @@ int x509parse_key_rsa( rsa_context *rsa, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load and parse a private RSA key @@ -448,6 +451,7 @@ int x509parse_key_rsa( rsa_context *rsa, */ int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, const char *password ); +#endif /* POLARSSL_FS_IO */ /** \ingroup x509_module */ /** @@ -462,6 +466,7 @@ int x509parse_keyfile_rsa( rsa_context *rsa, const char *path, int x509parse_public_key_rsa( rsa_context *rsa, const unsigned char *key, size_t keylen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load and parse a public RSA key @@ -472,6 +477,7 @@ int x509parse_public_key_rsa( rsa_context *rsa, * \return 0 if successful, or a specific X509 or PEM error code */ int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path ); +#endif /* POLARSSL_FS_IO */ #endif /* POLARSSL_RSA_C */ /** \ingroup x509_module */ @@ -490,6 +496,7 @@ int x509parse_key( pk_context *ctx, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load and parse a private key @@ -502,6 +509,7 @@ int x509parse_key( pk_context *ctx, */ int x509parse_keyfile( pk_context *ctx, const char *path, const char *password ); +#endif /* POLARSSL_FS_IO */ /** \ingroup x509_module */ /** @@ -516,6 +524,7 @@ int x509parse_keyfile( pk_context *ctx, int x509parse_public_key( pk_context *ctx, const unsigned char *key, size_t keylen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load and parse a public key @@ -526,6 +535,7 @@ int x509parse_public_key( pk_context *ctx, * \return 0 if successful, or a specific X509 or PEM error code */ int x509parse_public_keyfile( pk_context *ctx, const char *path ); +#endif /* POLARSSL_FS_IO */ /** \ingroup x509_module */ /** @@ -539,6 +549,7 @@ int x509parse_public_keyfile( pk_context *ctx, const char *path ); */ int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen ); +#if defined(POLARSSL_FS_IO) /** \ingroup x509_module */ /** * \brief Load and parse DHM parameters @@ -549,6 +560,7 @@ int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen * \return 0 if successful, or a specific X509 or PEM error code */ int x509parse_dhmfile( dhm_context *dhm, const char *path ); +#endif /* POLARSSL_FS_IO */ /** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */ diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 0c300d5439..fc9bb92a3a 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -35,9 +35,13 @@ depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C x509_pubkey_check:"data_files/server1.pubkey" Public key write check EC -depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C +depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C:POLARSSL_ECP_DP_SECP192R1_ENABLED x509_pubkey_check:"data_files/ec_pub.pem" Private key write check RSA depends_on:POLARSSL_RSA_C:POLARSSL_BASE64_C x509_key_check:"data_files/server1.key" + +Private key write check EC +depends_on:POLARSSL_ECP_C:POLARSSL_BASE64_C:POLARSSL_ECP_DP_SECP192R1_ENABLED +x509_key_check:"data_files/ec_prv.sec1.pem"