Annotation of embedaddon/axTLS/ssl/gen_cert.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2007, Cameron Rich
                      3:  * 
                      4:  * All rights reserved.
                      5:  * 
                      6:  * Redistribution and use in source and binary forms, with or without 
                      7:  * modification, are permitted provided that the following conditions are met:
                      8:  *
                      9:  * * Redistributions of source code must retain the above copyright notice, 
                     10:  *   this list of conditions and the following disclaimer.
                     11:  * * Redistributions in binary form must reproduce the above copyright notice, 
                     12:  *   this list of conditions and the following disclaimer in the documentation 
                     13:  *   and/or other materials provided with the distribution.
                     14:  * * Neither the name of the axTLS project nor the names of its contributors 
                     15:  *   may be used to endorse or promote products derived from this software 
                     16:  *   without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
                     19:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
                     21:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
                     22:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     23:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     24:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                     25:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
                     26:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     27:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     28:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30: 
                     31: #include "config.h"
                     32: 
                     33: #ifdef CONFIG_SSL_GENERATE_X509_CERT
                     34: #include <string.h>
                     35: #include <stdlib.h>
                     36: #include "os_port.h"
                     37: #include "ssl.h"
                     38: 
                     39: /**
                     40:  * Generate a basic X.509 certificate
                     41:  */
                     42: 
                     43: static uint8_t set_gen_length(int len, uint8_t *buf, int *offset)
                     44: {
                     45:     if (len < 0x80) /* short form */
                     46:     {
                     47:         buf[(*offset)++] = len;
                     48:         return 1;
                     49:     }
                     50:     else /* long form */
                     51:     {
                     52:         int i, length_bytes = 0;
                     53: 
                     54:         if (len & 0x00FF0000)
                     55:             length_bytes = 3;
                     56:         else if (len & 0x0000FF00)
                     57:             length_bytes = 2;
                     58:         else if (len & 0x000000FF)
                     59:             length_bytes = 1;
                     60:             
                     61:         buf[(*offset)++] = 0x80 + length_bytes;
                     62: 
                     63:         for (i = length_bytes-1; i >= 0; i--)
                     64:         {
                     65:             buf[*offset+i] = len & 0xFF;
                     66:             len >>= 8;
                     67:         }
                     68: 
                     69:         *offset += length_bytes;
                     70:         return length_bytes+1;
                     71:     }
                     72: }
                     73: 
                     74: static int pre_adjust_with_size(uint8_t type,
                     75:         int *seq_offset, uint8_t *buf, int *offset)
                     76: {
                     77:     buf[(*offset)++] = type;
                     78:     *seq_offset = *offset;
                     79:     *offset += 4;   /* fill in later */
                     80:     return *offset;
                     81: }
                     82: 
                     83: static void adjust_with_size(int seq_size, int seq_start, 
                     84:                 uint8_t *buf, int *offset)
                     85: {
                     86:     uint8_t seq_byte_size; 
                     87:     int orig_seq_size = seq_size;
                     88:     int orig_seq_start = seq_start;
                     89: 
                     90:     seq_size = *offset-seq_size;
                     91:     seq_byte_size = set_gen_length(seq_size, buf, &seq_start);
                     92: 
                     93:     if (seq_byte_size != 4)
                     94:     {
                     95:         memmove(&buf[orig_seq_start+seq_byte_size], 
                     96:                 &buf[orig_seq_size], seq_size);
                     97:         *offset -= 4-seq_byte_size;
                     98:     }
                     99: }
                    100: 
                    101: static void gen_serial_number(uint8_t *buf, int *offset)
                    102: {
                    103:     static const uint8_t ser_oid[] = { ASN1_INTEGER, 1, 0x7F };
                    104:     memcpy(&buf[*offset], ser_oid , sizeof(ser_oid));
                    105:     *offset += sizeof(ser_oid);
                    106: }
                    107: 
                    108: static void gen_signature_alg(uint8_t *buf, int *offset)
                    109: {
                    110:     /* OBJECT IDENTIFIER sha1withRSAEncryption (1 2 840 113549 1 1 5) */
                    111:     static const uint8_t sig_oid[] = 
                    112:     {
                    113:         ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09, 
                    114:         0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
                    115:         ASN1_NULL, 0x00
                    116:     };
                    117: 
                    118:     memcpy(&buf[*offset], sig_oid, sizeof(sig_oid));
                    119:     *offset += sizeof(sig_oid);
                    120: }
                    121: 
                    122: static int gen_dn(const char *name, uint8_t dn_type, 
                    123:                         uint8_t *buf, int *offset)
                    124: {
                    125:     int ret = X509_OK;
                    126:     int name_size = strlen(name);
                    127: 
                    128:     if (name_size > 0x70)    /* just too big */
                    129:     {
                    130:         ret = X509_NOT_OK;
                    131:         goto error;
                    132:     }
                    133: 
                    134:     buf[(*offset)++] = ASN1_SET;
                    135:     set_gen_length(9+name_size, buf, offset);
                    136:     buf[(*offset)++] = ASN1_SEQUENCE;
                    137:     set_gen_length(7+name_size, buf, offset);
                    138:     buf[(*offset)++] = ASN1_OID;
                    139:     buf[(*offset)++] = 3;
                    140:     buf[(*offset)++] = 0x55;
                    141:     buf[(*offset)++] = 0x04;
                    142:     buf[(*offset)++] = dn_type;
                    143:     buf[(*offset)++] = ASN1_PRINTABLE_STR;
                    144:     buf[(*offset)++] = name_size;
                    145:     strcpy(&buf[*offset], name);
                    146:     *offset += name_size;
                    147: 
                    148: error:
                    149:     return ret;
                    150: }
                    151: 
                    152: static int gen_issuer(const char * dn[], uint8_t *buf, int *offset)
                    153: {
                    154:     int ret = X509_OK;
                    155:     int seq_offset;
                    156:     int seq_size = pre_adjust_with_size(
                    157:                             ASN1_SEQUENCE, &seq_offset, buf, offset);
                    158:     char fqdn[128]; 
                    159: 
                    160:     /* we need the common name, so if not configured, work out the fully
                    161:      * qualified domain name */
                    162:     if (dn[X509_COMMON_NAME] == NULL || strlen(dn[X509_COMMON_NAME]) == 0)
                    163:     {
                    164:         int fqdn_len;
                    165:         gethostname(fqdn, sizeof(fqdn));
                    166:         fqdn_len = strlen(fqdn);
                    167:         fqdn[fqdn_len++] = '.';
                    168:         getdomainname(&fqdn[fqdn_len], sizeof(fqdn)-fqdn_len);
                    169:         fqdn_len = strlen(fqdn);
                    170: 
                    171:         if (fqdn[fqdn_len-1] == '.')    /* ensure '.' is not last char */
                    172:             fqdn[fqdn_len-1] = 0;
                    173: 
                    174:         dn[X509_COMMON_NAME] = fqdn;
                    175:     }
                    176: 
                    177:     if ((ret = gen_dn(dn[X509_COMMON_NAME], 3, buf, offset)))
                    178:         goto error;
                    179: 
                    180:     if (dn[X509_ORGANIZATION] != NULL && strlen(dn[X509_ORGANIZATION]) > 0)
                    181:     {
                    182:         if ((ret = gen_dn(dn[X509_ORGANIZATION], 10, buf, offset)))
                    183:             goto error;
                    184:     }
                    185: 
                    186:     if (dn[X509_ORGANIZATIONAL_UNIT] != NULL &&
                    187:                                 strlen(dn[X509_ORGANIZATIONAL_UNIT]) > 0)
                    188:     {
                    189:         if ((ret = gen_dn(dn[X509_ORGANIZATIONAL_UNIT], 11, buf, offset)))
                    190:             goto error;
                    191:     }
                    192: 
                    193:     adjust_with_size(seq_size, seq_offset, buf, offset);
                    194: 
                    195: error:
                    196:     return ret;
                    197: }
                    198: 
                    199: static void gen_utc_time(uint8_t *buf, int *offset)
                    200: {
                    201:     static const uint8_t time_seq[] = 
                    202:     {
                    203:         ASN1_SEQUENCE, 30, 
                    204:         ASN1_UTC_TIME, 13, 
                    205:         '0', '7', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z', 
                    206:         ASN1_UTC_TIME, 13,  /* make it good for 30 or so years */
                    207:         '3', '8', '0', '1', '0', '1', '0', '0', '0', '0', '0', '0', 'Z'
                    208:     };
                    209: 
                    210:     /* fixed time */
                    211:     memcpy(&buf[*offset], time_seq, sizeof(time_seq));
                    212:     *offset += sizeof(time_seq);
                    213: }
                    214: 
                    215: static void gen_pub_key2(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
                    216: {
                    217:     static const uint8_t pub_key_seq[] = 
                    218:     {
                    219:         ASN1_INTEGER, 0x03, 0x01, 0x00, 0x01 /* INTEGER 65537 */
                    220:     };
                    221: 
                    222:     int seq_offset;
                    223:     int pub_key_size = rsa_ctx->num_octets;
                    224:     uint8_t *block = (uint8_t *)alloca(pub_key_size);
                    225:     int seq_size = pre_adjust_with_size(
                    226:                             ASN1_SEQUENCE, &seq_offset, buf, offset);
                    227:     buf[(*offset)++] = ASN1_INTEGER;
                    228:     bi_export(rsa_ctx->bi_ctx, rsa_ctx->m, block, pub_key_size);
                    229: 
                    230:     if (*block & 0x80)  /* make integer positive */
                    231:     {
                    232:         set_gen_length(pub_key_size+1, buf, offset);
                    233:         buf[(*offset)++] = 0;
                    234:     }
                    235:     else
                    236:         set_gen_length(pub_key_size, buf, offset);
                    237: 
                    238:     memcpy(&buf[*offset], block, pub_key_size);
                    239:     *offset += pub_key_size;
                    240:     memcpy(&buf[*offset], pub_key_seq, sizeof(pub_key_seq));
                    241:     *offset += sizeof(pub_key_seq);
                    242:     adjust_with_size(seq_size, seq_offset, buf, offset);
                    243: }
                    244: 
                    245: static void gen_pub_key1(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
                    246: {
                    247:     int seq_offset;
                    248:     int seq_size = pre_adjust_with_size(
                    249:                             ASN1_BIT_STRING, &seq_offset, buf, offset);
                    250:     buf[(*offset)++] = 0;   /* bit string is multiple of 8 */
                    251:     gen_pub_key2(rsa_ctx, buf, offset);
                    252:     adjust_with_size(seq_size, seq_offset, buf, offset);
                    253: }
                    254: 
                    255: static void gen_pub_key(const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset)
                    256: {
                    257:     /*  OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1) */
                    258:     static const uint8_t rsa_enc_oid[] =
                    259:     {
                    260:         ASN1_SEQUENCE, 0x0d, ASN1_OID, 0x09,
                    261:         0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
                    262:         ASN1_NULL, 0x00
                    263:     };
                    264: 
                    265:     int seq_offset;
                    266:     int seq_size = pre_adjust_with_size(
                    267:                             ASN1_SEQUENCE, &seq_offset, buf, offset);
                    268: 
                    269:     memcpy(&buf[*offset], rsa_enc_oid, sizeof(rsa_enc_oid));
                    270:     *offset += sizeof(rsa_enc_oid);
                    271:     gen_pub_key1(rsa_ctx, buf, offset);
                    272:     adjust_with_size(seq_size, seq_offset, buf, offset);
                    273: }
                    274: 
                    275: static void gen_signature(const RSA_CTX *rsa_ctx, const uint8_t *sha_dgst, 
                    276:                         uint8_t *buf, int *offset)
                    277: {
                    278:     static const uint8_t asn1_sig[] = 
                    279:     {
                    280:         ASN1_SEQUENCE,  0x21, ASN1_SEQUENCE, 0x09, ASN1_OID, 0x05, 
                    281:         0x2b, 0x0e, 0x03, 0x02, 0x1a, /* sha1 (1 3 14 3 2 26) */
                    282:         ASN1_NULL, 0x00, ASN1_OCTET_STRING, 0x14 
                    283:     };
                    284: 
                    285:     uint8_t *enc_block = (uint8_t *)alloca(rsa_ctx->num_octets);
                    286:     uint8_t *block = (uint8_t *)alloca(sizeof(asn1_sig) + SHA1_SIZE);
                    287:     int sig_size;
                    288: 
                    289:     /* add the digest as an embedded asn.1 sequence */
                    290:     memcpy(block, asn1_sig, sizeof(asn1_sig));
                    291:     memcpy(&block[sizeof(asn1_sig)], sha_dgst, SHA1_SIZE);
                    292: 
                    293:     sig_size = RSA_encrypt(rsa_ctx, block, 
                    294:                             sizeof(asn1_sig) + SHA1_SIZE, enc_block, 1);
                    295: 
                    296:     buf[(*offset)++] = ASN1_BIT_STRING;
                    297:     set_gen_length(sig_size+1, buf, offset);
                    298:     buf[(*offset)++] = 0;   /* bit string is multiple of 8 */
                    299:     memcpy(&buf[*offset], enc_block, sig_size);
                    300:     *offset += sig_size;
                    301: }
                    302: 
                    303: static int gen_tbs_cert(const char * dn[],
                    304:                     const RSA_CTX *rsa_ctx, uint8_t *buf, int *offset,
                    305:                     uint8_t *sha_dgst)
                    306: {
                    307:     int ret = X509_OK;
                    308:     SHA1_CTX sha_ctx;
                    309:     int seq_offset;
                    310:     int begin_tbs = *offset;
                    311:     int seq_size = pre_adjust_with_size(
                    312:                         ASN1_SEQUENCE, &seq_offset, buf, offset);
                    313: 
                    314:     gen_serial_number(buf, offset);
                    315:     gen_signature_alg(buf, offset);
                    316: 
                    317:     /* CA certicate issuer */
                    318:     if ((ret = gen_issuer(dn, buf, offset)))
                    319:         goto error;
                    320: 
                    321:     gen_utc_time(buf, offset);
                    322: 
                    323:     /* certificate issuer */
                    324:     if ((ret = gen_issuer(dn, buf, offset)))
                    325:         goto error;
                    326: 
                    327:     gen_pub_key(rsa_ctx, buf, offset);
                    328:     adjust_with_size(seq_size, seq_offset, buf, offset);
                    329: 
                    330:     SHA1_Init(&sha_ctx);
                    331:     SHA1_Update(&sha_ctx, &buf[begin_tbs], *offset-begin_tbs);
                    332:     SHA1_Final(sha_dgst, &sha_ctx);
                    333: 
                    334: error:
                    335:     return ret;
                    336: }
                    337: 
                    338: /**
                    339:  * Create a new certificate.
                    340:  */
                    341: EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data)
                    342: {
                    343:     int ret = X509_OK, offset = 0, seq_offset;
                    344:     /* allocate enough space to load a new certificate */
                    345:     uint8_t *buf = (uint8_t *)alloca(ssl_ctx->rsa_ctx->num_octets*2 + 512);
                    346:     uint8_t sha_dgst[SHA1_SIZE];
                    347:     int seq_size = pre_adjust_with_size(ASN1_SEQUENCE, 
                    348:                                     &seq_offset, buf, &offset);
                    349: 
                    350:     if ((ret = gen_tbs_cert(dn, ssl_ctx->rsa_ctx, buf, &offset, sha_dgst)) < 0)
                    351:         goto error;
                    352: 
                    353:     gen_signature_alg(buf, &offset);
                    354:     gen_signature(ssl_ctx->rsa_ctx, sha_dgst, buf, &offset);
                    355:     adjust_with_size(seq_size, seq_offset, buf, &offset);
                    356:     *cert_data = (uint8_t *)malloc(offset); /* create the exact memory for it */
                    357:     memcpy(*cert_data, buf, offset);
                    358: 
                    359: error:
                    360:     return ret < 0 ? ret : offset;
                    361: }
                    362: 
                    363: #endif
                    364: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>