ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gen_cert.c Source File

gen_cert.c

00001 /*
00002  * Copyright (c) 2007, Cameron Rich
00003  * 
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without 
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * * Redistributions of source code must retain the above copyright notice, 
00010  *   this list of conditions and the following disclaimer.
00011  * * Redistributions in binary form must reproduce the above copyright notice, 
00012  *   this list of conditions and the following disclaimer in the documentation 
00013  *   and/or other materials provided with the distribution.
00014  * * Neither the name of the axTLS project nor the names of its contributors 
00015  *   may be used to endorse or promote products derived from this software 
00016  *   without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00021  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00025  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00026  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 #include "config.h"
00032 
00033 #ifdef CONFIG_SSL_GENERATE_X509_CERT
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include "os_port.h"
00037 #include "ssl.h"
00038 
00039 /**
00040  * Generate a basic X.509 certificate
00041  */
00042 
00043 static uint8_t set_gen_length(int len, uint8_t *buf, int *offset)
00044 {
00045     if (len < 0x80) /* short form */
00046     {
00047         buf[(*offset)++] = len;
00048         return 1;
00049     }
00050     else /* long form */
00051     {
00052         int i, length_bytes = 0;
00053 
00054         if (len & 0x00FF0000)
00055             length_bytes = 3;
00056         else if (len & 0x0000FF00)
00057             length_bytes = 2;
00058         else if (len & 0x000000FF)
00059             length_bytes = 1;
00060             
00061         buf[(*offset)++] = 0x80 + length_bytes;
00062 
00063         for (i = length_bytes-1; i >= 0; i--)
00064         {
00065             buf[*offset+i] = len & 0xFF;
00066             len >>= 8;
00067         }
00068 
00069         *offset += length_bytes;
00070         return length_bytes+1;
00071     }
00072 }
00073 
00074 static int pre_adjust_with_size(uint8_t type,
00075         int *seq_offset, uint8_t *buf, int *offset)
00076 {
00077     buf[(*offset)++] = type;
00078     *seq_offset = *offset;
00079     *offset += 4;   /* fill in later */
00080     return *offset;
00081 }
00082 
00083 static void adjust_with_size(int seq_size, int seq_start, 
00084                 uint8_t *buf, int *offset)
00085 {
00086     uint8_t seq_byte_size; 
00087     int orig_seq_size = seq_size;
00088     int orig_seq_start = seq_start;
00089 
00090     seq_size = *offset-seq_size;
00091     seq_byte_size = set_gen_length(seq_size, buf, &seq_start);
00092 
00093     if (seq_byte_size != 4)
00094     {
00095         memmove(&buf[orig_seq_start+seq_byte_size], 
00096                 &buf[orig_seq_size], seq_size);
00097         *offset -= 4-seq_byte_size;
00098     }
00099 }
00100 
00101 static void gen_serial_number(uint8_t *buf, int *offset)
00102 {
00103     static const uint8_t ser_oid[] = { ASN1_INTEGER, 1, 0x7F };
00104     memcpy(&buf[*offset], ser_oid , sizeof(ser_oid));
00105     *offset += sizeof(ser_oid);
00106 }
00107 
00108 static void gen_signature_alg(uint8_t *buf, int *offset)
00109 {
00110     /* OBJECT IDENTIFIER sha1withRSAEncryption (1 2 840 113549 1 1 5) */
00111     static const uint8_t sig_oid[] = 
00112     {
00113         ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09, 
00114         0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
00115         ASN1_NULL, 0x00
00116     };
00117 
00118     memcpy(&buf[*offset], sig_oid, sizeof(sig_oid));
00119     *offset += sizeof(sig_oid);
00120 }
00121 
00122 static int gen_dn(const char *name, uint8_t dn_type, 
00123                         uint8_t *buf, int *offset)
00124 {
00125     int ret = X509_OK;
00126     int name_size = strlen(name);
00127 
00128     if (name_size > 0x70)    /* just too big */
00129     {
00130         ret = X509_NOT_OK;
00131         goto error;
00132     }
00133 
00134     buf[(*offset)++] = ASN1_SET;
00135     set_gen_length(9+name_size, buf, offset);
00136     buf[(*offset)++] = ASN1_SEQUENCE;
00137     set_gen_length(7+name_size, buf, offset);
00138     buf[(*offset)++] = ASN1_OID;
00139     buf[(*offset)++] = 3;
00140     buf[(*offset)++] = 0x55;
00141     buf[(*offset)++] = 0x04;
00142     buf[(*offset)++] = dn_type;
00143     buf[(*offset)++] = ASN1_PRINTABLE_STR;
00144     buf[(*offset)++] = name_size;
00145     strcpy(&buf[*offset], name);
00146     *offset += name_size;
00147 
00148 error:
00149     return ret;
00150 }
00151 
00152 static int gen_issuer(const char * dn[], uint8_t *buf, int *offset)
00153 {
00154     int ret = X509_OK;
00155     int seq_offset;
00156     int seq_size = pre_adjust_with_size(
00157                             ASN1_SEQUENCE, &seq_offset, buf, offset);
00158     char fqdn[128]; 
00159 
00160     /* we need the common name, so if not configured, work out the fully
00161      * qualified domain name */
00162     if (dn[X509_COMMON_NAME] == NULL || strlen(dn[X509_COMMON_NAME]) == 0)
00163     {
00164         int fqdn_len;
00165         gethostname(fqdn, sizeof(fqdn));
00166         fqdn_len = strlen(fqdn);
00167         fqdn[fqdn_len++] = '.';
00168         getdomainname(&fqdn[fqdn_len], sizeof(fqdn)-fqdn_len);
00169         fqdn_len = strlen(fqdn);
00170 
00171         if (fqdn[fqdn_len-1] == '.')    /* ensure '.' is not last char */
00172             fqdn[fqdn_len-1] = 0;
00173 
00174         dn[X509_COMMON_NAME] = fqdn;
00175     }
00176 
00177     if ((ret = gen_dn(dn[X509_COMMON_NAME], 3, buf, offset)))
00178         goto error;
00179 
00180     if (dn[X509_ORGANIZATION] != NULL && strlen(dn[X509_ORGANIZATION]) > 0)
00181     {
00182         if ((ret = gen_dn(dn[X509_ORGANIZATION], 10, buf, offset)))
00183             goto error;
00184     }
00185 
00186     if (dn[X509_ORGANIZATIONAL_UNIT] != NULL &&
00187                                 strlen(dn[X509_ORGANIZATIONAL_UNIT]) > 0)
00188     {
00189         if ((ret = gen_dn(dn[X509_ORGANIZATIONAL_UNIT], 11, buf, offset)))
00190             goto error;
00191     }
00192 
00193     adjust_with_size(seq_size, seq_offset, buf, offset);
00194 
00195 error:
00196     return ret;
00197 }
00198 
00199 static void gen_utc_time(uint8_t *buf, int *offset)
00200 {
00201     static const uint8_t time_seq[] = 
00202     {
00203         ASN1_SEQUENCE, 30, 
00204         ASN1_UTC_TIME, 13, 
00205         '0', '7', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z', 
00206         ASN1_UTC_TIME, 13,  /* make it good for 30 or so years */
00207         '3', '8', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z'
00208     };
00209 
00210     /* fixed time */
00211     memcpy(&buf[*offset], time_seq, sizeof(time_seq));
00212     *offset += sizeof(time_seq);
00213 }
00214 
00215 static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
00216 {
00217     static const uint8_t pub_key_seq[] = 
00218     {
00219         ASN1_INTEGER, 0x03, 0x01, 0x00, 0x01 /* INTEGER 65537 */
00220     };
00221 
00222     int seq_offset;
00223     int pub_key_size = rsa_ctx->num_octets;
00224     uint8_t *block = (uint8_t *)alloca(pub_key_size);
00225     int seq_size = pre_adjust_with_size(
00226                             ASN1_SEQUENCE, &seq_offset, buf, offset);
00227     buf[(*offset)++] = ASN1_INTEGER;
00228     bi_export(rsa_ctx->bi_ctx, rsa_ctx->m, block, pub_key_size);
00229 
00230     if (*block & 0x80)  /* make integer positive */
00231     {
00232         set_gen_length(pub_key_size+1, buf, offset);
00233         buf[(*offset)++] = 0;
00234     }
00235     else
00236         set_gen_length(pub_key_size, buf, offset);
00237 
00238     memcpy(&buf[*offset], block, pub_key_size);
00239     *offset += pub_key_size;
00240     memcpy(&buf[*offset], pub_key_seq, sizeof(pub_key_seq));
00241     *offset += sizeof(pub_key_seq);
00242     adjust_with_size(seq_size, seq_offset, buf, offset);
00243 }
00244 
00245 static void gen_pub_key1(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
00246 {
00247     int seq_offset;
00248     int seq_size = pre_adjust_with_size(
00249                             ASN1_BIT_STRING, &seq_offset, buf, offset);
00250     buf[(*offset)++] = 0;   /* bit string is multiple of 8 */
00251     gen_pub_key2(rsa_ctx, buf, offset);
00252     adjust_with_size(seq_size, seq_offset, buf, offset);
00253 }
00254 
00255 static void gen_pub_key(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
00256 {
00257     /*  OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) */
00258     static const uint8_t rsa_enc_oid[] =
00259     {
00260         ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09,
00261         0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
00262         ASN1_NULL, 0x00
00263     };
00264 
00265     int seq_offset;
00266     int seq_size = pre_adjust_with_size(
00267                             ASN1_SEQUENCE, &seq_offset, buf, offset);
00268 
00269     memcpy(&buf[*offset], rsa_enc_oid, sizeof(rsa_enc_oid));
00270     *offset += sizeof(rsa_enc_oid);
00271     gen_pub_key1(rsa_ctx, buf, offset);
00272     adjust_with_size(seq_size, seq_offset, buf, offset);
00273 }
00274 
00275 static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, 
00276                         uint8_t *buf, int *offset)
00277 {
00278     static const uint8_t asn1_sig[] = 
00279     {
00280         ASN1_SEQUENCE,  0x21, ASN1_SEQUENCE, 0x09, ASN1_OID, 0x05, 
00281         0x2b, 0x0e, 0x03, 0x02, 0x1a, /* sha1 (1 3 14 3 2 26) */
00282         ASN1_NULL, 0x00, ASN1_OCTET_STRING, 0x14 
00283     };
00284 
00285     uint8_t *enc_block = (uint8_t *)alloca(rsa_ctx->num_octets);
00286     uint8_t *block = (uint8_t *)alloca(sizeof(asn1_sig) + SHA1_SIZE);
00287     int sig_size;
00288 
00289     /* add the digest as an embedded asn.1 sequence */
00290     memcpy(block, asn1_sig, sizeof(asn1_sig));
00291     memcpy(&block[sizeof(asn1_sig)], sha_dgst, SHA1_SIZE);
00292 
00293     sig_size = RSA_encrypt(rsa_ctx, block, 
00294                             sizeof(asn1_sig) + SHA1_SIZE, enc_block, 1);
00295 
00296     buf[(*offset)++] = ASN1_BIT_STRING;
00297     set_gen_length(sig_size+1, buf, offset);
00298     buf[(*offset)++] = 0;   /* bit string is multiple of 8 */
00299     memcpy(&buf[*offset], enc_block, sig_size);
00300     *offset += sig_size;
00301 }
00302 
00303 static int gen_tbs_cert(const char * dn[],
00304                     const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset,
00305                     uint8_t *sha_dgst)
00306 {
00307     int ret = X509_OK;
00308     SHA1_CTX sha_ctx;
00309     int seq_offset;
00310     int begin_tbs = *offset;
00311     int seq_size = pre_adjust_with_size(
00312                         ASN1_SEQUENCE, &seq_offset, buf, offset);
00313 
00314     gen_serial_number(buf, offset);
00315     gen_signature_alg(buf, offset);
00316 
00317     /* CA certicate issuer */
00318     if ((ret = gen_issuer(dn, buf, offset)))
00319         goto error;
00320 
00321     gen_utc_time(buf, offset);
00322 
00323     /* certificate issuer */
00324     if ((ret = gen_issuer(dn, buf, offset)))
00325         goto error;
00326 
00327     gen_pub_key(rsa_ctx, buf, offset);
00328     adjust_with_size(seq_size, seq_offset, buf, offset);
00329 
00330     SHA1_Init(&sha_ctx);
00331     SHA1_Update(&sha_ctx, &buf[begin_tbs], *offset-begin_tbs);
00332     SHA1_Final(sha_dgst, &sha_ctx);
00333 
00334 error:
00335     return ret;
00336 }
00337 
00338 /**
00339  * Create a new certificate.
00340  */
00341 EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data)
00342 {
00343     int ret = X509_OK, offset = 0, seq_offset;
00344     /* allocate enough space to load a new certificate */
00345     uint8_t *buf = (uint8_t *)alloca(ssl_ctx->rsa_ctx->num_octets*2 + 512);
00346     uint8_t sha_dgst[SHA1_SIZE];
00347     int seq_size = pre_adjust_with_size(ASN1_SEQUENCE, 
00348                                     &seq_offset, buf, &offset);
00349 
00350     if ((ret = gen_tbs_cert(dn, ssl_ctx->rsa_ctx, buf, &offset, sha_dgst)) < 0)
00351         goto error;
00352 
00353     gen_signature_alg(buf, &offset);
00354     gen_signature(ssl_ctx->rsa_ctx, sha_dgst, buf, &offset);
00355     adjust_with_size(seq_size, seq_offset, buf, &offset);
00356     *cert_data = (uint8_t *)malloc(offset); /* create the exact memory for it */
00357     memcpy(*cert_data, buf, offset);
00358 
00359 error:
00360     return ret < 0 ? ret : offset;
00361 }
00362 
00363 #endif
00364