mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-25 17:55:42 +01:00
Merged refactored x509write module into development
This commit is contained in:
commit
ca174fef80
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -83,6 +83,7 @@
|
||||
* 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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -169,13 +169,7 @@ typedef asn1_bitstring x509_bitstring;
|
||||
* 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
|
||||
@ -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.
|
||||
* - <tt>typedef struct _x509_node x509_node;</tt>
|
||||
* - <tt>typedef struct _x509_raw x509_raw;</tt>
|
||||
*/
|
||||
/*
|
||||
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
|
||||
* \{
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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,15 +209,8 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start,
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
// Write string
|
||||
//
|
||||
len = strlen( text );
|
||||
|
||||
if( *p - start < (int) len )
|
||||
return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
(*p) -= len;
|
||||
memcpy( *p, text, len );
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
|
||||
(const unsigned char *) text, strlen( text ) ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_PRINTABLE_STRING ) );
|
||||
@ -223,15 +224,8 @@ int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
// Write string
|
||||
//
|
||||
len = strlen( text );
|
||||
|
||||
if( *p - start < (int) len )
|
||||
return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
(*p) -= len;
|
||||
memcpy( *p, text, len );
|
||||
ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
|
||||
(const unsigned char *) text, strlen( text ) ) );
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_IA5_STRING ) );
|
||||
@ -239,5 +233,44 @@ int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
|
||||
return( len );
|
||||
}
|
||||
|
||||
int asn1_write_bitstring( unsigned char **p, unsigned char *start,
|
||||
const unsigned char *buf, size_t bits )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0, size;
|
||||
|
||||
size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 );
|
||||
|
||||
// Calculate byte length
|
||||
//
|
||||
if( *p - start < (int) size + 1 )
|
||||
return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL );
|
||||
|
||||
len = size + 1;
|
||||
(*p) -= size;
|
||||
memcpy( *p, buf, size );
|
||||
|
||||
// Write unused bits
|
||||
//
|
||||
*--(*p) = size * 8 - bits;
|
||||
|
||||
ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
|
||||
ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_BIT_STRING ) );
|
||||
|
||||
return( len );
|
||||
}
|
||||
|
||||
int asn1_write_octet_string( unsigned char **p, unsigned char *start,
|
||||
const unsigned char *buf, size_t size )
|
||||
{
|
||||
int ret;
|
||||
size_t len = 0;
|
||||
|
||||
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
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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 <stdlib.h>
|
||||
#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
|
||||
|
1
programs/.gitignore
vendored
1
programs/.gitignore
vendored
@ -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
|
||||
|
@ -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 $@
|
||||
|
@ -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_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;
|
||||
if( opt.output_format == OUTPUT_FORMAT_PEM )
|
||||
{
|
||||
if( ( ret = x509write_pubkey_pem( rsa, output_buf, 16000 ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
len = strlen( (char *) output_buf );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( ret = x509write_pubkey_der( rsa, output_buf, 16000 ) ) < 0 )
|
||||
return( ret );
|
||||
|
||||
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)
|
||||
{
|
||||
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");
|
||||
c = output_buf + sizeof(output_buf) - len - 1;
|
||||
}
|
||||
fprintf(f, "-----END PUBLIC KEY-----\n");
|
||||
|
||||
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;
|
||||
if( opt.output_format == OUTPUT_FORMAT_PEM )
|
||||
{
|
||||
if( ( ret = x509write_key_pem( rsa, output_buf, 16000 ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
len = strlen( (char *) output_buf );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ( ret = x509write_key_der( rsa, output_buf, 16000 ) ) < 0 )
|
||||
return( ret );
|
||||
|
||||
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)
|
||||
{
|
||||
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");
|
||||
c = output_buf + sizeof(output_buf) - len - 1;
|
||||
}
|
||||
fprintf(f, "-----END RSA PRIVATE KEY-----\n");
|
||||
|
||||
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 )
|
||||
|
@ -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)
|
||||
|
288
programs/util/pem2der.c
Normal file
288
programs/util/pem2der.c
Normal file
@ -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 <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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 */
|
@ -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)
|
||||
|
@ -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 );
|
||||
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,83 +184,82 @@ 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");
|
||||
#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;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1.1. Load the key
|
||||
*/
|
||||
@ -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)
|
||||
|
@ -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 = <GREP>)
|
||||
|
||||
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");
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user