diff --git a/ChangeLog b/ChangeLog index 549e43659..6cfdd0021 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,8 @@ Features * Support for zeros-and-length (ANSI X.923) padding, one-and-zeros (ISO/IEC 7816-4) padding and zero padding in the cipher layer * Support for session tickets (RFC 5077) + * Certificate Request (CSR) generation with extensions (key_usage, + ns_cert_type) Changes * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2 diff --git a/include/polarssl/asn1.h b/include/polarssl/asn1.h index 195ebcb84..ec8cbfafc 100644 --- a/include/polarssl/asn1.h +++ b/include/polarssl/asn1.h @@ -93,7 +93,10 @@ /** Returns the size of the binary string, without the trailing \\0 */ #define OID_SIZE(x) (sizeof(x) - 1) -/** Compares two asn1_buf structures for the same OID */ +/** Compares two asn1_buf structures for the same OID. Only works for + * 'defined' oid_str values (OID_HMAC_SHA1), you cannot use a 'unsigned + * char *oid' here! + */ #define OID_CMP(oid_str, oid_buf) \ ( ( OID_SIZE(oid_str) == (oid_buf)->len ) && \ memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) == 0 ) @@ -139,6 +142,17 @@ typedef struct _asn1_sequence } asn1_sequence; +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct _asn1_named_data +{ + asn1_buf oid; /**< The object identifier. */ + asn1_buf val; /**< The named value. */ + struct _asn1_named_data *next; /**< The next entry in the sequence. */ +} +asn1_named_data; + /** * Get the length of an ASN.1 element. * Updates the pointer to immediately behind the length. @@ -286,6 +300,25 @@ int asn1_get_alg_null( unsigned char **p, const unsigned char *end, asn1_buf *alg ); +/** + * Find a specific named_data entry in a sequence or list based on the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ); + +/** + * Free a asn1_named_data entry + * + * \param entry The named data entry to free + */ +void asn1_free_named_data( asn1_named_data *entry ); + #ifdef __cplusplus } #endif diff --git a/include/polarssl/asn1write.h b/include/polarssl/asn1write.h index 459b28256..4659b24c1 100644 --- a/include/polarssl/asn1write.h +++ b/include/polarssl/asn1write.h @@ -35,20 +35,164 @@ extern "C" { #endif +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ int asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + #if defined(POLARSSL_BIGNUM_C) +/** + * \brief Write a big number (ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ); #endif + +/** + * \brief Write a NULL tag (ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ int asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * + * \return the length written or a negative error code + */ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ); -int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, const char *algorithm_oid ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * Note: Uses NULL as algorithm parameter + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * + * \return the length written or a negative error code + */ +int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid ); + +/** + * \brief Write an int tag (ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ int asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * + * \return the length written or a negative error code + */ int asn1_write_printable_string( unsigned char **p, unsigned char *start, char *text ); + +/** + * \brief Write an IA5 string tag (ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * + * \return the length written or a negative error code + */ int asn1_write_ia5_string( unsigned char **p, unsigned char *start, char *text ); +/** + * \brief Write a bitstring tag (ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); #ifdef __cplusplus } #endif diff --git a/include/polarssl/error.h b/include/polarssl/error.h index 889e4bebc..4c9ef7c47 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -73,19 +73,20 @@ * PBKDF2 1 0x007C-0x007C * * High-level module nr (3 bits - 0x1...-0x8...) - * Name ID Nr of Errors - * PEM 1 9 - * PKCS#12 1 4 (Started from top) - * X509 2 25 - * PK 2 3 (Started from top) - * DHM 3 6 - * PKCS5 3 4 (Started from top) - * RSA 4 9 - * ECP 4 4 (Started from top) - * MD 5 4 - * CIPHER 6 5 - * SSL 6 6 (Started from top) - * SSL 7 31 + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 25 + * PK 2 3 (Started from top) + * DHM 3 6 + * PKCS5 3 4 (Started from top) + * RSA 4 9 + * ECP 4 4 (Started from top) + * MD 5 4 + * X509WRITE 5 3 (Started from top) + * CIPHER 6 5 + * SSL 6 6 (Started from top) + * SSL 7 31 * * Module dependent error code (5 bits 0x.08.-0x.F8.) */ diff --git a/include/polarssl/oid.h b/include/polarssl/oid.h index ebb5bad98..025a15f0a 100644 --- a/include/polarssl/oid.h +++ b/include/polarssl/oid.h @@ -227,6 +227,11 @@ #define OID_PKCS5_PBE_SHA1_DES_CBC OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ #define OID_PKCS5_PBE_SHA1_RC2_CBC OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ +/* + * PKCS#8 OIDs + */ +#define OID_PKCS9_CSR_EXT_REQ OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + /* * PKCS#12 PBE OIDs */ diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 878586233..e68789ce9 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -146,7 +146,7 @@ extern "C" { #endif -/** +/** * \addtogroup x509_module * \{ */ @@ -154,8 +154,8 @@ extern "C" { * \name Structures for parsing X.509 certificates and CRLs * \{ */ - -/** + +/** * Type-length-value structure that allows for ASN1 using DER. */ typedef asn1_buf x509_buf; @@ -166,16 +166,10 @@ typedef asn1_buf x509_buf; typedef asn1_bitstring x509_bitstring; /** - * Container for ASN1 named information objects. + * Container for ASN1 named information objects. * It allows for Relative Distinguished Names (e.g. cn=polarssl,ou=code,etc.). */ -typedef struct _x509_name -{ - x509_buf oid; /**< The object identifier. */ - x509_buf val; /**< The named value. */ - struct _x509_name *next; /**< The next named information object. */ -} -x509_name; +typedef asn1_named_data x509_name; /** * Container for a sequence of ASN.1 items @@ -190,7 +184,7 @@ typedef struct _x509_time } x509_time; -/** +/** * Container for an X.509 certificate. The certificate may be chained. */ typedef struct _x509_cert @@ -289,42 +283,6 @@ x509_crl; /** \} name Structures for parsing X.509 certificates and CRLs */ /** \} addtogroup x509_module */ -/** - * \name Structures for writing X.509 certificates. - * XvP: commented out as they are not used. - * - typedef struct _x509_node x509_node; - * - typedef struct _x509_raw x509_raw; - */ -/* -typedef struct _x509_node -{ - unsigned char *data; - unsigned char *p; - unsigned char *end; - - size_t len; -} -x509_node; - -typedef struct _x509_raw -{ - x509_node raw; - x509_node tbs; - - x509_node version; - x509_node serial; - x509_node tbs_signalg; - x509_node issuer; - x509_node validity; - x509_node subject; - x509_node subpubkey; - - x509_node signalg; - x509_node sign; -} -x509_raw; -*/ - /** * \name Functions to read in DHM parameters, a certificate, CRL or private RSA key * \{ diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 0d94f0154..0e443ee8c 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -29,14 +29,40 @@ #include "config.h" -#if defined(POLARSSL_X509_WRITE_C) +#include "x509.h" -#include "rsa.h" +/** + * \addtogroup x509_module + * \{ + */ + +/** + * \name X509 Write Error codes + * \{ + */ +#define POLARSSL_ERR_X509WRITE_UNKNOWN_OID -0x5F80 /**< Requested OID is unknown. */ +#define POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA -0x5F00 /**< Failed to allocate memory. */ +#define POLARSSL_ERR_X509WRITE_MALLOC_FAILED -0x5E80 /**< Failed to allocate memory. */ +/* \} name */ +/* \} addtogroup x509_module */ #ifdef __cplusplus extern "C" { #endif +/** + * \addtogroup x509_module + * \{ + */ + +/** + * \name Structures for writing X.509 CSRs (Certificate Signing Request) + * \{ + */ + +/** + * Container for CSR named objects + */ typedef struct _x509_req_name { char oid[128]; @@ -46,15 +72,187 @@ typedef struct _x509_req_name } x509_req_name; -int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ); -int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa ); -int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, - x509_req_name *req_name, md_type_t md_alg ); +/** + * Container for a CSR + */ +typedef struct _x509_csr +{ + rsa_context *rsa; + x509_req_name *subject; + md_type_t md_alg; + asn1_named_data *extensions; +} +x509_csr; + +/* \} addtogroup x509_module */ + +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void x509write_csr_init( x509_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=NL,O=Offspark,CN=PolarSSL Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int x509write_csr_set_subject_name( x509_csr *ctx, char *subject_name ); + +/** + * \brief Set the RSA key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param rsa RSA key to include + */ +void x509write_csr_set_rsa_key( x509_csr *ctx, rsa_context *rsa ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. POLARSSL_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_ald MD algorithm to use + */ +void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a POLARSSL_ERR_X509WRITE_MALLOC_FAILED + */ +int x509write_csr_set_extension( x509_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void x509write_csr_free( x509_csr *ctx ); + +/** + * \brief Write a RSA public key to a PKCS#1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a RSA key to a PKCS#1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param rsa CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ); + +#if defined(POLARSSL_BASE64_C) +/** + * \brief Write a RSA public key to a PKCS#1 PEM string + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a RSA key to a PKCS#1 PEM string + * + * \param rsa RSA to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param rsa CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 successful, or a specific error code + */ +int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ); +#endif /* POLARSSL_BASE64_C */ #ifdef __cplusplus } #endif -#endif /* POLARSSL_X509_WRITE_C */ - #endif /* POLARSSL_X509_WRITE_H */ diff --git a/library/asn1parse.c b/library/asn1parse.c index ff566c9ce..f6b271ec5 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -343,4 +343,32 @@ int asn1_get_alg_null( unsigned char **p, return( 0 ); } +void asn1_free_named_data( asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + polarssl_free( cur->oid.p ); + polarssl_free( cur->val.p ); + + memset( cur, 0, sizeof( asn1_named_data ) ); +} + +asn1_named_data *asn1_find_named_data( asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + #endif diff --git a/library/asn1write.c b/library/asn1write.c index b1d68392f..463c730fb 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -72,6 +72,21 @@ int asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) return( 1 ); } +int asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p - start < (int) size ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( len ); +} + #if defined(POLARSSL_BIGNUM_C) int asn1_write_mpi( unsigned char **p, unsigned char *start, mpi *X ) { @@ -125,15 +140,8 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ) int ret; size_t len = 0; - // Write OID - // - len = strlen( oid ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, oid, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, strlen( oid ) ) ); ASN1_CHK_ADD( len , asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len , asn1_write_tag( p, start, ASN1_OID ) ); @@ -142,7 +150,7 @@ int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid ) } int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *algorithm_oid ) + const char *oid ) { int ret; size_t null_len = 0; @@ -155,7 +163,7 @@ int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, // Write OID // - ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, algorithm_oid ) ); + ASN1_CHK_ADD( oid_len, asn1_write_oid( p, start, oid ) ); len = oid_len + null_len; ASN1_CHK_ADD( len, asn1_write_len( p, start, oid_len + null_len ) ); @@ -201,43 +209,68 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start, int ret; size_t len = 0; - // Write string - // - len = strlen( text ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, text, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, strlen( text ) ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) ); return( len ); } - + int asn1_write_ia5_string( unsigned char **p, unsigned char *start, - char *text ) + char *text ) { int ret; size_t len = 0; - // Write string - // - len = strlen( text ); - - if( *p - start < (int) len ) - return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - memcpy( *p, text, len ); + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, + (const unsigned char *) text, strlen( text ) ) ); ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) ); return( len ); } - +int asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0, size; + + size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + + // Calculate byte length + // + if( *p - start < (int) size + 1 ) + return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = size * 8 - bits; + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) ); + + return( len ); +} + +int asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start, buf, size ) ); + + ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_OCTET_STRING ) ); + + return( len ); +} #endif diff --git a/library/error.c b/library/error.c index 35a4af086..86586dde2 100644 --- a/library/error.c +++ b/library/error.c @@ -149,6 +149,10 @@ #include "polarssl/x509.h" #endif +#if defined(POLARSSL_X509_WRITE_C) +#include "polarssl/x509write.h" +#endif + #if defined(POLARSSL_XTEA_C) #include "polarssl/xtea.h" #endif @@ -432,6 +436,15 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "X509 - Elliptic curve is unsupported (only NIST curves are supported)" ); #endif /* POLARSSL_X509_PARSE_C */ +#if defined(POLARSSL_X509_WRITE_C) + if( use_ret == -(POLARSSL_ERR_X509WRITE_UNKNOWN_OID) ) + snprintf( buf, buflen, "X509WRITE - Requested OID is unknown" ); + if( use_ret == -(POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA) ) + snprintf( buf, buflen, "X509WRITE - Failed to allocate memory" ); + if( use_ret == -(POLARSSL_ERR_X509WRITE_MALLOC_FAILED) ) + snprintf( buf, buflen, "X509WRITE - Failed to allocate memory" ); +#endif /* POLARSSL_X509_WRITE_C */ + if( strlen( buf ) == 0 ) snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); } diff --git a/library/x509write.c b/library/x509write.c index 7aa65ce37..7e04e1206 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -33,7 +33,231 @@ #include "polarssl/md.h" #include "polarssl/oid.h" -int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) +#if defined(POLARSSL_BASE64_C) +#include "polarssl/base64.h" +#endif + +#if defined(POLARSSL_MEMORY_C) +#include "polarssl/memory.h" +#else +#include +#define polarssl_malloc malloc +#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 ) +{ + int ret = 0; + char *s = subject_name, *c = s; + char *end = s + strlen( s ); + char *oid = NULL; + int in_tag = 1; + x509_req_name *cur; + + while( ctx->subject ) + { + cur = ctx->subject; + ctx->subject = ctx->subject->next; + polarssl_free( cur ); + } + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 ) + oid = OID_AT_CN; + else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 ) + oid = OID_AT_COUNTRY; + else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 ) + oid = OID_AT_ORGANIZATION; + else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 ) + oid = OID_AT_LOCALITY; + else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 ) + oid = OID_PKCS9_EMAIL; + else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 ) + oid = OID_AT_ORG_UNIT; + else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 ) + oid = OID_AT_STATE; + else + { + ret = POLARSSL_ERR_X509WRITE_UNKNOWN_OID; + goto exit; + } + + s = c + 1; + in_tag = 0; + } + + if( !in_tag && ( *c == ',' || c == end ) ) + { + if( c - s > 127 ) + { + ret = POLARSSL_ERR_X509WRITE_BAD_INPUT_DATA; + goto exit; + } + + 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 = ctx->subject; + ctx->subject = cur; + + strncpy( cur->oid, oid, strlen( oid ) ); + strncpy( cur->name, s, c - s ); + + s = c + 1; + in_tag = 1; + } + c++; + } + +exit: + + return( ret ); +} + +int x509write_csr_set_extension( x509_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( ctx->extensions, oid, + oid_len ) ) == 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; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->next = ctx->extensions; + ctx->extensions = cur; + } + + if( cur->val.len != val_len ) + { + polarssl_free( cur->val.p ); + + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); + if( cur->val.p == NULL ) + { + polarssl_free( cur->oid.p ); + polarssl_free( cur ); + return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); + } + } + + memcpy( cur->val.p, val, val_len ); + + return( 0 ); +} + +int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE, + OID_SIZE( OID_KEY_USAGE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_csr_set_ns_cert_type( x509_csr *ctx, unsigned char ns_cert_type ) +{ + unsigned char buf[4]; + unsigned char *c; + int ret; + + c = buf + 4; + + if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + return( ret ); + + ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE, + OID_SIZE( OID_NS_CERT_TYPE ), + buf, 4 ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int x509write_pubkey_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; unsigned char *c; @@ -41,6 +265,12 @@ int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) c = buf + size - 1; + /* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->E ) ); ASN1_CHK_ADD( len, asn1_write_mpi( &c, buf, &rsa->N ) ); @@ -50,6 +280,11 @@ int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) if( c - buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ *--c = 0; len += 1; @@ -64,7 +299,7 @@ int x509_write_pubkey_der( unsigned char *buf, size_t size, rsa_context *rsa ) return( len ); } -int x509_write_key_der( unsigned char *buf, size_t size, rsa_context *rsa ) +int x509write_key_der( rsa_context *rsa, unsigned char *buf, size_t size ) { int ret; unsigned char *c; @@ -167,8 +402,7 @@ static int x509_write_sig( unsigned char **p, unsigned char *start, return( len ); } -int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, - x509_req_name *req_name, md_type_t md_alg ) +int x509write_csr_der( x509_csr *ctx, unsigned char *buf, size_t size ) { int ret; const char *sig_oid; @@ -178,15 +412,52 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, unsigned char tmp_buf[2048]; size_t sub_len = 0, pub_len = 0, sig_len = 0; size_t len = 0; - x509_req_name *cur = req_name; + x509_req_name *cur = ctx->subject; + asn1_named_data *cur_ext = ctx->extensions; c = tmp_buf + 2048 - 1; - ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, 0 ) ); + 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; + } + + if( len ) + { + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + + ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); + ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); + + ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, 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 ) ); + } + + 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, &rsa->E ) ); - ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &rsa->N ) ); + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->E ) ); + ASN1_CHK_ADD( pub_len, asn1_write_mpi( &c, tmp_buf, &ctx->rsa->N ) ); ASN1_CHK_ADD( pub_len, asn1_write_len( &c, tmp_buf, pub_len ) ); ASN1_CHK_ADD( pub_len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); @@ -194,6 +465,11 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, if( c - tmp_buf < 1 ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); + /* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ *--c = 0; pub_len += 1; @@ -217,21 +493,24 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); - md( md_info_from_type( md_alg ), c, len, hash ); + md( md_info_from_type( ctx->md_alg ), c, len, hash ); - rsa_pkcs1_sign( rsa, NULL, NULL, RSA_PRIVATE, md_alg, 0, hash, sig ); + rsa_pkcs1_sign( ctx->rsa, NULL, NULL, RSA_PRIVATE, ctx->md_alg, 0, hash, sig ); // Generate correct OID // - ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, md_alg, &sig_oid ); + ret = oid_get_oid_by_sig_alg( POLARSSL_PK_RSA, ctx->md_alg, &sig_oid ); c2 = buf + size - 1; - ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, rsa->len ) ); + ASN1_CHK_ADD( sig_len, x509_write_sig( &c2, buf, sig_oid, sig, ctx->rsa->len ) ); c2 -= len; memcpy( c2, c, len ); @@ -243,4 +522,117 @@ int x509_write_cert_req( unsigned char *buf, size_t size, rsa_context *rsa, return( len ); } +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY "-----END RSA PRIVATE KEY-----\n" + +#if defined(POLARSSL_BASE64_C) +static int x509write_pemify( const char *begin_str, const char *end_str, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t size ) +{ + int ret; + unsigned char base_buf[4096]; + unsigned char *c = base_buf, *p = buf; + size_t len = 0, olen = sizeof(base_buf); + + if( ( ret = base64_encode( base_buf, &olen, der_data, der_len ) ) != 0 ) + return( ret ); + + if( olen + strlen( begin_str ) + strlen( end_str ) + + olen / 64 > size ) + { + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + memcpy( p, begin_str, strlen( begin_str ) ); + p += strlen( begin_str ); + + while( olen ) + { + len = ( olen > 64 ) ? 64 : olen; + memcpy( p, c, len ); + olen -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, end_str, strlen( end_str ) ); + p += strlen( end_str ); + + *p = '\0'; + + return( 0 ); +} + +int x509write_pubkey_pem( rsa_context *rsa, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_pubkey_der( rsa, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int x509write_key_pem( rsa_context *rsa, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_key_der( rsa, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_PRIVATE_KEY, PEM_END_PRIVATE_KEY, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int x509write_csr_pem( x509_csr *ctx, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[4096]; + + if( ( ret = x509write_csr_der( ctx, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = x509write_pemify( PEM_BEGIN_CSR, PEM_END_CSR, + output_buf + sizeof(output_buf) - 1 - ret, + ret, buf, size ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* POLARSSL_BASE64_C */ + #endif diff --git a/programs/.gitignore b/programs/.gitignore index e9f4e54ef..2b7510f6e 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -35,6 +35,7 @@ test/o_p_test test/selftest test/ssl_cert_test test/ssl_test +util/pem2der util/strerror x509/cert_app x509/cert_req diff --git a/programs/Makefile b/programs/Makefile index 1c2b5fc80..ea024fae6 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -39,7 +39,7 @@ APPS = aes/aescrypt2 aes/crypt_and_hash \ test/ssl_cert_test test/benchmark \ test/selftest test/ssl_test \ test/ecp-bench \ - util/strerror \ + util/pem2der util/strerror \ x509/cert_app x509/crl_app \ x509/cert_req @@ -195,6 +195,10 @@ test/o_p_test: test/o_p_test.c ../library/libpolarssl.a echo " CC test/o_p_test.c" $(CC) $(CFLAGS) $(OFLAGS) test/o_p_test.c $(LDFLAGS) -o $@ -lssl -lcrypto +util/pem2der: util/pem2der.c ../library/libpolarssl.a + echo " CC util/pem2der.c" + $(CC) $(CFLAGS) $(OFLAGS) util/pem2der.c $(LDFLAGS) -o $@ + util/strerror: util/strerror.c ../library/libpolarssl.a echo " CC util/strerror.c" $(CC) $(CFLAGS) $(OFLAGS) util/strerror.c $(LDFLAGS) -o $@ diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c index 88cb9071c..d9ab45c94 100644 --- a/programs/pkey/key_app_writer.c +++ b/programs/pkey/key_app_writer.c @@ -1,5 +1,5 @@ /* - * Key reading application + * Key writing application * * Copyright (C) 2006-2013, Brainspark B.V. * @@ -60,11 +60,15 @@ int main( int argc, char *argv[] ) #define OUTPUT_MODE_PRIVATE 1 #define OUTPUT_MODE_PUBLIC 2 +#define OUTPUT_FORMAT_PEM 0 +#define OUTPUT_FORMAT_DER 1 + #define DFL_MODE MODE_NONE #define DFL_FILENAME "keyfile.key" #define DFL_DEBUG_LEVEL 0 -#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE +#define DFL_OUTPUT_MODE OUTPUT_MODE_NONE #define DFL_OUTPUT_FILENAME "keyfile.pem" +#define DFL_OUTPUT_FORMAT OUTPUT_FORMAT_PEM /* * global options @@ -75,79 +79,80 @@ struct options const char *filename; /* filename of the key file */ int output_mode; /* the output mode to use */ const char *output_file; /* where to store the constructed key file */ + int output_format; /* the output format to use */ } opt; -static void write_public_key( rsa_context *rsa, const char *output_file ) +static int write_public_key( rsa_context *rsa, const char *output_file ) { + int ret; FILE *f; unsigned char output_buf[16000]; - unsigned char base_buf[16000]; - unsigned char *c; - int ret; - size_t len = 0, olen = 16000; + unsigned char *c = output_buf; + size_t len = 0; memset(output_buf, 0, 16000); - ret = x509_write_pubkey_der( output_buf, 16000, rsa ); - if( ret < 0 ) - return; - - len = ret; - c = output_buf + 15999 - len; - - base64_encode( base_buf, &olen, c, len ); - - c = base_buf; - - f = fopen( output_file, "w" ); - fprintf(f, "-----BEGIN PUBLIC KEY-----\n"); - while (olen) + if( opt.output_format == OUTPUT_FORMAT_PEM ) { - int use_len = olen; - if (use_len > 64) use_len = 64; - fwrite( c, 1, use_len, f ); - olen -= use_len; - c += use_len; - fprintf(f, "\n"); + if( ( ret = x509write_pubkey_pem( rsa, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); } - fprintf(f, "-----END PUBLIC KEY-----\n"); + else + { + if( ( ret = x509write_pubkey_der( rsa, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len - 1; + } + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + return( -1 ); + fclose(f); + + return( 0 ); } -static void write_private_key( rsa_context *rsa, const char *output_file ) +static int write_private_key( rsa_context *rsa, const char *output_file ) { + int ret; FILE *f; unsigned char output_buf[16000]; - unsigned char base_buf[16000]; - unsigned char *c; - int ret; - size_t len = 0, olen = 16000; + unsigned char *c = output_buf; + size_t len = 0; memset(output_buf, 0, 16000); - ret = x509_write_key_der( output_buf, 16000, rsa ); - if( ret < 0 ) - return; - - len = ret; - c = output_buf + 15999 - len; - - base64_encode( base_buf, &olen, c, len ); - - c = base_buf; - - f = fopen( output_file, "w" ); - fprintf(f, "-----BEGIN RSA PRIVATE KEY-----\n"); - while (olen) + if( opt.output_format == OUTPUT_FORMAT_PEM ) { - int use_len = olen; - if (use_len > 64) use_len = 64; - fwrite( c, 1, use_len, f ); - olen -= use_len; - c += use_len; - fprintf(f, "\n"); + if( ( ret = x509write_key_pem( rsa, output_buf, 16000 ) ) != 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); } - fprintf(f, "-----END RSA PRIVATE KEY-----\n"); + else + { + if( ( ret = x509write_key_der( rsa, output_buf, 16000 ) ) < 0 ) + return( ret ); + + len = ret; + c = output_buf + sizeof(output_buf) - len - 1; + } + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( c, 1, len, f ) != len ) + return( -1 ); + fclose(f); + + return( 0 ); } #define USAGE \ @@ -156,7 +161,8 @@ static void write_private_key( rsa_context *rsa, const char *output_file ) " mode=private|public default: none\n" \ " filename=%%s default: keyfile.key\n" \ " output_mode=private|public default: none\n" \ - " output_file=%%s defeult: keyfile.pem\n" \ + " output_file=%%s default: keyfile.pem\n" \ + " output_format=pem|der default: pem\n" \ "\n" int main( int argc, char *argv[] ) @@ -184,6 +190,7 @@ int main( int argc, char *argv[] ) opt.filename = DFL_FILENAME; opt.output_mode = DFL_OUTPUT_MODE; opt.output_file = DFL_OUTPUT_FILENAME; + opt.output_format = DFL_OUTPUT_FORMAT; for( i = 1; i < argc; i++ ) { @@ -210,6 +217,15 @@ int main( int argc, char *argv[] ) else goto usage; } + else if( strcmp( p, "output_format" ) == 0 ) + { + if( strcmp( q, "pem" ) == 0 ) + opt.output_format = OUTPUT_FORMAT_PEM; + else if( strcmp( q, "der" ) == 0 ) + opt.output_format = OUTPUT_FORMAT_DER; + else + goto usage; + } else if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else if( strcmp( p, "output_file" ) == 0 ) diff --git a/programs/util/CMakeLists.txt b/programs/util/CMakeLists.txt index c0f2e4cea..aedd94f58 100644 --- a/programs/util/CMakeLists.txt +++ b/programs/util/CMakeLists.txt @@ -5,6 +5,9 @@ set(libs add_executable(strerror strerror.c) target_link_libraries(strerror ${libs}) -install(TARGETS strerror +add_executable(pem2der pem2der.c) +target_link_libraries(pem2der ${libs}) + +install(TARGETS strerror pem2der DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/util/pem2der.c b/programs/util/pem2der.c new file mode 100644 index 000000000..0315f02ea --- /dev/null +++ b/programs/util/pem2der.c @@ -0,0 +1,288 @@ +/* + * Convert PEM to DER + * + * Copyright (C) 2006-2013, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#include +#include +#include + +#include "polarssl/config.h" + +#include "polarssl/error.h" +#include "polarssl/base64.h" + +#define DFL_FILENAME "file.pem" +#define DFL_OUTPUT_FILENAME "file.der" + +/* + * global options + */ +struct options +{ + char *filename; /* filename of the input file */ + char *output_file; /* where to store the output */ +} opt; + +int convert_pem_to_der( const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + const unsigned char *s1, *s2, *end = input + ilen; + size_t len = 0; + + s1 = (unsigned char *) strstr( (char *) input, "-----BEGIN" ); + if( s1 == NULL ) + return( -1 ); + + s2 = (unsigned char *) strstr( (char *) input, "-----END" ); + if( s2 == NULL ) + return( -1 ); + + s1 += 10; + while( s1 < end && *s1 != '-' ) + s1++; + while( s1 < end && *s1 == '-' ) + s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + + if( s2 <= s1 || s2 > end ) + return( -1 ); + + ret = base64_decode( NULL, &len, (const unsigned char *) s1, s2 - s1 ); + if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER ) + return( ret ); + + if( len > *olen ) + return( -1 ); + + if( ( ret = base64_decode( output, &len, (const unsigned char *) s1, + s2 - s1 ) ) != 0 ) + { + return( ret ); + } + + *olen = len; + + return( 0 ); +} + +/* + * Load all data from a file into a given buffer. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( -1 ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( -1 ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = (unsigned char *) malloc( *n + 1 ) ) == NULL ) + { + fclose( f ); + return( -1 ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + free( *buf ); + return( -1 ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + return( 0 ); +} + +/* + * Write buffer to a file + */ +static int write_file( const char *path, unsigned char *buf, size_t n ) +{ + FILE *f; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( -1 ); + + if( fwrite( buf, 1, n, f ) != n ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + return( 0 ); +} + +#define USAGE \ + "\n usage: pem2der param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: file.pem\n" \ + " output_file=%%s default: file.der\n" \ + "\n" + +#if !defined(POLARSSL_BASE64_C) || !defined(POLARSSL_FS_IO) +int main( int argc, char *argv[] ) +{ + ((void) argc); + ((void) argv); + + printf("POLARSSL_BASE64_C and/or POLARSSL_FS_IO not defined.\n"); + return( 0 ); +} +#else +int main( int argc, char *argv[] ) +{ + int ret = 0; + unsigned char *pem_buffer = NULL; + unsigned char der_buffer[4096]; + char buf[1024]; + size_t pem_size, der_size = sizeof(der_buffer); + int i, j, n; + char *p, *q; + + /* + * Set to sane values + */ + memset( buf, 0, sizeof(buf) ); + memset( der_buffer, 0, sizeof(der_buffer) ); + + if( argc == 0 ) + { + usage: + printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + opt.output_file = DFL_OUTPUT_FILENAME; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + n = strlen( p ); + for( j = 0; j < n; j++ ) + { + if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) + argv[i][j] |= 0x20; + } + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else + goto usage; + } + + /* + * 1.1. Load the PEM file + */ + printf( "\n . Loading the PEM file ..." ); + fflush( stdout ); + + ret = load_file( opt.filename, &pem_buffer, &pem_size ); + + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! load_file returned %d - %s\n\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 1.2. Convert from PEM to DER + */ + printf( " . Converting from PEM to DER ..." ); + fflush( stdout ); + + if( ( ret = convert_pem_to_der( pem_buffer, pem_size, der_buffer, &der_size ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! convert_pem_to_der %d - %s\n\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 1.3. Write the DER file + */ + printf( " . Writing the DER file ..." ); + fflush( stdout ); + + ret = write_file( opt.output_file, der_buffer, der_size ); + + if( ret != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! write_file returned %d - %s\n\n", ret, buf ); + goto exit; + } + + printf( " ok\n" ); + +exit: + free( pem_buffer ); + +#if defined(_WIN32) + printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( ret ); +} +#endif /* POLARSSL_BASE64_C && POLARSSL_FS_IO */ diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt index 08a962aef..d07cff82d 100644 --- a/programs/x509/CMakeLists.txt +++ b/programs/x509/CMakeLists.txt @@ -16,6 +16,9 @@ target_link_libraries(cert_app ${libs}) add_executable(crl_app crl_app.c) target_link_libraries(crl_app ${libs}) -install(TARGETS cert_app crl_app +add_executable(cert_req cert_req.c) +target_link_libraries(cert_req ${libs}) + +install(TARGETS cert_app crl_app cert_req DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c index cbd62521d..384ef08d6 100644 --- a/programs/x509/cert_req.c +++ b/programs/x509/cert_req.c @@ -44,6 +44,8 @@ #define DFL_DEBUG_LEVEL 0 #define DFL_OUTPUT_FILENAME "cert.req" #define DFL_SUBJECT_NAME "CN=Cert,O=PolarSSL,C=NL" +#define DFL_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 /* * global options @@ -54,53 +56,32 @@ struct options int debug_level; /* level of debugging */ char *output_file; /* where to store the constructed key file */ char *subject_name; /* subject name for certificate request */ + unsigned char key_usage; /* key usage flags */ + unsigned char ns_cert_type; /* NS cert type */ } opt; -void my_debug( void *ctx, int level, const char *str ) -{ - if( level < opt.debug_level ) - { - fprintf( (FILE *) ctx, "%s", str ); - fflush( (FILE *) ctx ); - } -} - -void write_certificate_request( rsa_context *rsa, x509_req_name *req_name, - char *output_file ) +int write_certificate_request( x509_csr *req, char *output_file ) { + int ret; FILE *f; unsigned char output_buf[4096]; - unsigned char base_buf[4096]; - unsigned char *c; - int ret; - size_t len = 0, olen = 4096; + size_t len = 0; - memset(output_buf, 0, 4096); - ret = x509_write_cert_req( output_buf, 4096, rsa, req_name, POLARSSL_MD_SHA1 ); + memset( output_buf, 0, 4096 ); + if( ( ret = x509write_csr_pem( req, output_buf, 4096 ) ) < 0 ) + return( ret ); - if( ret < 0 ) - return; + len = strlen( (char *) output_buf ); - len = ret; - c = output_buf + 4095 - len; + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); - base64_encode( base_buf, &olen, c, len ); + if( fwrite( output_buf, 1, len, f ) != len ) + return( -1 ); - c = base_buf; - - f = fopen( output_file, "w" ); - fprintf(f, "-----BEGIN CERTIFICATE REQUEST-----\n"); - while (olen) - { - int use_len = olen; - if (use_len > 64) use_len = 64; - fwrite( c, 1, use_len, f ); - olen -= use_len; - c += use_len; - fprintf(f, "\n"); - } - fprintf(f, "-----END CERTIFICATE REQUEST-----\n"); fclose(f); + + return( 0 ); } #define USAGE \ @@ -110,6 +91,24 @@ void write_certificate_request( rsa_context *rsa, x509_req_name *req_name, " debug_level=%%d default: 0 (disabled)\n" \ " output_file=%%s default: cert.req\n" \ " subject_name=%%s default: CN=Cert,O=PolarSSL,C=NL\n" \ + " key_usage=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " digital_signature\n" \ + " non_repudiation\n" \ + " key_encipherment\n" \ + " data_encipherment\n" \ + " key_agreement\n" \ + " key_certificate_sign\n" \ + " crl_sign\n" \ + " ns_cert_type=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " ssl_client\n" \ + " ssl_server\n" \ + " email\n" \ + " object_signing\n" \ + " ssl_ca\n" \ + " email_ca\n" \ + " object_signing_ca\n" \ "\n" #if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_RSA_C) || \ @@ -130,16 +129,14 @@ int main( int argc, char *argv[] ) rsa_context rsa; char buf[1024]; int i, j, n; - char *p, *q; - char *s, *c, *end; - int in_tag; - char *oid = NULL; - x509_req_name *req_name = NULL; - x509_req_name *cur = req_name; + char *p, *q, *r; + x509_csr req; /* * Set to sane values */ + x509write_csr_init( &req ); + x509write_csr_set_md_alg( &req, POLARSSL_MD_SHA1 ); memset( &rsa, 0, sizeof( rsa_context ) ); memset( buf, 0, 1024 ); @@ -147,6 +144,7 @@ int main( int argc, char *argv[] ) { usage: printf( USAGE ); + ret = 1; goto exit; } @@ -154,6 +152,8 @@ int main( int argc, char *argv[] ) opt.debug_level = DFL_DEBUG_LEVEL; opt.output_file = DFL_OUTPUT_FILENAME; opt.subject_name = DFL_SUBJECT_NAME; + opt.key_usage = DFL_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; for( i = 1; i < argc; i++ ) { @@ -184,81 +184,80 @@ int main( int argc, char *argv[] ) { opt.subject_name = q; } + else if( strcmp( p, "key_usage" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "digital_signature" ) == 0 ) + opt.key_usage |= KU_DIGITAL_SIGNATURE; + else if( strcmp( q, "non_repudiation" ) == 0 ) + opt.key_usage |= KU_NON_REPUDIATION; + else if( strcmp( q, "key_encipherment" ) == 0 ) + opt.key_usage |= KU_KEY_ENCIPHERMENT; + else if( strcmp( q, "data_encipherment" ) == 0 ) + opt.key_usage |= KU_DATA_ENCIPHERMENT; + else if( strcmp( q, "key_agreement" ) == 0 ) + opt.key_usage |= KU_KEY_AGREEMENT; + else if( strcmp( q, "key_cert_sign" ) == 0 ) + opt.key_usage |= KU_KEY_CERT_SIGN; + else if( strcmp( q, "crl_sign" ) == 0 ) + opt.key_usage |= KU_CRL_SIGN; + else + goto usage; + + q = r; + } + } + else if( strcmp( p, "ns_cert_type" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "ssl_client" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_SSL_CLIENT; + else if( strcmp( q, "ssl_server" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_SSL_SERVER; + else if( strcmp( q, "email" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_EMAIL; + else if( strcmp( q, "object_signing" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING; + else if( strcmp( q, "ssl_ca" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_SSL_CA; + else if( strcmp( q, "email_ca" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_EMAIL_CA; + else if( strcmp( q, "object_signing_ca" ) == 0 ) + opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING_CA; + else + goto usage; + + q = r; + } + } else goto usage; } + if( opt.key_usage ) + x509write_csr_set_key_usage( &req, opt.key_usage ); + + if( opt.ns_cert_type ) + x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type ); + /* * 1.0. Check the subject name for validity */ - s = opt.subject_name; - end = s + strlen( s ); - - c = s; - - in_tag = 1; - while( c <= end ) + if( ( ret = x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 ) { - if( in_tag && *c == '=' ) - { - if( memcmp( s, "CN", 2 ) == 0 && c - s == 2 ) - oid = OID_AT_CN; - else if( memcmp( s, "C", 1 ) == 0 && c - s == 1 ) - oid = OID_AT_COUNTRY; - else if( memcmp( s, "O", 1 ) == 0 && c - s == 1 ) - oid = OID_AT_ORGANIZATION; - else if( memcmp( s, "L", 1 ) == 0 && c - s == 1 ) - oid = OID_AT_LOCALITY; - else if( memcmp( s, "R", 1 ) == 0 && c - s == 1 ) - oid = OID_PKCS9_EMAIL; - else if( memcmp( s, "OU", 2 ) == 0 && c - s == 2 ) - oid = OID_AT_ORG_UNIT; - else if( memcmp( s, "ST", 2 ) == 0 && c - s == 2 ) - oid = OID_AT_STATE; - else - { - printf("Failed to parse subject name.\n"); - goto exit; - } - - s = c + 1; - in_tag = 0; - } - - if( !in_tag && ( *c == ',' || c == end ) ) - { - if( c - s > 127 ) - { - printf("Name too large for buffer.\n"); - goto exit; - } - - if( cur == NULL ) - { - req_name = malloc( sizeof(x509_req_name) ); - cur = req_name; - } - else - { - cur->next = malloc( sizeof(x509_req_name) ); - cur = cur->next; - } - - if( cur == NULL ) - { - printf( "Failed to allocate memory.\n" ); - goto exit; - } - - memset( cur, 0, sizeof(x509_req_name) ); - - strncpy( cur->oid, oid, strlen( oid ) ); - strncpy( cur->name, s, c - s ); - - s = c + 1; - in_tag = 1; - } - c++; +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! x509write_csr_set_subject_name returned %d - %s\n\n", ret, buf ); + goto exit; } /* @@ -275,16 +274,32 @@ int main( int argc, char *argv[] ) error_strerror( ret, buf, 1024 ); #endif printf( " failed\n ! x509parse_key_rsa returned %d - %s\n\n", ret, buf ); - rsa_free( &rsa ); + goto exit; + } + + x509write_csr_set_rsa_key( &req, &rsa ); + + printf( " ok\n" ); + + /* + * 1.2. Writing the request + */ + printf( " . Writing the certificate request ..." ); + fflush( stdout ); + + if( ( ret = write_certificate_request( &req, opt.output_file ) ) != 0 ) + { +#ifdef POLARSSL_ERROR_C + error_strerror( ret, buf, 1024 ); +#endif + printf( " failed\n ! write_certifcate_request %d - %s\n\n", ret, buf ); goto exit; } printf( " ok\n" ); - write_certificate_request( &rsa, req_name, opt.output_file ); - exit: - + x509write_csr_free( &req ); rsa_free( &rsa ); #if defined(_WIN32) diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 7257ae670..5b9549402 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -13,7 +13,7 @@ my @low_level_modules = ( "AES", "ASN1", "BLOWFISH", "CAMELLIA", "BIGNUM", "PADLOCK", "DES", "NET", "CTR_DRBG", "ENTROPY", "MD2", "MD4", "MD5", "SHA1", "SHA256", "SHA512", "GCM" ); my @high_level_modules = ( "PEM", "X509", "DHM", "RSA", "ECP", "MD", "CIPHER", "SSL", - "PK", "PKCS12", "PKCS5" ); + "PK", "PKCS12", "PKCS5", "X509WRITE" ); my $line_separator = $/; undef $/; @@ -49,6 +49,7 @@ while (my $line = ) my $define_name = $module_name; $define_name = "X509_PARSE" if ($define_name eq "X509"); + $define_name = "X509_WRITE" if ($define_name eq "X509WRITE"); $define_name = "ASN1_PARSE" if ($define_name eq "ASN1"); $define_name = "SSL_TLS" if ($define_name eq "SSL"); diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index c4984360b..7a48440e4 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -1,27 +1,27 @@ Certificate Request check Server1 SHA1 depends_on:POLARSSL_SHA1_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA1:"data_files/server1.req.sha1" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA1:"data_files/server1.req.sha1" Certificate Request check Server1 SHA224 depends_on:POLARSSL_SHA256_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA224:"data_files/server1.req.sha224" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA224:"data_files/server1.req.sha224" Certificate Request check Server1 SHA256 depends_on:POLARSSL_SHA256_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA256:"data_files/server1.req.sha256" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA256:"data_files/server1.req.sha256" Certificate Request check Server1 SHA384 depends_on:POLARSSL_SHA512_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA384:"data_files/server1.req.sha384" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA384:"data_files/server1.req.sha384" Certificate Request check Server1 SHA512 depends_on:POLARSSL_SHA512_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_SHA512:"data_files/server1.req.sha512" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_SHA512:"data_files/server1.req.sha512" Certificate Request check Server1 MD4 depends_on:POLARSSL_MD4_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_MD4:"data_files/server1.req.md4" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD4:"data_files/server1.req.md4" Certificate Request check Server1 MD5 depends_on:POLARSSL_MD5_C -x509_cert_req_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req.md5" +x509_csr_check:"data_files/server1.key":POLARSSL_MD_MD5:"data_files/server1.req.md5" diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 680dfb4c4..d3c801a1d 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -11,36 +11,19 @@ */ /* BEGIN_CASE */ -void x509_cert_req_check( char *key_file, int md_type, +void x509_csr_check( char *key_file, int md_type, char *cert_req_check_file ) { rsa_context rsa; pem_context pem; - x509_req_name req_name, *cur; + x509_csr req; unsigned char *c; unsigned char buf[4000]; unsigned char check_buf[4000]; int ret; size_t olen = 2000; FILE *f; - - cur = &req_name; - - memset( cur, 0, sizeof(x509_req_name) ); - strcpy( cur->oid, OID_AT_CN ); - strcpy( cur->name, "PolarSSL Server 1" ); - cur->next = malloc( sizeof(x509_req_name) ); - cur = cur->next; - - memset( cur, 0, sizeof(x509_req_name) ); - strcpy( cur->oid, OID_AT_ORGANIZATION ); - strcpy( cur->name, "PolarSSL" ); - cur->next = malloc( sizeof(x509_req_name) ); - cur = cur->next; - - memset( cur, 0, sizeof(x509_req_name) ); - strcpy( cur->oid, OID_AT_COUNTRY ); - strcpy( cur->name, "NL" ); + char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1"; memset( &rsa, 0, sizeof(rsa_context) ); ret = x509parse_keyfile_rsa( &rsa, key_file, NULL ); @@ -48,7 +31,12 @@ void x509_cert_req_check( char *key_file, int md_type, if( ret != 0 ) return; - ret = x509_write_cert_req( buf, 4000, &rsa, &req_name, md_type ); + x509write_csr_init( &req ); + x509write_csr_set_md_alg( &req, md_type ); + x509write_csr_set_rsa_key( &req, &rsa ); + TEST_ASSERT( x509write_csr_set_subject_name( &req, subject_name ) == 0 ); + + ret = x509write_csr_der( &req, buf, 4000 ); TEST_ASSERT( ret >= 0 ); c = buf + 3999 - ret; @@ -64,12 +52,7 @@ void x509_cert_req_check( char *key_file, int md_type, TEST_ASSERT( memcmp( c, pem.buf, pem.buflen ) == 0 ); TEST_ASSERT( pem.buflen == (size_t) ret ); - while( ( cur = req_name.next ) != NULL ) - { - req_name.next = cur->next; - free( cur ); - } - + x509write_csr_free( &req ); rsa_free( &rsa ); pem_free( &pem ); }