Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509write_crt.c Source File

x509write_crt.c

00001 /*
00002  *  X.509 certificate 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  * - certificates: RFC 5280, updated by RFC 6818
00024  * - CSRs: PKCS#10 v1.7 aka RFC 2986
00025  * - attributes: PKCS#9 v2.0 aka RFC 2985
00026  */
00027 
00028 #if !defined(MBEDTLS_CONFIG_FILE)
00029 #include "mbedtls/config.h"
00030 #else
00031 #include MBEDTLS_CONFIG_FILE
00032 #endif
00033 
00034 #if defined(MBEDTLS_X509_CRT_WRITE_C)
00035 
00036 #include "mbedtls/x509_crt.h"
00037 #include "mbedtls/oid.h"
00038 #include "mbedtls/asn1write.h"
00039 #include "mbedtls/sha1.h"
00040 
00041 #include <string.h>
00042 
00043 #if defined(MBEDTLS_PEM_WRITE_C)
00044 #include "mbedtls/pem.h"
00045 #endif /* MBEDTLS_PEM_WRITE_C */
00046 
00047 /* Implementation that should never be optimized out by the compiler */
00048 static void mbedtls_zeroize( void *v, size_t n ) {
00049     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00050 }
00051 
00052 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
00053 {
00054     memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
00055 
00056     mbedtls_mpi_init( &ctx->serial );
00057     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
00058 }
00059 
00060 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
00061 {
00062     mbedtls_mpi_free( &ctx->serial );
00063 
00064     mbedtls_asn1_free_named_data_list( &ctx->subject );
00065     mbedtls_asn1_free_named_data_list( &ctx->issuer );
00066     mbedtls_asn1_free_named_data_list( &ctx->extensions );
00067 
00068     mbedtls_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
00069 }
00070 
00071 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
00072 {
00073     ctx->version = version;
00074 }
00075 
00076 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg )
00077 {
00078     ctx->md_alg = md_alg;
00079 }
00080 
00081 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
00082 {
00083     ctx->subject_key = key;
00084 }
00085 
00086 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
00087 {
00088     ctx->issuer_key = key;
00089 }
00090 
00091 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
00092                                     const char *subject_name )
00093 {
00094     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
00095 }
00096 
00097 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
00098                                    const char *issuer_name )
00099 {
00100     return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
00101 }
00102 
00103 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial )
00104 {
00105     int ret;
00106 
00107     if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
00108         return( ret );
00109 
00110     return( 0 );
00111 }
00112 
00113 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before,
00114                                 const char *not_after )
00115 {
00116     if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
00117         strlen( not_after )  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
00118     {
00119         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00120     }
00121     strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
00122     strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
00123     ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
00124     ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
00125 
00126     return( 0 );
00127 }
00128 
00129 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
00130                                  const char *oid, size_t oid_len,
00131                                  int critical,
00132                                  const unsigned char *val, size_t val_len )
00133 {
00134     return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
00135                                critical, val, val_len );
00136 }
00137 
00138 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
00139                                          int is_ca, int max_pathlen )
00140 {
00141     int ret;
00142     unsigned char buf[9];
00143     unsigned char *c = buf + sizeof(buf);
00144     size_t len = 0;
00145 
00146     memset( buf, 0, sizeof(buf) );
00147 
00148     if( is_ca && max_pathlen > 127 )
00149         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
00150 
00151     if( is_ca )
00152     {
00153         if( max_pathlen >= 0 )
00154         {
00155             MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
00156         }
00157         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
00158     }
00159 
00160     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00161     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00162                                                 MBEDTLS_ASN1_SEQUENCE ) );
00163 
00164     return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
00165                                         MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
00166                                         0, buf + sizeof(buf) - len, len );
00167 }
00168 
00169 #if defined(MBEDTLS_SHA1_C)
00170 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
00171 {
00172     int ret;
00173     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
00174     unsigned char *c = buf + sizeof(buf);
00175     size_t len = 0;
00176 
00177     memset( buf, 0, sizeof(buf) );
00178     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
00179 
00180     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
00181                             buf + sizeof( buf ) - 20 );
00182     if( ret != 0 )
00183         return( ret );
00184     c = buf + sizeof( buf ) - 20;
00185     len = 20;
00186 
00187     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00188     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
00189 
00190     return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
00191                                         MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
00192                                         0, buf + sizeof(buf) - len, len );
00193 }
00194 
00195 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
00196 {
00197     int ret;
00198     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
00199     unsigned char *c = buf + sizeof( buf );
00200     size_t len = 0;
00201 
00202     memset( buf, 0, sizeof(buf) );
00203     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
00204 
00205     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
00206                             buf + sizeof( buf ) - 20 );
00207     if( ret != 0 )
00208         return( ret );
00209     c = buf + sizeof( buf ) - 20;
00210     len = 20;
00211 
00212     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00213     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
00214 
00215     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
00216     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
00217                                                 MBEDTLS_ASN1_SEQUENCE ) );
00218 
00219     return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
00220                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
00221                                    0, buf + sizeof( buf ) - len, len );
00222 }
00223 #endif /* MBEDTLS_SHA1_C */
00224 
00225 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
00226                                          unsigned int key_usage )
00227 {
00228     unsigned char buf[4], ku;
00229     unsigned char *c;
00230     int ret;
00231 
00232     /* We currently only support 7 bits, from 0x80 to 0x02 */
00233     if( ( key_usage & ~0xfe ) != 0 )
00234         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
00235 
00236     c = buf + 4;
00237     ku = (unsigned char) key_usage;
00238 
00239     if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 )
00240         return( ret );
00241 
00242     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
00243                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
00244                                        1, buf, 4 );
00245     if( ret != 0 )
00246         return( ret );
00247 
00248     return( 0 );
00249 }
00250 
00251 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
00252                                     unsigned char ns_cert_type )
00253 {
00254     unsigned char buf[4];
00255     unsigned char *c;
00256     int ret;
00257 
00258     c = buf + 4;
00259 
00260     if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
00261         return( ret );
00262 
00263     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
00264                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
00265                                        0, buf, 4 );
00266     if( ret != 0 )
00267         return( ret );
00268 
00269     return( 0 );
00270 }
00271 
00272 static int x509_write_time( unsigned char **p, unsigned char *start,
00273                             const char *t, size_t size )
00274 {
00275     int ret;
00276     size_t len = 0;
00277 
00278     /*
00279      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
00280      */
00281     if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
00282     {
00283         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
00284                                              (const unsigned char *) t + 2,
00285                                              size - 2 ) );
00286         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00287         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
00288     }
00289     else
00290     {
00291         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
00292                                                   (const unsigned char *) t,
00293                                                   size ) );
00294         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
00295         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
00296     }
00297 
00298     return( (int) len );
00299 }
00300 
00301 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,
00302                        int (*f_rng)(void *, unsigned char *, size_t),
00303                        void *p_rng )
00304 {
00305     int ret;
00306     const char *sig_oid;
00307     size_t sig_oid_len = 0;
00308     unsigned char *c, *c2;
00309     unsigned char hash[64];
00310     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
00311     unsigned char tmp_buf[2048];
00312     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
00313     size_t len = 0;
00314     mbedtls_pk_type_t pk_alg;
00315 
00316     /*
00317      * Prepare data to be signed in tmp_buf
00318      */
00319     c = tmp_buf + sizeof( tmp_buf );
00320 
00321     /* Signature algorithm needed in TBS, and later for actual signature */
00322 
00323     /* There's no direct way of extracting a signature algorithm
00324      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
00325     if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
00326         pk_alg = MBEDTLS_PK_RSA;
00327     else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
00328         pk_alg = MBEDTLS_PK_ECDSA;
00329     else
00330         return( MBEDTLS_ERR_X509_INVALID_ALG );
00331 
00332     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
00333                                           &sig_oid, &sig_oid_len ) ) != 0 )
00334     {
00335         return( ret );
00336     }
00337 
00338     /*
00339      *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
00340      */
00341 
00342     /* Only for v3 */
00343     if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
00344     {
00345         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
00346         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00347         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00348                                                            MBEDTLS_ASN1_SEQUENCE ) );
00349         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00350         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
00351                                                            MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
00352     }
00353 
00354     /*
00355      *  SubjectPublicKeyInfo
00356      */
00357     MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key,
00358                                                 tmp_buf, c - tmp_buf ) );
00359     c -= pub_len;
00360     len += pub_len;
00361 
00362     /*
00363      *  Subject  ::=  Name
00364      */
00365     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
00366 
00367     /*
00368      *  Validity ::= SEQUENCE {
00369      *       notBefore      Time,
00370      *       notAfter       Time }
00371      */
00372     sub_len = 0;
00373 
00374     MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
00375                                             MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
00376 
00377     MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
00378                                             MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
00379 
00380     len += sub_len;
00381     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
00382     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00383                                                     MBEDTLS_ASN1_SEQUENCE ) );
00384 
00385     /*
00386      *  Issuer  ::=  Name
00387      */
00388     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) );
00389 
00390     /*
00391      *  Signature   ::=  AlgorithmIdentifier
00392      */
00393     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
00394                        sig_oid, strlen( sig_oid ), 0 ) );
00395 
00396     /*
00397      *  Serial   ::=  INTEGER
00398      */
00399     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
00400 
00401     /*
00402      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
00403      */
00404 
00405     /* Can be omitted for v1 */
00406     if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
00407     {
00408         sub_len = 0;
00409         MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
00410         len += sub_len;
00411         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
00412         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
00413                                                            MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
00414     }
00415 
00416     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
00417     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
00418                                                        MBEDTLS_ASN1_SEQUENCE ) );
00419 
00420     /*
00421      * Make signature
00422      */
00423     if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
00424                             len, hash ) ) != 0 )
00425     {
00426         return( ret );
00427     }
00428 
00429     if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
00430                          f_rng, p_rng ) ) != 0 )
00431     {
00432         return( ret );
00433     }
00434 
00435     /*
00436      * Write data to output buffer
00437      */
00438     c2 = buf + size;
00439     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
00440                                         sig_oid, sig_oid_len, sig, sig_len ) );
00441 
00442     if( len > (size_t)( c2 - buf ) )
00443         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
00444 
00445     c2 -= len;
00446     memcpy( c2, c, len );
00447 
00448     len += sig_and_oid_len;
00449     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
00450     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
00451                                                  MBEDTLS_ASN1_SEQUENCE ) );
00452 
00453     return( (int) len );
00454 }
00455 
00456 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
00457 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
00458 
00459 #if defined(MBEDTLS_PEM_WRITE_C)
00460 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size,
00461                        int (*f_rng)(void *, unsigned char *, size_t),
00462                        void *p_rng )
00463 {
00464     int ret;
00465     unsigned char output_buf[4096];
00466     size_t olen = 0;
00467 
00468     if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
00469                                    f_rng, p_rng ) ) < 0 )
00470     {
00471         return( ret );
00472     }
00473 
00474     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
00475                                   output_buf + sizeof(output_buf) - ret,
00476                                   ret, buf, size, &olen ) ) != 0 )
00477     {
00478         return( ret );
00479     }
00480 
00481     return( 0 );
00482 }
00483 #endif /* MBEDTLS_PEM_WRITE_C */
00484 
00485 #endif /* MBEDTLS_X509_CRT_WRITE_C */