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"