mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509write_csr.c Source File

x509write_csr.c

00001 /*
00002  *  X.509 Certificate Signing Request writing
00003  *
00004  *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
00005  *
00006  *  This file is part of mbed TLS (https://tls.mbed.org)
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License along
00019  *  with this program; if not, write to the Free Software Foundation, Inc.,
00020  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021  */
00022 /*
00023  * References:
00024  * - CSRs: PKCS#10 v1.7 aka RFC 2986
00025  * - attributes: PKCS#9 v2.0 aka RFC 2985
00026  */
00027 
00028 #if !defined(POLARSSL_CONFIG_FILE)
00029 #include "polarssl/config.h"
00030 #else
00031 #include POLARSSL_CONFIG_FILE
00032 #endif
00033 
00034 #if defined(POLARSSL_X509_CSR_WRITE_C)
00035 
00036 #include "polarssl/x509_csr.h"
00037 #include "polarssl/oid.h"
00038 #include "polarssl/asn1write.h"
00039 
00040 #include <string.h>
00041 #include <stdlib.h>
00042 
00043 #if defined(POLARSSL_PEM_WRITE_C)
00044 #include "polarssl/pem.h"
00045 #endif
00046 
00047 /* Implementation that should never be optimized out by the compiler */
00048 static void polarssl_zeroize( void *v, size_t n ) {
00049     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00050 }
00051 
00052 void x509write_csr_init( x509write_csr *ctx )
00053 {
00054     memset( ctx, 0, sizeof(x509write_csr) );
00055 }
00056 
00057 void x509write_csr_free( x509write_csr *ctx )
00058 {
00059     asn1_free_named_data_list( &ctx->subject );
00060     asn1_free_named_data_list( &ctx->extensions );
00061 
00062     polarssl_zeroize( ctx, sizeof(x509write_csr) );
00063 }
00064 
00065 void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg )
00066 {
00067     ctx->md_alg = md_alg;
00068 }
00069 
00070 void x509write_csr_set_key( x509write_csr *ctx, pk_context *key )
00071 {
00072     ctx->key = key;
00073 }
00074 
00075 int x509write_csr_set_subject_name( x509write_csr *ctx,
00076                                     const char *subject_name )
00077 {
00078     return x509_string_to_names( &ctx->subject, subject_name );
00079 }
00080 
00081 int x509write_csr_set_extension( x509write_csr *ctx,
00082                                  const char *oid, size_t oid_len,
00083                                  const unsigned char *val, size_t val_len )
00084 {
00085     return x509_set_extension( &ctx->extensions, oid, oid_len,
00086                                0, val, val_len );
00087 }
00088 
00089 int x509write_csr_set_key_usage( x509write_csr *ctx, unsigned char key_usage )
00090 {
00091     unsigned char buf[4];
00092     unsigned char *c;
00093     int ret;
00094 
00095     c = buf + 4;
00096 
00097     if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
00098         return( ret );
00099 
00100     ret = x509write_csr_set_extension( ctx, OID_KEY_USAGE,
00101                                        OID_SIZE( OID_KEY_USAGE ),
00102                                        buf, 4 );
00103     if( ret != 0 )
00104         return( ret );
00105 
00106     return( 0 );
00107 }
00108 
00109 int x509write_csr_set_ns_cert_type( x509write_csr *ctx,
00110                                     unsigned char ns_cert_type )
00111 {
00112     unsigned char buf[4];
00113     unsigned char *c;
00114     int ret;
00115 
00116     c = buf + 4;
00117 
00118     if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
00119         return( ret );
00120 
00121     ret = x509write_csr_set_extension( ctx, OID_NS_CERT_TYPE,
00122                                        OID_SIZE( OID_NS_CERT_TYPE ),
00123                                        buf, 4 );
00124     if( ret != 0 )
00125         return( ret );
00126 
00127     return( 0 );
00128 }
00129 
00130 int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size,
00131                        int (*f_rng)(void *, unsigned char *, size_t),
00132                        void *p_rng )
00133 {
00134     int ret;
00135     const char *sig_oid;
00136     size_t sig_oid_len = 0;
00137     unsigned char *c, *c2;
00138     unsigned char hash[64];
00139     unsigned char sig[POLARSSL_MPI_MAX_SIZE];
00140     unsigned char tmp_buf[2048];
00141     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
00142     size_t len = 0;
00143     pk_type_t pk_alg;
00144 
00145     /*
00146      * Prepare data to be signed in tmp_buf
00147      */
00148     c = tmp_buf + sizeof( tmp_buf );
00149 
00150     ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
00151 
00152     if( len )
00153     {
00154         ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
00155         ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
00156                                                         ASN1_SEQUENCE ) );
00157 
00158         ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
00159         ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
00160                                                         ASN1_SET ) );
00161 
00162         ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ,
00163                                           OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) );
00164 
00165         ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
00166         ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
00167                                                         ASN1_SEQUENCE ) );
00168     }
00169 
00170     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
00171     ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
00172                                                     ASN1_CONTEXT_SPECIFIC ) );
00173 
00174     ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key,
00175                                                 tmp_buf, c - tmp_buf ) );
00176     c -= pub_len;
00177     len += pub_len;
00178 
00179     /*
00180      *  Subject  ::=  Name
00181      */
00182     ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
00183 
00184     /*
00185      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00186      */
00187     ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) );
00188 
00189     ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
00190     ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
00191                                                     ASN1_SEQUENCE ) );
00192 
00193     /*
00194      * Prepare signature
00195      */
00196     md( md_info_from_type( ctx->md_alg ), c, len, hash );
00197 
00198     pk_alg = pk_get_type( ctx->key );
00199     if( pk_alg == POLARSSL_PK_ECKEY )
00200         pk_alg = POLARSSL_PK_ECDSA;
00201 
00202     if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
00203                          f_rng, p_rng ) ) != 0 ||
00204         ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
00205                                         &sig_oid, &sig_oid_len ) ) != 0 )
00206     {
00207         return( ret );
00208     }
00209 
00210     /*
00211      * Write data to output buffer
00212      */
00213     c2 = buf + size;
00214     ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
00215                                         sig_oid, sig_oid_len, sig, sig_len ) );
00216 
00217     c2 -= len;
00218     memcpy( c2, c, len );
00219 
00220     len += sig_and_oid_len;
00221     ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
00222     ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
00223                                                  ASN1_SEQUENCE ) );
00224 
00225     return( (int) len );
00226 }
00227 
00228 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
00229 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
00230 
00231 #if defined(POLARSSL_PEM_WRITE_C)
00232 int x509write_csr_pem( x509write_csr *ctx, unsigned char *buf, size_t size,
00233                        int (*f_rng)(void *, unsigned char *, size_t),
00234                        void *p_rng )
00235 {
00236     int ret;
00237     unsigned char output_buf[4096];
00238     size_t olen = 0;
00239 
00240     if( ( ret = x509write_csr_der( ctx, output_buf, sizeof(output_buf),
00241                                    f_rng, p_rng ) ) < 0 )
00242     {
00243         return( ret );
00244     }
00245 
00246     if( ( ret = pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
00247                                   output_buf + sizeof(output_buf) - ret,
00248                                   ret, buf, size, &olen ) ) != 0 )
00249     {
00250         return( ret );
00251     }
00252 
00253     return( 0 );
00254 }
00255 #endif /* POLARSSL_PEM_WRITE_C */
00256 
00257 #endif /* POLARSSL_X509_CSR_WRITE_C */
00258