Example program to test AES-GCM functionality. Used for a workshop

Dependencies:   mbed

Committer:
HannesTschofenig
Date:
Thu Sep 27 06:34:22 2018 +0000
Revision:
0:796d0f61a05b
Example AES-GCM test program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
HannesTschofenig 0:796d0f61a05b 1 /*
HannesTschofenig 0:796d0f61a05b 2 * X.509 certificate writing
HannesTschofenig 0:796d0f61a05b 3 *
HannesTschofenig 0:796d0f61a05b 4 * Copyright (C) 2006-2014, Brainspark B.V.
HannesTschofenig 0:796d0f61a05b 5 *
HannesTschofenig 0:796d0f61a05b 6 * This file is part of PolarSSL (http://www.polarssl.org)
HannesTschofenig 0:796d0f61a05b 7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
HannesTschofenig 0:796d0f61a05b 8 *
HannesTschofenig 0:796d0f61a05b 9 * All rights reserved.
HannesTschofenig 0:796d0f61a05b 10 *
HannesTschofenig 0:796d0f61a05b 11 * This program is free software; you can redistribute it and/or modify
HannesTschofenig 0:796d0f61a05b 12 * it under the terms of the GNU General Public License as published by
HannesTschofenig 0:796d0f61a05b 13 * the Free Software Foundation; either version 2 of the License, or
HannesTschofenig 0:796d0f61a05b 14 * (at your option) any later version.
HannesTschofenig 0:796d0f61a05b 15 *
HannesTschofenig 0:796d0f61a05b 16 * This program is distributed in the hope that it will be useful,
HannesTschofenig 0:796d0f61a05b 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
HannesTschofenig 0:796d0f61a05b 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
HannesTschofenig 0:796d0f61a05b 19 * GNU General Public License for more details.
HannesTschofenig 0:796d0f61a05b 20 *
HannesTschofenig 0:796d0f61a05b 21 * You should have received a copy of the GNU General Public License along
HannesTschofenig 0:796d0f61a05b 22 * with this program; if not, write to the Free Software Foundation, Inc.,
HannesTschofenig 0:796d0f61a05b 23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
HannesTschofenig 0:796d0f61a05b 24 */
HannesTschofenig 0:796d0f61a05b 25 /*
HannesTschofenig 0:796d0f61a05b 26 * References:
HannesTschofenig 0:796d0f61a05b 27 * - certificates: RFC 5280, updated by RFC 6818
HannesTschofenig 0:796d0f61a05b 28 * - CSRs: PKCS#10 v1.7 aka RFC 2986
HannesTschofenig 0:796d0f61a05b 29 * - attributes: PKCS#9 v2.0 aka RFC 2985
HannesTschofenig 0:796d0f61a05b 30 */
HannesTschofenig 0:796d0f61a05b 31
HannesTschofenig 0:796d0f61a05b 32 #if !defined(POLARSSL_CONFIG_FILE)
HannesTschofenig 0:796d0f61a05b 33 #include "polarssl/config.h"
HannesTschofenig 0:796d0f61a05b 34 #else
HannesTschofenig 0:796d0f61a05b 35 #include POLARSSL_CONFIG_FILE
HannesTschofenig 0:796d0f61a05b 36 #endif
HannesTschofenig 0:796d0f61a05b 37
HannesTschofenig 0:796d0f61a05b 38 #if defined(POLARSSL_X509_CRT_WRITE_C)
HannesTschofenig 0:796d0f61a05b 39
HannesTschofenig 0:796d0f61a05b 40 #include "polarssl/x509_crt.h"
HannesTschofenig 0:796d0f61a05b 41 #include "polarssl/oid.h"
HannesTschofenig 0:796d0f61a05b 42 #include "polarssl/asn1write.h"
HannesTschofenig 0:796d0f61a05b 43 #include "polarssl/sha1.h"
HannesTschofenig 0:796d0f61a05b 44
HannesTschofenig 0:796d0f61a05b 45 #if defined(POLARSSL_PEM_WRITE_C)
HannesTschofenig 0:796d0f61a05b 46 #include "polarssl/pem.h"
HannesTschofenig 0:796d0f61a05b 47 #endif /* POLARSSL_PEM_WRITE_C */
HannesTschofenig 0:796d0f61a05b 48
HannesTschofenig 0:796d0f61a05b 49 void x509write_crt_init( x509write_cert *ctx )
HannesTschofenig 0:796d0f61a05b 50 {
HannesTschofenig 0:796d0f61a05b 51 memset( ctx, 0, sizeof(x509write_cert) );
HannesTschofenig 0:796d0f61a05b 52
HannesTschofenig 0:796d0f61a05b 53 mpi_init( &ctx->serial );
HannesTschofenig 0:796d0f61a05b 54 ctx->version = X509_CRT_VERSION_3;
HannesTschofenig 0:796d0f61a05b 55 }
HannesTschofenig 0:796d0f61a05b 56
HannesTschofenig 0:796d0f61a05b 57 void x509write_crt_free( x509write_cert *ctx )
HannesTschofenig 0:796d0f61a05b 58 {
HannesTschofenig 0:796d0f61a05b 59 mpi_free( &ctx->serial );
HannesTschofenig 0:796d0f61a05b 60
HannesTschofenig 0:796d0f61a05b 61 asn1_free_named_data_list( &ctx->subject );
HannesTschofenig 0:796d0f61a05b 62 asn1_free_named_data_list( &ctx->issuer );
HannesTschofenig 0:796d0f61a05b 63 asn1_free_named_data_list( &ctx->extensions );
HannesTschofenig 0:796d0f61a05b 64
HannesTschofenig 0:796d0f61a05b 65 memset( ctx, 0, sizeof(x509write_cert) );
HannesTschofenig 0:796d0f61a05b 66 }
HannesTschofenig 0:796d0f61a05b 67
HannesTschofenig 0:796d0f61a05b 68 void x509write_crt_set_version( x509write_cert *ctx, int version )
HannesTschofenig 0:796d0f61a05b 69 {
HannesTschofenig 0:796d0f61a05b 70 ctx->version = version;
HannesTschofenig 0:796d0f61a05b 71 }
HannesTschofenig 0:796d0f61a05b 72
HannesTschofenig 0:796d0f61a05b 73 void x509write_crt_set_md_alg( x509write_cert *ctx, md_type_t md_alg )
HannesTschofenig 0:796d0f61a05b 74 {
HannesTschofenig 0:796d0f61a05b 75 ctx->md_alg = md_alg;
HannesTschofenig 0:796d0f61a05b 76 }
HannesTschofenig 0:796d0f61a05b 77
HannesTschofenig 0:796d0f61a05b 78 void x509write_crt_set_subject_key( x509write_cert *ctx, pk_context *key )
HannesTschofenig 0:796d0f61a05b 79 {
HannesTschofenig 0:796d0f61a05b 80 ctx->subject_key = key;
HannesTschofenig 0:796d0f61a05b 81 }
HannesTschofenig 0:796d0f61a05b 82
HannesTschofenig 0:796d0f61a05b 83 void x509write_crt_set_issuer_key( x509write_cert *ctx, pk_context *key )
HannesTschofenig 0:796d0f61a05b 84 {
HannesTschofenig 0:796d0f61a05b 85 ctx->issuer_key = key;
HannesTschofenig 0:796d0f61a05b 86 }
HannesTschofenig 0:796d0f61a05b 87
HannesTschofenig 0:796d0f61a05b 88 int x509write_crt_set_subject_name( x509write_cert *ctx,
HannesTschofenig 0:796d0f61a05b 89 const char *subject_name )
HannesTschofenig 0:796d0f61a05b 90 {
HannesTschofenig 0:796d0f61a05b 91 return x509_string_to_names( &ctx->subject, subject_name );
HannesTschofenig 0:796d0f61a05b 92 }
HannesTschofenig 0:796d0f61a05b 93
HannesTschofenig 0:796d0f61a05b 94 int x509write_crt_set_issuer_name( x509write_cert *ctx,
HannesTschofenig 0:796d0f61a05b 95 const char *issuer_name )
HannesTschofenig 0:796d0f61a05b 96 {
HannesTschofenig 0:796d0f61a05b 97 return x509_string_to_names( &ctx->issuer, issuer_name );
HannesTschofenig 0:796d0f61a05b 98 }
HannesTschofenig 0:796d0f61a05b 99
HannesTschofenig 0:796d0f61a05b 100 int x509write_crt_set_serial( x509write_cert *ctx, const mpi *serial )
HannesTschofenig 0:796d0f61a05b 101 {
HannesTschofenig 0:796d0f61a05b 102 int ret;
HannesTschofenig 0:796d0f61a05b 103
HannesTschofenig 0:796d0f61a05b 104 if( ( ret = mpi_copy( &ctx->serial, serial ) ) != 0 )
HannesTschofenig 0:796d0f61a05b 105 return( ret );
HannesTschofenig 0:796d0f61a05b 106
HannesTschofenig 0:796d0f61a05b 107 return( 0 );
HannesTschofenig 0:796d0f61a05b 108 }
HannesTschofenig 0:796d0f61a05b 109
HannesTschofenig 0:796d0f61a05b 110 int x509write_crt_set_validity( x509write_cert *ctx, const char *not_before,
HannesTschofenig 0:796d0f61a05b 111 const char *not_after )
HannesTschofenig 0:796d0f61a05b 112 {
HannesTschofenig 0:796d0f61a05b 113 if( strlen(not_before) != X509_RFC5280_UTC_TIME_LEN - 1 ||
HannesTschofenig 0:796d0f61a05b 114 strlen(not_after) != X509_RFC5280_UTC_TIME_LEN - 1 )
HannesTschofenig 0:796d0f61a05b 115 {
HannesTschofenig 0:796d0f61a05b 116 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
HannesTschofenig 0:796d0f61a05b 117 }
HannesTschofenig 0:796d0f61a05b 118 strncpy( ctx->not_before, not_before, X509_RFC5280_UTC_TIME_LEN );
HannesTschofenig 0:796d0f61a05b 119 strncpy( ctx->not_after , not_after , X509_RFC5280_UTC_TIME_LEN );
HannesTschofenig 0:796d0f61a05b 120 ctx->not_before[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
HannesTschofenig 0:796d0f61a05b 121 ctx->not_after[X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
HannesTschofenig 0:796d0f61a05b 122
HannesTschofenig 0:796d0f61a05b 123 return( 0 );
HannesTschofenig 0:796d0f61a05b 124 }
HannesTschofenig 0:796d0f61a05b 125
HannesTschofenig 0:796d0f61a05b 126 int x509write_crt_set_extension( x509write_cert *ctx,
HannesTschofenig 0:796d0f61a05b 127 const char *oid, size_t oid_len,
HannesTschofenig 0:796d0f61a05b 128 int critical,
HannesTschofenig 0:796d0f61a05b 129 const unsigned char *val, size_t val_len )
HannesTschofenig 0:796d0f61a05b 130 {
HannesTschofenig 0:796d0f61a05b 131 return x509_set_extension( &ctx->extensions, oid, oid_len,
HannesTschofenig 0:796d0f61a05b 132 critical, val, val_len );
HannesTschofenig 0:796d0f61a05b 133 }
HannesTschofenig 0:796d0f61a05b 134
HannesTschofenig 0:796d0f61a05b 135 int x509write_crt_set_basic_constraints( x509write_cert *ctx,
HannesTschofenig 0:796d0f61a05b 136 int is_ca, int max_pathlen )
HannesTschofenig 0:796d0f61a05b 137 {
HannesTschofenig 0:796d0f61a05b 138 int ret;
HannesTschofenig 0:796d0f61a05b 139 unsigned char buf[9];
HannesTschofenig 0:796d0f61a05b 140 unsigned char *c = buf + sizeof(buf);
HannesTschofenig 0:796d0f61a05b 141 size_t len = 0;
HannesTschofenig 0:796d0f61a05b 142
HannesTschofenig 0:796d0f61a05b 143 memset( buf, 0, sizeof(buf) );
HannesTschofenig 0:796d0f61a05b 144
HannesTschofenig 0:796d0f61a05b 145 if( is_ca && max_pathlen > 127 )
HannesTschofenig 0:796d0f61a05b 146 return( POLARSSL_ERR_X509_BAD_INPUT_DATA );
HannesTschofenig 0:796d0f61a05b 147
HannesTschofenig 0:796d0f61a05b 148 if( is_ca )
HannesTschofenig 0:796d0f61a05b 149 {
HannesTschofenig 0:796d0f61a05b 150 if( max_pathlen >= 0 )
HannesTschofenig 0:796d0f61a05b 151 {
HannesTschofenig 0:796d0f61a05b 152 ASN1_CHK_ADD( len, asn1_write_int( &c, buf, max_pathlen ) );
HannesTschofenig 0:796d0f61a05b 153 }
HannesTschofenig 0:796d0f61a05b 154 ASN1_CHK_ADD( len, asn1_write_bool( &c, buf, 1 ) );
HannesTschofenig 0:796d0f61a05b 155 }
HannesTschofenig 0:796d0f61a05b 156
HannesTschofenig 0:796d0f61a05b 157 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
HannesTschofenig 0:796d0f61a05b 158 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
HannesTschofenig 0:796d0f61a05b 159 ASN1_SEQUENCE ) );
HannesTschofenig 0:796d0f61a05b 160
HannesTschofenig 0:796d0f61a05b 161 return x509write_crt_set_extension( ctx, OID_BASIC_CONSTRAINTS,
HannesTschofenig 0:796d0f61a05b 162 OID_SIZE( OID_BASIC_CONSTRAINTS ),
HannesTschofenig 0:796d0f61a05b 163 0, buf + sizeof(buf) - len, len );
HannesTschofenig 0:796d0f61a05b 164 }
HannesTschofenig 0:796d0f61a05b 165
HannesTschofenig 0:796d0f61a05b 166 #if defined(POLARSSL_SHA1_C)
HannesTschofenig 0:796d0f61a05b 167 int x509write_crt_set_subject_key_identifier( x509write_cert *ctx )
HannesTschofenig 0:796d0f61a05b 168 {
HannesTschofenig 0:796d0f61a05b 169 int ret;
HannesTschofenig 0:796d0f61a05b 170 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
HannesTschofenig 0:796d0f61a05b 171 unsigned char *c = buf + sizeof(buf);
HannesTschofenig 0:796d0f61a05b 172 size_t len = 0;
HannesTschofenig 0:796d0f61a05b 173
HannesTschofenig 0:796d0f61a05b 174 memset( buf, 0, sizeof(buf));
HannesTschofenig 0:796d0f61a05b 175 ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->subject_key ) );
HannesTschofenig 0:796d0f61a05b 176
HannesTschofenig 0:796d0f61a05b 177 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
HannesTschofenig 0:796d0f61a05b 178 c = buf + sizeof(buf) - 20;
HannesTschofenig 0:796d0f61a05b 179 len = 20;
HannesTschofenig 0:796d0f61a05b 180
HannesTschofenig 0:796d0f61a05b 181 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
HannesTschofenig 0:796d0f61a05b 182 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_OCTET_STRING ) );
HannesTschofenig 0:796d0f61a05b 183
HannesTschofenig 0:796d0f61a05b 184 return x509write_crt_set_extension( ctx, OID_SUBJECT_KEY_IDENTIFIER,
HannesTschofenig 0:796d0f61a05b 185 OID_SIZE( OID_SUBJECT_KEY_IDENTIFIER ),
HannesTschofenig 0:796d0f61a05b 186 0, buf + sizeof(buf) - len, len );
HannesTschofenig 0:796d0f61a05b 187 }
HannesTschofenig 0:796d0f61a05b 188
HannesTschofenig 0:796d0f61a05b 189 int x509write_crt_set_authority_key_identifier( x509write_cert *ctx )
HannesTschofenig 0:796d0f61a05b 190 {
HannesTschofenig 0:796d0f61a05b 191 int ret;
HannesTschofenig 0:796d0f61a05b 192 unsigned char buf[POLARSSL_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
HannesTschofenig 0:796d0f61a05b 193 unsigned char *c = buf + sizeof(buf);
HannesTschofenig 0:796d0f61a05b 194 size_t len = 0;
HannesTschofenig 0:796d0f61a05b 195
HannesTschofenig 0:796d0f61a05b 196 memset( buf, 0, sizeof(buf));
HannesTschofenig 0:796d0f61a05b 197 ASN1_CHK_ADD( len, pk_write_pubkey( &c, buf, ctx->issuer_key ) );
HannesTschofenig 0:796d0f61a05b 198
HannesTschofenig 0:796d0f61a05b 199 sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 );
HannesTschofenig 0:796d0f61a05b 200 c = buf + sizeof(buf) - 20;
HannesTschofenig 0:796d0f61a05b 201 len = 20;
HannesTschofenig 0:796d0f61a05b 202
HannesTschofenig 0:796d0f61a05b 203 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
HannesTschofenig 0:796d0f61a05b 204 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONTEXT_SPECIFIC | 0 ) );
HannesTschofenig 0:796d0f61a05b 205
HannesTschofenig 0:796d0f61a05b 206 ASN1_CHK_ADD( len, asn1_write_len( &c, buf, len ) );
HannesTschofenig 0:796d0f61a05b 207 ASN1_CHK_ADD( len, asn1_write_tag( &c, buf, ASN1_CONSTRUCTED |
HannesTschofenig 0:796d0f61a05b 208 ASN1_SEQUENCE ) );
HannesTschofenig 0:796d0f61a05b 209
HannesTschofenig 0:796d0f61a05b 210 return x509write_crt_set_extension( ctx, OID_AUTHORITY_KEY_IDENTIFIER,
HannesTschofenig 0:796d0f61a05b 211 OID_SIZE( OID_AUTHORITY_KEY_IDENTIFIER ),
HannesTschofenig 0:796d0f61a05b 212 0, buf + sizeof(buf) - len, len );
HannesTschofenig 0:796d0f61a05b 213 }
HannesTschofenig 0:796d0f61a05b 214 #endif /* POLARSSL_SHA1_C */
HannesTschofenig 0:796d0f61a05b 215
HannesTschofenig 0:796d0f61a05b 216 int x509write_crt_set_key_usage( x509write_cert *ctx, unsigned char key_usage )
HannesTschofenig 0:796d0f61a05b 217 {
HannesTschofenig 0:796d0f61a05b 218 unsigned char buf[4];
HannesTschofenig 0:796d0f61a05b 219 unsigned char *c;
HannesTschofenig 0:796d0f61a05b 220 int ret;
HannesTschofenig 0:796d0f61a05b 221
HannesTschofenig 0:796d0f61a05b 222 c = buf + 4;
HannesTschofenig 0:796d0f61a05b 223
HannesTschofenig 0:796d0f61a05b 224 if( ( ret = asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 )
HannesTschofenig 0:796d0f61a05b 225 return( ret );
HannesTschofenig 0:796d0f61a05b 226
HannesTschofenig 0:796d0f61a05b 227 ret = x509write_crt_set_extension( ctx, OID_KEY_USAGE,
HannesTschofenig 0:796d0f61a05b 228 OID_SIZE( OID_KEY_USAGE ),
HannesTschofenig 0:796d0f61a05b 229 1, buf, 4 );
HannesTschofenig 0:796d0f61a05b 230 if( ret != 0 )
HannesTschofenig 0:796d0f61a05b 231 return( ret );
HannesTschofenig 0:796d0f61a05b 232
HannesTschofenig 0:796d0f61a05b 233 return( 0 );
HannesTschofenig 0:796d0f61a05b 234 }
HannesTschofenig 0:796d0f61a05b 235
HannesTschofenig 0:796d0f61a05b 236 int x509write_crt_set_ns_cert_type( x509write_cert *ctx,
HannesTschofenig 0:796d0f61a05b 237 unsigned char ns_cert_type )
HannesTschofenig 0:796d0f61a05b 238 {
HannesTschofenig 0:796d0f61a05b 239 unsigned char buf[4];
HannesTschofenig 0:796d0f61a05b 240 unsigned char *c;
HannesTschofenig 0:796d0f61a05b 241 int ret;
HannesTschofenig 0:796d0f61a05b 242
HannesTschofenig 0:796d0f61a05b 243 c = buf + 4;
HannesTschofenig 0:796d0f61a05b 244
HannesTschofenig 0:796d0f61a05b 245 if( ( ret = asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 )
HannesTschofenig 0:796d0f61a05b 246 return( ret );
HannesTschofenig 0:796d0f61a05b 247
HannesTschofenig 0:796d0f61a05b 248 ret = x509write_crt_set_extension( ctx, OID_NS_CERT_TYPE,
HannesTschofenig 0:796d0f61a05b 249 OID_SIZE( OID_NS_CERT_TYPE ),
HannesTschofenig 0:796d0f61a05b 250 0, buf, 4 );
HannesTschofenig 0:796d0f61a05b 251 if( ret != 0 )
HannesTschofenig 0:796d0f61a05b 252 return( ret );
HannesTschofenig 0:796d0f61a05b 253
HannesTschofenig 0:796d0f61a05b 254 return( 0 );
HannesTschofenig 0:796d0f61a05b 255 }
HannesTschofenig 0:796d0f61a05b 256
HannesTschofenig 0:796d0f61a05b 257 static int x509_write_time( unsigned char **p, unsigned char *start,
HannesTschofenig 0:796d0f61a05b 258 const char *time, size_t size )
HannesTschofenig 0:796d0f61a05b 259 {
HannesTschofenig 0:796d0f61a05b 260 int ret;
HannesTschofenig 0:796d0f61a05b 261 size_t len = 0;
HannesTschofenig 0:796d0f61a05b 262
HannesTschofenig 0:796d0f61a05b 263 /*
HannesTschofenig 0:796d0f61a05b 264 * write ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
HannesTschofenig 0:796d0f61a05b 265 */
HannesTschofenig 0:796d0f61a05b 266 if( time[0] == '2' && time[1] == '0' && time [2] < '5' )
HannesTschofenig 0:796d0f61a05b 267 {
HannesTschofenig 0:796d0f61a05b 268 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
HannesTschofenig 0:796d0f61a05b 269 (const unsigned char *) time + 2,
HannesTschofenig 0:796d0f61a05b 270 size - 2 ) );
HannesTschofenig 0:796d0f61a05b 271 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
HannesTschofenig 0:796d0f61a05b 272 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_UTC_TIME ) );
HannesTschofenig 0:796d0f61a05b 273 }
HannesTschofenig 0:796d0f61a05b 274 else
HannesTschofenig 0:796d0f61a05b 275 {
HannesTschofenig 0:796d0f61a05b 276 ASN1_CHK_ADD( len, asn1_write_raw_buffer( p, start,
HannesTschofenig 0:796d0f61a05b 277 (const unsigned char *) time,
HannesTschofenig 0:796d0f61a05b 278 size ) );
HannesTschofenig 0:796d0f61a05b 279 ASN1_CHK_ADD( len, asn1_write_len( p, start, len ) );
HannesTschofenig 0:796d0f61a05b 280 ASN1_CHK_ADD( len, asn1_write_tag( p, start, ASN1_GENERALIZED_TIME ) );
HannesTschofenig 0:796d0f61a05b 281 }
HannesTschofenig 0:796d0f61a05b 282
HannesTschofenig 0:796d0f61a05b 283 return( (int) len );
HannesTschofenig 0:796d0f61a05b 284 }
HannesTschofenig 0:796d0f61a05b 285
HannesTschofenig 0:796d0f61a05b 286 int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size,
HannesTschofenig 0:796d0f61a05b 287 int (*f_rng)(void *, unsigned char *, size_t),
HannesTschofenig 0:796d0f61a05b 288 void *p_rng )
HannesTschofenig 0:796d0f61a05b 289 {
HannesTschofenig 0:796d0f61a05b 290 int ret;
HannesTschofenig 0:796d0f61a05b 291 const char *sig_oid;
HannesTschofenig 0:796d0f61a05b 292 size_t sig_oid_len = 0;
HannesTschofenig 0:796d0f61a05b 293 unsigned char *c, *c2;
HannesTschofenig 0:796d0f61a05b 294 unsigned char hash[64];
HannesTschofenig 0:796d0f61a05b 295 unsigned char sig[POLARSSL_MPI_MAX_SIZE];
HannesTschofenig 0:796d0f61a05b 296 unsigned char tmp_buf[2048];
HannesTschofenig 0:796d0f61a05b 297 size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
HannesTschofenig 0:796d0f61a05b 298 size_t len = 0;
HannesTschofenig 0:796d0f61a05b 299 pk_type_t pk_alg;
HannesTschofenig 0:796d0f61a05b 300
HannesTschofenig 0:796d0f61a05b 301 /*
HannesTschofenig 0:796d0f61a05b 302 * Prepare data to be signed in tmp_buf
HannesTschofenig 0:796d0f61a05b 303 */
HannesTschofenig 0:796d0f61a05b 304 c = tmp_buf + sizeof( tmp_buf );
HannesTschofenig 0:796d0f61a05b 305
HannesTschofenig 0:796d0f61a05b 306 /* Signature algorithm needed in TBS, and later for actual signature */
HannesTschofenig 0:796d0f61a05b 307 pk_alg = pk_get_type( ctx->issuer_key );
HannesTschofenig 0:796d0f61a05b 308 if( pk_alg == POLARSSL_PK_ECKEY )
HannesTschofenig 0:796d0f61a05b 309 pk_alg = POLARSSL_PK_ECDSA;
HannesTschofenig 0:796d0f61a05b 310
HannesTschofenig 0:796d0f61a05b 311 if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
HannesTschofenig 0:796d0f61a05b 312 &sig_oid, &sig_oid_len ) ) != 0 )
HannesTschofenig 0:796d0f61a05b 313 {
HannesTschofenig 0:796d0f61a05b 314 return( ret );
HannesTschofenig 0:796d0f61a05b 315 }
HannesTschofenig 0:796d0f61a05b 316
HannesTschofenig 0:796d0f61a05b 317 /*
HannesTschofenig 0:796d0f61a05b 318 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
HannesTschofenig 0:796d0f61a05b 319 */
HannesTschofenig 0:796d0f61a05b 320 ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
HannesTschofenig 0:796d0f61a05b 321 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
HannesTschofenig 0:796d0f61a05b 322 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
HannesTschofenig 0:796d0f61a05b 323 ASN1_SEQUENCE ) );
HannesTschofenig 0:796d0f61a05b 324 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
HannesTschofenig 0:796d0f61a05b 325 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC |
HannesTschofenig 0:796d0f61a05b 326 ASN1_CONSTRUCTED | 3 ) );
HannesTschofenig 0:796d0f61a05b 327
HannesTschofenig 0:796d0f61a05b 328 /*
HannesTschofenig 0:796d0f61a05b 329 * SubjectPublicKeyInfo
HannesTschofenig 0:796d0f61a05b 330 */
HannesTschofenig 0:796d0f61a05b 331 ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key,
HannesTschofenig 0:796d0f61a05b 332 tmp_buf, c - tmp_buf ) );
HannesTschofenig 0:796d0f61a05b 333 c -= pub_len;
HannesTschofenig 0:796d0f61a05b 334 len += pub_len;
HannesTschofenig 0:796d0f61a05b 335
HannesTschofenig 0:796d0f61a05b 336 /*
HannesTschofenig 0:796d0f61a05b 337 * Subject ::= Name
HannesTschofenig 0:796d0f61a05b 338 */
HannesTschofenig 0:796d0f61a05b 339 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) );
HannesTschofenig 0:796d0f61a05b 340
HannesTschofenig 0:796d0f61a05b 341 /*
HannesTschofenig 0:796d0f61a05b 342 * Validity ::= SEQUENCE {
HannesTschofenig 0:796d0f61a05b 343 * notBefore Time,
HannesTschofenig 0:796d0f61a05b 344 * notAfter Time }
HannesTschofenig 0:796d0f61a05b 345 */
HannesTschofenig 0:796d0f61a05b 346 sub_len = 0;
HannesTschofenig 0:796d0f61a05b 347
HannesTschofenig 0:796d0f61a05b 348 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
HannesTschofenig 0:796d0f61a05b 349 X509_RFC5280_UTC_TIME_LEN ) );
HannesTschofenig 0:796d0f61a05b 350
HannesTschofenig 0:796d0f61a05b 351 ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
HannesTschofenig 0:796d0f61a05b 352 X509_RFC5280_UTC_TIME_LEN ) );
HannesTschofenig 0:796d0f61a05b 353
HannesTschofenig 0:796d0f61a05b 354 len += sub_len;
HannesTschofenig 0:796d0f61a05b 355 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
HannesTschofenig 0:796d0f61a05b 356 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
HannesTschofenig 0:796d0f61a05b 357 ASN1_SEQUENCE ) );
HannesTschofenig 0:796d0f61a05b 358
HannesTschofenig 0:796d0f61a05b 359 /*
HannesTschofenig 0:796d0f61a05b 360 * Issuer ::= Name
HannesTschofenig 0:796d0f61a05b 361 */
HannesTschofenig 0:796d0f61a05b 362 ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) );
HannesTschofenig 0:796d0f61a05b 363
HannesTschofenig 0:796d0f61a05b 364 /*
HannesTschofenig 0:796d0f61a05b 365 * Signature ::= AlgorithmIdentifier
HannesTschofenig 0:796d0f61a05b 366 */
HannesTschofenig 0:796d0f61a05b 367 ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf,
HannesTschofenig 0:796d0f61a05b 368 sig_oid, strlen( sig_oid ), 0 ) );
HannesTschofenig 0:796d0f61a05b 369
HannesTschofenig 0:796d0f61a05b 370 /*
HannesTschofenig 0:796d0f61a05b 371 * Serial ::= INTEGER
HannesTschofenig 0:796d0f61a05b 372 */
HannesTschofenig 0:796d0f61a05b 373 ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
HannesTschofenig 0:796d0f61a05b 374
HannesTschofenig 0:796d0f61a05b 375 /*
HannesTschofenig 0:796d0f61a05b 376 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
HannesTschofenig 0:796d0f61a05b 377 */
HannesTschofenig 0:796d0f61a05b 378 sub_len = 0;
HannesTschofenig 0:796d0f61a05b 379 ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) );
HannesTschofenig 0:796d0f61a05b 380 len += sub_len;
HannesTschofenig 0:796d0f61a05b 381 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) );
HannesTschofenig 0:796d0f61a05b 382 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC |
HannesTschofenig 0:796d0f61a05b 383 ASN1_CONSTRUCTED | 0 ) );
HannesTschofenig 0:796d0f61a05b 384
HannesTschofenig 0:796d0f61a05b 385 ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) );
HannesTschofenig 0:796d0f61a05b 386 ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED |
HannesTschofenig 0:796d0f61a05b 387 ASN1_SEQUENCE ) );
HannesTschofenig 0:796d0f61a05b 388
HannesTschofenig 0:796d0f61a05b 389 /*
HannesTschofenig 0:796d0f61a05b 390 * Make signature
HannesTschofenig 0:796d0f61a05b 391 */
HannesTschofenig 0:796d0f61a05b 392 md( md_info_from_type( ctx->md_alg ), c, len, hash );
HannesTschofenig 0:796d0f61a05b 393
HannesTschofenig 0:796d0f61a05b 394 if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
HannesTschofenig 0:796d0f61a05b 395 f_rng, p_rng ) ) != 0 )
HannesTschofenig 0:796d0f61a05b 396 {
HannesTschofenig 0:796d0f61a05b 397 return( ret );
HannesTschofenig 0:796d0f61a05b 398 }
HannesTschofenig 0:796d0f61a05b 399
HannesTschofenig 0:796d0f61a05b 400 /*
HannesTschofenig 0:796d0f61a05b 401 * Write data to output buffer
HannesTschofenig 0:796d0f61a05b 402 */
HannesTschofenig 0:796d0f61a05b 403 c2 = buf + size;
HannesTschofenig 0:796d0f61a05b 404 ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf,
HannesTschofenig 0:796d0f61a05b 405 sig_oid, sig_oid_len, sig, sig_len ) );
HannesTschofenig 0:796d0f61a05b 406
HannesTschofenig 0:796d0f61a05b 407 c2 -= len;
HannesTschofenig 0:796d0f61a05b 408 memcpy( c2, c, len );
HannesTschofenig 0:796d0f61a05b 409
HannesTschofenig 0:796d0f61a05b 410 len += sig_and_oid_len;
HannesTschofenig 0:796d0f61a05b 411 ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) );
HannesTschofenig 0:796d0f61a05b 412 ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED |
HannesTschofenig 0:796d0f61a05b 413 ASN1_SEQUENCE ) );
HannesTschofenig 0:796d0f61a05b 414
HannesTschofenig 0:796d0f61a05b 415 return( (int) len );
HannesTschofenig 0:796d0f61a05b 416 }
HannesTschofenig 0:796d0f61a05b 417
HannesTschofenig 0:796d0f61a05b 418 #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
HannesTschofenig 0:796d0f61a05b 419 #define PEM_END_CRT "-----END CERTIFICATE-----\n"
HannesTschofenig 0:796d0f61a05b 420
HannesTschofenig 0:796d0f61a05b 421 #if defined(POLARSSL_PEM_WRITE_C)
HannesTschofenig 0:796d0f61a05b 422 int x509write_crt_pem( x509write_cert *crt, unsigned char *buf, size_t size,
HannesTschofenig 0:796d0f61a05b 423 int (*f_rng)(void *, unsigned char *, size_t),
HannesTschofenig 0:796d0f61a05b 424 void *p_rng )
HannesTschofenig 0:796d0f61a05b 425 {
HannesTschofenig 0:796d0f61a05b 426 int ret;
HannesTschofenig 0:796d0f61a05b 427 unsigned char output_buf[4096];
HannesTschofenig 0:796d0f61a05b 428 size_t olen = 0;
HannesTschofenig 0:796d0f61a05b 429
HannesTschofenig 0:796d0f61a05b 430 if( ( ret = x509write_crt_der( crt, output_buf, sizeof(output_buf),
HannesTschofenig 0:796d0f61a05b 431 f_rng, p_rng ) ) < 0 )
HannesTschofenig 0:796d0f61a05b 432 {
HannesTschofenig 0:796d0f61a05b 433 return( ret );
HannesTschofenig 0:796d0f61a05b 434 }
HannesTschofenig 0:796d0f61a05b 435
HannesTschofenig 0:796d0f61a05b 436 if( ( ret = pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
HannesTschofenig 0:796d0f61a05b 437 output_buf + sizeof(output_buf) - ret,
HannesTschofenig 0:796d0f61a05b 438 ret, buf, size, &olen ) ) != 0 )
HannesTschofenig 0:796d0f61a05b 439 {
HannesTschofenig 0:796d0f61a05b 440 return( ret );
HannesTschofenig 0:796d0f61a05b 441 }
HannesTschofenig 0:796d0f61a05b 442
HannesTschofenig 0:796d0f61a05b 443 return( 0 );
HannesTschofenig 0:796d0f61a05b 444 }
HannesTschofenig 0:796d0f61a05b 445 #endif /* POLARSSL_PEM_WRITE_C */
HannesTschofenig 0:796d0f61a05b 446
HannesTschofenig 0:796d0f61a05b 447 #endif /* POLARSSL_X509_CRT_WRITE_C */
HannesTschofenig 0:796d0f61a05b 448
HannesTschofenig 0:796d0f61a05b 449