File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / axTLS / ssl / asn1.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Sep 28 11:55:55 2012 UTC (12 years, 6 months ago) by misho
Branches: v1_4_8, MAIN
CVS tags: datecs, HEAD
axTLS

    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>