Annotation of embedaddon/axTLS/ssl/asn1.c, revision 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>