mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

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-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 /*
00022  * References:
00023  * - CSRs: PKCS#10 v1.7 aka RFC 2986
00024  * - attributes: PKCS#9 v2.0 aka RFC 2985
00025  */
00026 
00027 #if !defined(MBEDTLS_CONFIG_FILE)
00028 #include "mbedtls/config.h"
00029 #else
00030 #include MBEDTLS_CONFIG_FILE
00031 #endif
00032 
00033 #if defined(MBEDTLS_X509_CSR_WRITE_C)
00034 
00035 #include "mbedtls/x509_csr.h"
00036 #include "mbedtls/oid.h"
00037 #include "mbedtls/asn1write.h"
00038 
00039 #include <string.h>
00040 #include <stdlib.h>
00041 
00042 #if defined(MBEDTLS_PEM_WRITE_C)
00043 #include "mbedtls/pem.h"
00044 #endif
00045 
00046 /* Implementation that should never be optimized out by the compiler */
00047 static void mbedtls_zeroize( void *v, size_t n ) {
00048     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00049 }
00050 
00051 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
00052 {
00053     memset( ctx, 0, sizeof(mbedtls_x509write_csr) );
00054 }
00055 
00056 void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )
00057 {
00058     mbedtls_asn1_free_named_data_list( &ctx->subject );
00059     mbedtls_asn1_free_named_data_list( &ctx->extensions );
00060 
00061     mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_csr) );
00062 }
00063 
00064 void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )
00065 {
00066     ctx->md_alg = md_alg;
00067 }
00068 
00069 void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key )
00070 {
00071     ctx->key = key;
00072 }
00073 
00074 int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
00075                                     const char *subject_name )
00076 {
00077     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
00078 }
00079 
00080 int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
00081                                  const char *oid, size_t oid_len,
00082                                  const unsigned char *val, size_t val_len )
00083 {
00084     return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
00085                                0, val, val_len );
00086 }
00087 
00088 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
00089 {
00090     unsigned char buf[4];
00091     unsigned char *c;
00092     int ret;
00093 
00094     c = buf + 4;
00095 
00096     if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
00097         return( ret );
00098 
00099     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
00100                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
00101                                        buf, 4 );
00102     if( ret != 0 )
00103         return( ret );
00104 
00105     return( 0 );
00106 }
00107 
00108 int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
00109                                     unsigned char ns_cert_type )
00110 {
00111     unsigned char buf[4];
00112     unsigned char *c;
00113     int ret;
00114 
00115     c = buf + 4;
00116 
00117     if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
00118         return( ret );
00119 
00120     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
00121                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
00122                                        buf, 4 );
00123     if( ret != 0 )
00124         return( ret );
00125 
00126     return( 0 );
00127 }
00128 
00129 int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
00130                        int (*f_rng)(void *, unsigned char *, size_t),
00131                        void *p_rng )
00132 {
00133     int ret;
00134     const char *sig_oid;
00135     size_t sig_oid_len = 0;
00136     unsigned char *c, *c2;
00137     unsigned char hash[64];
00138     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
00139     unsigned char tmp_buf[2048];
00140     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
00141     size_t len = 0;
00142     mbedtls_pk_type_t pk_alg;
00143 
00144     /*
00145      * Prepare data to be signed in tmp_buf
00146      */
00147     c = tmp_buf + sizeof( tmp_buf );
00148 
00149     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
00150 
00151     if( len )
00152     {
00153         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00154         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00155                                                         MBEDTLS_ASN1_SEQUENCE ) );
00156 
00157         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00158         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00159                                                         MBEDTLS_ASN1_SET ) );
00160 
00161         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,
00162                                           MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) );
00163 
00164         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00165         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00166                                                         MBEDTLS_ASN1_SEQUENCE ) );
00167     }
00168 
00169     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00170     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00171                                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC ) );
00172 
00173     MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key,
00174                                                 tmp_buf, c - tmp_buf ) );
00175     c -= pub_len;
00176     len += pub_len;
00177 
00178     /*
00179      *  Subject  ::=  Name
00180      */
00181     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
00182 
00183     /*
00184      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00185      */
00186     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) );
00187 
00188     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00189     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00190                                                     MBEDTLS_ASN1_SEQUENCE ) );
00191 
00192     /*
00193      * Prepare signature
00194      */
00195     mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
00196 
00197     pk_alg = mbedtls_pk_get_type( ctx->key );
00198     if( pk_alg == MBEDTLS_PK_ECKEY )
00199         pk_alg = MBEDTLS_PK_ECDSA;
00200 
00201     if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
00202                          f_rng, p_rng ) ) != 0 ||
00203         ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
00204                                         &sig_oid, &sig_oid_len ) ) != 0 )
00205     {
00206         return( ret );
00207     }
00208 
00209     /*
00210      * Write data to output buffer
00211      */
00212     c2 = buf + size;
00213     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
00214                                         sig_oid, sig_oid_len, sig, sig_len ) );
00215 
00216     c2 -= len;
00217     memcpy( c2, c, len );
00218 
00219     len += sig_and_oid_len;
00220     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
00221     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
00222                                                  MBEDTLS_ASN1_SEQUENCE ) );
00223 
00224     return( (int) len );
00225 }
00226 
00227 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"
00228 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"
00229 
00230 #if defined(MBEDTLS_PEM_WRITE_C)
00231 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,
00232                        int (*f_rng)(void *, unsigned char *, size_t),
00233                        void *p_rng )
00234 {
00235     int ret;
00236     unsigned char output_buf[4096];
00237     size_t olen = 0;
00238 
00239     if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),
00240                                    f_rng, p_rng ) ) < 0 )
00241     {
00242         return( ret );
00243     }
00244 
00245     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
00246                                   output_buf + sizeof(output_buf) - ret,
00247                                   ret, buf, size, &olen ) ) != 0 )
00248     {
00249         return( ret );
00250     }
00251 
00252     return( 0 );
00253 }
00254 #endif /* MBEDTLS_PEM_WRITE_C */
00255 
00256 #endif /* MBEDTLS_X509_CSR_WRITE_C */