Annotation of embedaddon/axTLS/ssl/asn1.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: /**
32: * Some primitive asn methods for extraction ASN.1 data.
33: */
34:
35: #include <stdio.h>
36: #include <stdlib.h>
37: #include <string.h>
38: #include <time.h>
39: #include "os_port.h"
40: #include "crypto.h"
41: #include "crypto_misc.h"
42:
43: #define SIG_OID_PREFIX_SIZE 8
44: #define SIG_IIS6_OID_SIZE 5
45: #define SIG_SUBJECT_ALT_NAME_SIZE 3
46:
47: /* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
48: static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] =
49: {
50: 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
51: };
52:
53: static const uint8_t sig_sha1WithRSAEncrypt[SIG_IIS6_OID_SIZE] =
54: {
55: 0x2b, 0x0e, 0x03, 0x02, 0x1d
56: };
57:
58: static const uint8_t sig_subject_alt_name[SIG_SUBJECT_ALT_NAME_SIZE] =
59: {
60: 0x55, 0x1d, 0x11
61: };
62:
63: /* CN, O, OU */
64: static const uint8_t g_dn_types[] = { 3, 10, 11 };
65:
66: int get_asn1_length(const uint8_t *buf, int *offset)
67: {
68: int len, i;
69:
70: if (!(buf[*offset] & 0x80)) /* short form */
71: {
72: len = buf[(*offset)++];
73: }
74: else /* long form */
75: {
76: int length_bytes = buf[(*offset)++]&0x7f;
77: len = 0;
78: for (i = 0; i < length_bytes; i++)
79: {
80: len <<= 8;
81: len += buf[(*offset)++];
82: }
83: }
84:
85: return len;
86: }
87:
88: /**
89: * Skip the ASN1.1 object type and its length. Get ready to read the object's
90: * data.
91: */
92: int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
93: {
94: if (buf[*offset] != obj_type)
95: return X509_NOT_OK;
96: (*offset)++;
97: return get_asn1_length(buf, offset);
98: }
99:
100: /**
101: * Skip over an ASN.1 object type completely. Get ready to read the next
102: * object.
103: */
104: int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
105: {
106: int len;
107:
108: if (buf[*offset] != obj_type)
109: return X509_NOT_OK;
110: (*offset)++;
111: len = get_asn1_length(buf, offset);
112: *offset += len;
113: return 0;
114: }
115:
116: /**
117: * Read an integer value for ASN.1 data
118: * Note: This function allocates memory which must be freed by the user.
119: */
120: int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
121: {
122: int len;
123:
124: if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
125: goto end_int_array;
126:
127: if (len > 1 && buf[*offset] == 0x00) /* ignore the negative byte */
128: {
129: len--;
130: (*offset)++;
131: }
132:
133: *object = (uint8_t *)malloc(len);
134: memcpy(*object, &buf[*offset], len);
135: *offset += len;
136:
137: end_int_array:
138: return len;
139: }
140:
141: /**
142: * Get all the RSA private key specifics from an ASN.1 encoded file
143: */
144: int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
145: {
146: int offset = 7;
147: uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL;
148: int mod_len, priv_len, pub_len;
149: #ifdef CONFIG_BIGINT_CRT
150: uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL;
151: int p_len, q_len, dP_len, dQ_len, qInv_len;
152: #endif
153:
154: /* not in der format */
155: if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
156: {
157: #ifdef CONFIG_SSL_FULL_MODE
158: printf("Error: This is not a valid ASN.1 file\n");
159: #endif
160: return X509_INVALID_PRIV_KEY;
161: }
162:
163: /* Use the private key to mix up the RNG if possible. */
164: RNG_custom_init(buf, len);
165:
166: mod_len = asn1_get_int(buf, &offset, &modulus);
167: pub_len = asn1_get_int(buf, &offset, &pub_exp);
168: priv_len = asn1_get_int(buf, &offset, &priv_exp);
169:
170: if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
171: return X509_INVALID_PRIV_KEY;
172:
173: #ifdef CONFIG_BIGINT_CRT
174: p_len = asn1_get_int(buf, &offset, &p);
175: q_len = asn1_get_int(buf, &offset, &q);
176: dP_len = asn1_get_int(buf, &offset, &dP);
177: dQ_len = asn1_get_int(buf, &offset, &dQ);
178: qInv_len = asn1_get_int(buf, &offset, &qInv);
179:
180: if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
181: return X509_INVALID_PRIV_KEY;
182:
183: RSA_priv_key_new(rsa_ctx,
184: modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
185: p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
186:
187: free(p);
188: free(q);
189: free(dP);
190: free(dQ);
191: free(qInv);
192: #else
193: RSA_priv_key_new(rsa_ctx,
194: modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
195: #endif
196:
197: free(modulus);
198: free(priv_exp);
199: free(pub_exp);
200: return X509_OK;
201: }
202:
203: /**
204: * Get the time of a certificate. Ignore hours/minutes/seconds.
205: */
206: static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
207: {
208: int ret = X509_NOT_OK, len, t_offset;
209: struct tm tm;
210:
211: if (buf[(*offset)++] != ASN1_UTC_TIME)
212: goto end_utc_time;
213:
214: len = get_asn1_length(buf, offset);
215: t_offset = *offset;
216:
217: memset(&tm, 0, sizeof(struct tm));
218: tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
219:
220: if (tm.tm_year <= 50) /* 1951-2050 thing */
221: {
222: tm.tm_year += 100;
223: }
224:
225: tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
226: tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
227: *t = mktime(&tm);
228: *offset += len;
229: ret = X509_OK;
230:
231: end_utc_time:
232: return ret;
233: }
234:
235: /**
236: * Get the version type of a certificate (which we don't actually care about)
237: */
238: int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
239: {
240: int ret = X509_NOT_OK;
241:
242: (*offset) += 2; /* get past explicit tag */
243: if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
244: goto end_version;
245:
246: ret = X509_OK;
247: end_version:
248: return ret;
249: }
250:
251: /**
252: * Retrieve the notbefore and notafter certificate times.
253: */
254: int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
255: {
256: return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
257: asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
258: asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
259: }
260:
261: /**
262: * Get the components of a distinguished name
263: */
264: static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
265: {
266: int dn_type = 0;
267: int len;
268:
269: if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
270: goto end_oid;
271:
272: /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
273: components we are interested in. */
274: if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
275: dn_type = buf[(*offset)++];
276: else
277: {
278: *offset += len; /* skip over it */
279: }
280:
281: end_oid:
282: return dn_type;
283: }
284:
285: /**
286: * Obtain an ASN.1 printable string type.
287: */
288: static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
289: {
290: int len = X509_NOT_OK;
291: int asn1_type = buf[*offset];
292:
293: /* some certs have this awful crud in them for some reason */
294: if (asn1_type != ASN1_PRINTABLE_STR &&
295: asn1_type != ASN1_PRINTABLE_STR2 &&
296: asn1_type != ASN1_TELETEX_STR &&
297: asn1_type != ASN1_IA5_STR &&
298: asn1_type != ASN1_UNICODE_STR)
299: goto end_pnt_str;
300:
301: (*offset)++;
302: len = get_asn1_length(buf, offset);
303:
304: if (asn1_type == ASN1_UNICODE_STR)
305: {
306: int i;
307: *str = (char *)malloc(len/2+1); /* allow for null */
308:
309: for (i = 0; i < len; i += 2)
310: (*str)[i/2] = buf[*offset + i + 1];
311:
312: (*str)[len/2] = 0; /* null terminate */
313: }
314: else
315: {
316: *str = (char *)malloc(len+1); /* allow for null */
317: memcpy(*str, &buf[*offset], len);
318: (*str)[len] = 0; /* null terminate */
319: }
320:
321: *offset += len;
322:
323: end_pnt_str:
324: return len;
325: }
326:
327: /**
328: * Get the subject name (or the issuer) of a certificate.
329: */
330: int asn1_name(const uint8_t *cert, int *offset, char *dn[])
331: {
332: int ret = X509_NOT_OK;
333: int dn_type;
334: char *tmp;
335:
336: if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
337: goto end_name;
338:
339: while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
340: {
341: int i, found = 0;
342:
343: if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
344: (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
345: goto end_name;
346:
347: tmp = NULL;
348:
349: if (asn1_get_printable_str(cert, offset, &tmp) < 0)
350: {
351: free(tmp);
352: goto end_name;
353: }
354:
355: /* find the distinguished named type */
356: for (i = 0; i < X509_NUM_DN_TYPES; i++)
357: {
358: if (dn_type == g_dn_types[i])
359: {
360: if (dn[i] == NULL)
361: {
362: dn[i] = tmp;
363: found = 1;
364: break;
365: }
366: }
367: }
368:
369: if (found == 0) /* not found so get rid of it */
370: {
371: free(tmp);
372: }
373: }
374:
375: ret = X509_OK;
376: end_name:
377: return ret;
378: }
379:
380: /**
381: * Read the modulus and public exponent of a certificate.
382: */
383: int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
384: {
385: int ret = X509_NOT_OK, mod_len, pub_len;
386: uint8_t *modulus = NULL, *pub_exp = NULL;
387:
388: if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
389: asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
390: asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
391: goto end_pub_key;
392:
393: (*offset)++; /* ignore the padding bit field */
394:
395: if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
396: goto end_pub_key;
397:
398: mod_len = asn1_get_int(cert, offset, &modulus);
399: pub_len = asn1_get_int(cert, offset, &pub_exp);
400:
401: RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
402:
403: free(modulus);
404: free(pub_exp);
405: ret = X509_OK;
406:
407: end_pub_key:
408: return ret;
409: }
410:
411: #ifdef CONFIG_SSL_CERT_VERIFICATION
412: /**
413: * Read the signature of the certificate.
414: */
415: int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
416: {
417: int ret = X509_NOT_OK;
418:
419: if (cert[(*offset)++] != ASN1_BIT_STRING)
420: goto end_sig;
421:
422: x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
423: (*offset)++; /* ignore bit string padding bits */
424: x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
425: memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
426: *offset += x509_ctx->sig_len;
427: ret = X509_OK;
428:
429: end_sig:
430: return ret;
431: }
432:
433: /*
434: * Compare 2 distinguished name components for equality
435: * @return 0 if a match
436: */
437: static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
438: {
439: int ret;
440:
441: if (dn1 == NULL && dn2 == NULL)
442: ret = 0;
443: else
444: ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 1;
445:
446: return ret;
447: }
448:
449: /**
450: * Clean up all of the CA certificates.
451: */
452: void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
453: {
454: int i = 0;
455:
456: if (ca_cert_ctx == NULL)
457: return;
458:
459: while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
460: {
461: x509_free(ca_cert_ctx->cert[i]);
462: ca_cert_ctx->cert[i++] = NULL;
463: }
464:
465: free(ca_cert_ctx);
466: }
467:
468: /*
469: * Compare 2 distinguished names for equality
470: * @return 0 if a match
471: */
472: int asn1_compare_dn(char * const dn1[], char * const dn2[])
473: {
474: int i;
475:
476: for (i = 0; i < X509_NUM_DN_TYPES; i++)
477: {
478: if (asn1_compare_dn_comp(dn1[i], dn2[i]))
479: return 1;
480: }
481:
482: return 0; /* all good */
483: }
484:
485: int asn1_find_oid(const uint8_t* cert, int* offset,
486: const uint8_t* oid, int oid_length)
487: {
488: int seqlen;
489: if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
490: {
491: int end = *offset + seqlen;
492:
493: while (*offset < end)
494: {
495: int type = cert[(*offset)++];
496: int length = get_asn1_length(cert, offset);
497: int noffset = *offset + length;
498:
499: if (type == ASN1_SEQUENCE)
500: {
501: type = cert[(*offset)++];
502: length = get_asn1_length(cert, offset);
503:
504: if (type == ASN1_OID && length == oid_length &&
505: memcmp(cert + *offset, oid, oid_length) == 0)
506: {
507: *offset += oid_length;
508: return 1;
509: }
510: }
511:
512: *offset = noffset;
513: }
514: }
515:
516: return 0;
517: }
518:
519: int asn1_find_subjectaltname(const uint8_t* cert, int offset)
520: {
521: if (asn1_find_oid(cert, &offset, sig_subject_alt_name,
522: SIG_SUBJECT_ALT_NAME_SIZE))
523: {
524: return offset;
525: }
526:
527: return 0;
528: }
529:
530: #endif /* CONFIG_SSL_CERT_VERIFICATION */
531:
532: /**
533: * Read the signature type of the certificate. We only support RSA-MD5 and
534: * RSA-SHA1 signature types.
535: */
536: int asn1_signature_type(const uint8_t *cert,
537: int *offset, X509_CTX *x509_ctx)
538: {
539: int ret = X509_NOT_OK, len;
540:
541: if (cert[(*offset)++] != ASN1_OID)
542: goto end_check_sig;
543:
544: len = get_asn1_length(cert, offset);
545:
546: if (len == 5 && memcmp(sig_sha1WithRSAEncrypt, &cert[*offset],
547: SIG_IIS6_OID_SIZE) == 0)
548: {
549: x509_ctx->sig_type = SIG_TYPE_SHA1;
550: }
551: else
552: {
553: if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
554: goto end_check_sig; /* unrecognised cert type */
555:
556: x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
557: }
558:
559: *offset += len;
560: asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
561: ret = X509_OK;
562:
563: end_check_sig:
564: return ret;
565: }
566:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>