takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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