Commit 9013af76 authored by Paul Bakker's avatar Paul Bakker
Browse files

Merged major refactoring of x509write module into development

This refactoring adds support for proper CSR writing and X509
certificate generation / signing
parents 18f0341a 0237620a
......@@ -154,8 +154,8 @@ typedef struct _asn1_named_data
asn1_named_data;
/**
* Get the length of an ASN.1 element.
* Updates the pointer to immediately behind the length.
* \brief Get the length of an ASN.1 element.
* Updates the pointer to immediately behind the length.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -170,8 +170,8 @@ int asn1_get_len( unsigned char **p,
size_t *len );
/**
* Get the tag and length of the tag. Check for the requested tag.
* Updates the pointer to immediately behind the tag and length.
* \brief Get the tag and length of the tag. Check for the requested tag.
* Updates the pointer to immediately behind the tag and length.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -186,8 +186,8 @@ int asn1_get_tag( unsigned char **p,
size_t *len, int tag );
/**
* Retrieve a boolean ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
* \brief Retrieve a boolean ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -200,8 +200,8 @@ int asn1_get_bool( unsigned char **p,
int *val );
/**
* Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
* \brief Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -214,8 +214,8 @@ int asn1_get_int( unsigned char **p,
int *val );
/**
* Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
* \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -227,8 +227,9 @@ int asn1_get_bitstring( unsigned char **p, const unsigned char *end,
asn1_bitstring *bs);
/**
* Retrieve a bitstring ASN.1 tag without unused bits and its value.
* Updates the pointer to the beginning of the bit/octet string.
* \brief Retrieve a bitstring ASN.1 tag without unused bits and its
* value.
* Updates the pointer to the beginning of the bit/octet string.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -240,8 +241,8 @@ int asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
size_t *len );
/**
* Parses and splits an ASN.1 "SEQUENCE OF <tag>"
* Updated the pointer to immediately behind the full sequence tag.
* \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>"
* Updated the pointer to immediately behind the full sequence tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -257,8 +258,8 @@ int asn1_get_sequence_of( unsigned char **p,
#if defined(POLARSSL_BIGNUM_C)
/**
* Retrieve a MPI value from an integer ASN.1 tag.
* Updates the pointer to immediately behind the full tag.
* \brief Retrieve a MPI value from an integer ASN.1 tag.
* Updates the pointer to immediately behind the full tag.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -272,8 +273,9 @@ int asn1_get_mpi( unsigned char **p,
#endif
/**
* Retrieve an AlgorithmIdentifier ASN.1 sequence.
* Updates the pointer to immediately behind the full AlgorithmIdentifier.
* \brief Retrieve an AlgorithmIdentifier ASN.1 sequence.
* Updates the pointer to immediately behind the full
* AlgorithmIdentifier.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -287,8 +289,10 @@ int asn1_get_alg( unsigned char **p,
asn1_buf *alg, asn1_buf *params );
/**
* Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no params.
* Updates the pointer to immediately behind the full AlgorithmIdentifier.
* \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no
* params.
* Updates the pointer to immediately behind the full
* AlgorithmIdentifier.
*
* \param p The position in the ASN.1 data
* \param end End of data
......@@ -301,7 +305,8 @@ int asn1_get_alg_null( unsigned char **p,
asn1_buf *alg );
/**
* Find a specific named_data entry in a sequence or list based on the OID.
* \brief Find a specific named_data entry in a sequence or list based on
* the OID.
*
* \param list The list to seek through
* \param oid The OID to look for
......@@ -313,12 +318,20 @@ asn1_named_data *asn1_find_named_data( asn1_named_data *list,
const char *oid, size_t len );
/**
* Free a asn1_named_data entry
* \brief Free a asn1_named_data entry
*
* \param entry The named data entry to free
*/
void asn1_free_named_data( asn1_named_data *entry );
/**
* \brief Free all entries in a asn1_named_data list
* Head will be set to NULL
*
* \param head Pointer to the head of the list of named data entries to free
*/
void asn1_free_named_data_list( asn1_named_data **head );
#ifdef __cplusplus
}
#endif
......
......@@ -29,7 +29,7 @@
#include "asn1.h"
#define ASN1_CHK_ADD(g, f) if( ( ret = f ) < 0 ) return( ret ); else g += ret
#define ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else g += ret; } while( 0 )
#ifdef __cplusplus
extern "C" {
......@@ -105,24 +105,41 @@ int asn1_write_null( unsigned char **p, unsigned char *start );
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param oid the OID to write
* \param oid_len length of the OID
*
* \return the length written or a negative error code
*/
int asn1_write_oid( unsigned char **p, unsigned char *start, const char *oid );
int asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len );
/**
* \brief Write an AlgorithmIdentifier sequence in ASN.1 format
* Note: function works backwards in data buffer
* Note: Uses NULL as algorithm parameter
*
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param oid the OID of the algorithm
* \param oid_len length of the OID
* \param par_len length of parameters, which must be already written.
* If 0, NULL parameters are added
*
* \return the length written or a negative error code
*/
int asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
const char *oid );
const char *oid, size_t oid_len,
size_t par_len );
/**
* \brief Write a boolean tag (ASN1_BOOLEAN) and value in ASN.1 format
* Note: function works backwards in data buffer
*
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param boolean 0 or 1
*
* \return the length written or a negative error code
*/
int asn1_write_bool( unsigned char **p, unsigned char *start, int boolean );
/**
* \brief Write an int tag (ASN1_INTEGER) and value in ASN.1 format
......@@ -144,11 +161,12 @@ int asn1_write_int( unsigned char **p, unsigned char *start, int val );
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param text the text to write
* \param text_len length of the text
*
* \return the length written or a negative error code
*/
int asn1_write_printable_string( unsigned char **p, unsigned char *start,
char *text );
const char *text, size_t text_len );
/**
* \brief Write an IA5 string tag (ASN1_IA5_STRING) and
......@@ -158,11 +176,12 @@ int asn1_write_printable_string( unsigned char **p, unsigned char *start,
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param text the text to write
* \param text_len length of the text
*
* \return the length written or a negative error code
*/
int asn1_write_ia5_string( unsigned char **p, unsigned char *start,
char *text );
const char *text, size_t text_len );
/**
* \brief Write a bitstring tag (ASN1_BIT_STRING) and
......@@ -193,6 +212,28 @@ int asn1_write_bitstring( unsigned char **p, unsigned char *start,
*/
int asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size );
/**
* \brief Create or find a specific named_data entry for writing in a
* sequence or list based on the OID. If not already in there,
* a new entry is added to the head of the list.
* Warning: Destructive behaviour for the val data!
*
* \param list Pointer to the location of the head of the list to seek
* through (will be updated in case of a new entry)
* \param oid The OID to look for
* \param oid_len Size of the OID
* \param val Data to store (can be NULL if you want to fill it by hand)
* \param val_len Minimum length of the data buffer needed
*
* \return NULL if if there was a memory allocation error, or a pointer
* to the new / existing entry.
*/
asn1_named_data *asn1_store_named_data( asn1_named_data **list,
const char *oid, size_t oid_len,
const unsigned char *val,
size_t val_len );
#ifdef __cplusplus
}
#endif
......
......@@ -401,11 +401,11 @@
/**
* \def POLARSSL_ERROR_STRERROR_DUMMY
*
* Enable a dummy error function to make use of error_strerror() in
* Enable a dummy error function to make use of polarssl_strerror() in
* third party libraries easier.
*
* Disable if you run into name conflicts and want to really remove the
* error_strerror()
* polarssl_strerror()
*/
#define POLARSSL_ERROR_STRERROR_DUMMY
......@@ -1384,7 +1384,7 @@
*
* Module: library/x509write.c
*
* Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_RSA_C
* Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_C
*
* This module is required for X.509 certificate request writing.
*/
......
......@@ -133,6 +133,7 @@ ecp_keypair;
*/
#define POLARSSL_ECP_MAX_BITS 521
#define POLARSSL_ECP_MAX_BYTES ( ( POLARSSL_ECP_MAX_BITS + 7 ) / 8 )
#define POLARSSL_ECP_MAX_PT_LEN ( 2 * POLARSSL_ECP_MAX_BYTES + 1 )
/*
* Maximum window size (actually, NAF width) used for point multipliation.
......
......@@ -371,7 +371,20 @@ int oid_get_attr_short_name( const asn1_buf *oid, const char **short_name );
int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg );
/**
* \brief Translate ECParameters OID into an EC group identifier
* \brief Translate pk_type into PublicKeyAlgorithm OID
*
* \param pk_alg Public key type to look for
* \param oid place to store ASN.1 OID string pointer
* \param olen length of the OID
*
* \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND
*/
int oid_get_oid_by_pk_alg( pk_type_t pk_alg,
const char **oid, size_t *olen );
#if defined(POLARSSL_ECP_C)
/**
* \brief Translate NamedCurve OID into an EC group identifier
*
* \param oid OID to use
* \param grp_id place to store group id
......@@ -380,6 +393,19 @@ int oid_get_pk_alg( const asn1_buf *oid, pk_type_t *pk_alg );
*/
int oid_get_ec_grp( const asn1_buf *oid, ecp_group_id *grp_id );
/**
* \brief Translate EC group identifier into NamedCurve OID
*
* \param grp_id EC group identifier
* \param oid place to store ASN.1 OID string pointer
* \param olen length of the OID
*
* \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND
*/
int oid_get_oid_by_ec_grp( ecp_group_id grp_id,
const char **oid, size_t *olen );
#endif /* POLARSSL_ECP_C */
#if defined(POLARSSL_MD_C)
/**
* \brief Translate SignatureAlgorithm OID into md_type and pk_type
......@@ -409,11 +435,12 @@ int oid_get_sig_alg_desc( const asn1_buf *oid, const char **desc );
* \param md_alg message digest algorithm
* \param pk_alg public key algorithm
* \param oid place to store ASN.1 OID string pointer
* \param olen length of the OID
*
* \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND
*/
int oid_get_oid_by_sig_alg( pk_type_t pk_alg, md_type_t md_alg,
const char **oid );
const char **oid, size_t *olen );
/**
* \brief Translate hash algorithm OID into md_type
......@@ -441,10 +468,11 @@ int oid_get_extended_key_usage( const asn1_buf *oid, const char **desc );
*
* \param md_alg message digest algorithm
* \param oid place to store ASN.1 OID string pointer
* \param olen length of the OID
*
* \return 0 if successful, or POLARSSL_ERR_OID_NOT_FOUND
*/
int oid_get_oid_by_md( md_type_t md_alg, const char **oid );
int oid_get_oid_by_md( md_type_t md_alg, const char **oid, size_t *olen );
#if defined(POLARSSL_CIPHER_C)
/**
......
......@@ -369,6 +369,15 @@ int pk_debug( const pk_context *ctx, pk_debug_item *items );
*/
const char * pk_get_name( const pk_context *ctx );
/**
* \brief Get the key typee
*
* \param ctx Context to use
*
* \return Type on success, or POLARSSL_PK_NONE
*/
pk_type_t pk_get_type( const pk_context *ctx );
#ifdef __cplusplus
}
#endif
......
......@@ -31,8 +31,6 @@
#if defined(POLARSSL_X509_PARSE_C) || defined(POLARSSL_X509_WRITE_C)
#include "asn1.h"
#include "rsa.h"
#include "ecp.h"
#include "dhm.h"
#include "md.h"
#include "pk.h"
......@@ -151,7 +149,7 @@ extern "C" {
* \{ */
/**
* \name Structures for parsing X.509 certificates and CRLs
* \name Structures for parsing X.509 certificates, CRLs and CSRs
* \{
*/
......@@ -227,12 +225,12 @@ typedef struct _x509_cert
md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
struct _x509_cert *next; /**< Next certificate in the CA-chain. */
struct _x509_cert *next; /**< Next certificate in the CA-chain. */
}
x509_cert;
/**
* Certificate revocation list entry.
/**
* Certificate revocation list entry.
* Contains the CA-specific serial numbers and revocation dates.
*/
typedef struct _x509_crl_entry
......@@ -249,8 +247,8 @@ typedef struct _x509_crl_entry
}
x509_crl_entry;
/**
* Certificate revocation list structure.
/**
* Certificate revocation list structure.
* Every CRL may have multiple entries.
*/
typedef struct _x509_crl
......@@ -265,7 +263,7 @@ typedef struct _x509_crl
x509_name issuer; /**< The parsed issuer data (named information object). */
x509_time this_update;
x509_time this_update;
x509_time next_update;
x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */
......@@ -277,10 +275,32 @@ typedef struct _x509_crl
md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
struct _x509_crl *next;
struct _x509_crl *next;
}
x509_crl;
/** \} name Structures for parsing X.509 certificates and CRLs */
/**
* Certificate Signing Request (CSR) structure.
*/
typedef struct _x509_csr
{
x509_buf raw; /**< The raw CSR data (DER). */
x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */
int version;
x509_buf subject_raw; /**< The raw subject data (DER). */
x509_name subject; /**< The parsed subject data (named information object). */
pk_context pk; /**< Container for the public key context. */
x509_buf sig_oid;
x509_buf sig;
md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. POLARSSL_MD_SHA256 */
pk_type_t sig_pk /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. POLARSSL_PK_RSA */;
}
x509_csr;
/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
/** \} addtogroup x509_module */
/**
......@@ -317,6 +337,7 @@ int x509parse_crt_der( x509_cert *chain, const unsigned char *buf, size_t buflen
*/
int x509parse_crt( x509_cert *chain, const unsigned char *buf, size_t buflen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load one or more certificates and add them
......@@ -348,6 +369,7 @@ int x509parse_crtfile( x509_cert *chain, const char *path );
* if partly successful or a specific X509 or PEM error code
*/
int x509parse_crtpath( x509_cert *chain, const char *path );
#endif /* POLARSSL_FS_IO */
/** \ingroup x509_module */
/**
......@@ -362,6 +384,19 @@ int x509parse_crtpath( x509_cert *chain, const char *path );
*/
int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen );
/** \ingroup x509_module */
/**
* \brief Load a Certificate Signing Request (CSR)
*
* \param csr CSR context to fill
* \param buf buffer holding the CRL data
* \param buflen size of the buffer
*
* \return 0 if successful, or a specific X509 or PEM error code
*/
int x509parse_csr( x509_csr *csr, const unsigned char *buf, size_t buflen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load one or more CRLs and add them
......@@ -374,6 +409,18 @@ int x509parse_crl( x509_crl *chain, const unsigned char *buf, size_t buflen );
*/
int x509parse_crlfile( x509_crl *chain, const char *path );
/** \ingroup x509_module */
/**
* \brief Load a Certificate Signing Request (CSR)
*
* \param csr CSR context to fill
* \param path filename to read the CSR from
*
* \return 0 if successful, or a specific X509 or PEM error code
*/
int x509parse_csrfile( x509_csr *csr, const char *path );
#endif /* POLARSSL_FS_IO */
#if defined(POLARSSL_RSA_C)
/** \ingroup x509_module */
/**
......@@ -391,6 +438,7 @@ int x509parse_key_rsa( rsa_context *rsa,
const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load and parse a private RSA key
......@@ -403,6 +451,7 @@ int x509parse_key_rsa( rsa_context *rsa,
*/
int x509parse_keyfile_rsa( rsa_context *rsa, const char *path,
const char *password );
#endif /* POLARSSL_FS_IO */
/** \ingroup x509_module */
/**
......@@ -417,6 +466,7 @@ int x509parse_keyfile_rsa( rsa_context *rsa, const char *path,
int x509parse_public_key_rsa( rsa_context *rsa,
const unsigned char *key, size_t keylen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load and parse a public RSA key
......@@ -427,6 +477,7 @@ int x509parse_public_key_rsa( rsa_context *rsa,
* \return 0 if successful, or a specific X509 or PEM error code
*/
int x509parse_public_keyfile_rsa( rsa_context *rsa, const char *path );
#endif /* POLARSSL_FS_IO */
#endif /* POLARSSL_RSA_C */
/** \ingroup x509_module */
......@@ -445,6 +496,7 @@ int x509parse_key( pk_context *ctx,
const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load and parse a private key
......@@ -457,6 +509,7 @@ int x509parse_key( pk_context *ctx,
*/
int x509parse_keyfile( pk_context *ctx,
const char *path, const char *password );
#endif /* POLARSSL_FS_IO */
/** \ingroup x509_module */
/**
......@@ -471,6 +524,7 @@ int x509parse_keyfile( pk_context *ctx,
int x509parse_public_key( pk_context *ctx,
const unsigned char *key, size_t keylen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load and parse a public key
......@@ -481,6 +535,7 @@ int x509parse_public_key( pk_context *ctx,
* \return 0 if successful, or a specific X509 or PEM error code
*/
int x509parse_public_keyfile( pk_context *ctx, const char *path );
#endif /* POLARSSL_FS_IO */
/** \ingroup x509_module */
/**
......@@ -494,6 +549,7 @@ int x509parse_public_keyfile( pk_context *ctx, const char *path );
*/
int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen );
#if defined(POLARSSL_FS_IO)
/** \ingroup x509_module */
/**
* \brief Load and parse DHM parameters
......@@ -504,6 +560,7 @@ int x509parse_dhm( dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen
* \return 0 if successful, or a specific X509 or PEM error code
*/
int x509parse_dhmfile( dhm_context *dhm, const char *path );
#endif /* POLARSSL_FS_IO */
/** \} name Functions to read in DHM parameters, a certificate, CRL or private RSA key */
......@@ -563,6 +620,21 @@ int x509parse_cert_info( char *buf, size_t size, const char *prefix,
int x509parse_crl_info( char *buf, size_t size, const char *prefix,
const x509_crl *crl );
/**
* \brief Returns an informational string about the
* CSR.
*
* \param buf Buffer to write to
* \param size Maximum size of buffer
* \param prefix A line prefix
* \param csr The X509 CSR to represent
*
* \return The amount of data written to the buffer, or -1 in
* case of an error.
*/
int x509parse_csr_info( char *buf, size_t size, const char *prefix,
const x509_csr *csr );
/**
* \brief Give an known OID, return its descriptive string.
*
......@@ -680,6 +752,13 @@ void x509_free( x509_cert *crt );
*/
void x509_crl_free( x509_crl *crl );
/**
* \brief Unallocate all CSR data
*
* \param csr CSR to free
*/
void x509_csr_free( x509_csr *csr );
/** \} name Functions to clear a certificate, CRL or private RSA key */
......
......@@ -61,28 +61,41 @@ extern "C" {
*/
/**
* Container for CSR named objects
* Container for a CSR
*/
typedef struct _x509_req_name
typedef struct _x509write_csr
{
char oid[128];
char name[128];
struct _x509_req_name *next;
pk_context *key;
asn1_named_data *subject;
md_type_t md_alg;
asn1_named_data *extensions;
}
x509_req_name;
x509write_csr;