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>