From 1c0e550e213f67e77c7a2e9618baa002a587a897 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Mon, 26 Aug 2013 13:41:01 +0200 Subject: [PATCH] Added support for Netscape Certificate Types in CSR writing Further generalization of extension adding / replacing in the CSR structure --- include/polarssl/x509write.h | 28 +++++++++++- library/x509write.c | 84 +++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h index 671047429..a8e672add 100644 --- a/include/polarssl/x509write.h +++ b/include/polarssl/x509write.h @@ -130,12 +130,38 @@ void x509write_csr_set_md_alg( x509_csr *ctx, md_type_t md_alg ); * (e.g. KU_DIGITAL_SIGNATURE | KU_KEY_CERT_SIGN) * * \param ctx CSR context to use - * \param key_usage key usage bitstring to set + * \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 * diff --git a/library/x509write.c b/library/x509write.c index 0ca7733b2..f609fb454 100644 --- a/library/x509write.c +++ b/library/x509write.c @@ -156,14 +156,14 @@ exit: return( ret ); } -int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) +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; - unsigned char *c; - int len; - if( ( cur = asn1_find_named_data( ctx->extensions, OID_KEY_USAGE, - OID_SIZE( OID_KEY_USAGE ) ) ) == NULL ) + if( ( cur = asn1_find_named_data( ctx->extensions, oid, + oid_len ) ) == NULL ) { cur = polarssl_malloc( sizeof(asn1_named_data) ); if( cur == NULL ) @@ -171,32 +171,84 @@ int x509write_csr_set_key_usage( x509_csr *ctx, unsigned char key_usage ) memset( cur, 0, sizeof(asn1_named_data) ); - cur->oid.len = OID_SIZE( OID_KEY_USAGE ); - cur->oid.p = polarssl_malloc( cur->oid.len ); + cur->oid.len = oid_len; + cur->oid.p = polarssl_malloc( oid_len ); if( cur->oid.p == NULL ) { - free( cur ); + polarssl_free( cur ); return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } - cur->val.len = 4; - cur->val.p = polarssl_malloc( cur->val.len ); + cur->val.len = val_len; + cur->val.p = polarssl_malloc( val_len ); if( cur->val.p == NULL ) { - free( cur->oid.p ); - free( cur ); + polarssl_free( cur->oid.p ); + polarssl_free( cur ); return( POLARSSL_ERR_X509WRITE_MALLOC_FAILED ); } - memcpy( cur->oid.p, OID_KEY_USAGE, OID_SIZE( OID_KEY_USAGE ) ); + memcpy( cur->oid.p, oid, oid_len ); cur->next = ctx->extensions; ctx->extensions = cur; } - c = cur->val.p + cur->val.len; - if( ( len = asn1_write_bitstring( &c, cur->val.p, &key_usage, 6 ) ) < 0 ) -exit(1); + 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, 6 ) ) != 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 ); }