Ashley Mills / axTLS
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers asn1.c Source File

asn1.c

00001 /*
00002  * Copyright (c) 2007, Cameron Rich
00003  * 
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without 
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * * Redistributions of source code must retain the above copyright notice, 
00010  *   this list of conditions and the following disclaimer.
00011  * * Redistributions in binary form must reproduce the above copyright notice, 
00012  *   this list of conditions and the following disclaimer in the documentation 
00013  *   and/or other materials provided with the distribution.
00014  * * Neither the name of the axTLS project nor the names of its contributors 
00015  *   may be used to endorse or promote products derived from this software 
00016  *   without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00021  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00025  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00026  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 /**
00032  * Some primitive asn methods for extraction ASN.1 data.
00033  */
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <time.h>
00039 #include "os_port.h"
00040 #include "crypto.h "
00041 #include "crypto_misc.h "
00042 #include "config.h"
00043 
00044 #define SIG_OID_PREFIX_SIZE 8
00045 #define SIG_IIS6_OID_SIZE   5
00046 #define SIG_SUBJECT_ALT_NAME_SIZE 3
00047 
00048 /* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
00049 static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] = 
00050 {
00051     0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
00052 };
00053 
00054 static const uint8_t sig_sha1WithRSAEncrypt[SIG_IIS6_OID_SIZE] =
00055 {
00056     0x2b, 0x0e, 0x03, 0x02, 0x1d
00057 };
00058 
00059 static const uint8_t sig_subject_alt_name[SIG_SUBJECT_ALT_NAME_SIZE] =
00060 {
00061     0x55, 0x1d, 0x11
00062 };
00063 
00064 /* CN, O, OU */
00065 static const uint8_t g_dn_types[] = { 3, 10, 11 };
00066 
00067 int get_asn1_length(const uint8_t *buf, int *offset)
00068 {
00069     int len, i;
00070 
00071     if (!(buf[*offset] & 0x80)) /* short form */
00072     {
00073         len = buf[(*offset)++];
00074     }
00075     else  /* long form */
00076     {
00077         int length_bytes = buf[(*offset)++]&0x7f;
00078         len = 0;
00079         for (i = 0; i < length_bytes; i++)
00080         {
00081             len <<= 8;
00082             len += buf[(*offset)++];
00083         }
00084     }
00085 
00086     return len;
00087 }
00088 
00089 /**
00090  * Skip the ASN1.1 object type and its length. Get ready to read the object's
00091  * data.
00092  */
00093 int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
00094 {
00095     if (buf[*offset] != obj_type)
00096         return X509_NOT_OK;
00097     (*offset)++;
00098     return get_asn1_length(buf, offset);
00099 }
00100 
00101 /**
00102  * Skip over an ASN.1 object type completely. Get ready to read the next
00103  * object.
00104  */
00105 int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
00106 {
00107     int len;
00108 
00109     if (buf[*offset] != obj_type)
00110         return X509_NOT_OK;
00111     (*offset)++;
00112     len = get_asn1_length(buf, offset);
00113     *offset += len;
00114     return 0;
00115 }
00116 
00117 /**
00118  * Read an integer value for ASN.1 data
00119  * Note: This function allocates memory which must be freed by the user.
00120  */
00121 int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
00122 {
00123     int len;
00124 
00125     if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
00126         goto end_int_array;
00127 
00128     if (len > 1 && buf[*offset] == 0x00)    /* ignore the negative byte */
00129     {
00130         len--;
00131         (*offset)++;
00132     }
00133 
00134     *object = (uint8_t *)malloc(len);
00135     memcpy(*object, &buf[*offset], len);
00136     *offset += len;
00137 
00138 end_int_array:
00139     return len;
00140 }
00141 
00142 /**
00143  * Get all the RSA private key specifics from an ASN.1 encoded file 
00144  */
00145 int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
00146 {
00147     int offset = 7;
00148     uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL;
00149     int mod_len, priv_len, pub_len;
00150 #ifdef CONFIG_BIGINT_CRT
00151     uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL;
00152     int p_len, q_len, dP_len, dQ_len, qInv_len;
00153 #endif
00154 
00155     /* not in der format */
00156     if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
00157     {
00158 #ifdef CONFIG_SSL_FULL_MODE
00159         printf("Error: This is not a valid ASN.1 file\n");
00160 #endif
00161         return X509_INVALID_PRIV_KEY;
00162     }
00163 
00164     /* Use the private key to mix up the RNG if possible. */
00165     RNG_custom_init(buf, len);
00166 
00167     mod_len = asn1_get_int(buf, &offset, &modulus);
00168     pub_len = asn1_get_int(buf, &offset, &pub_exp);
00169     priv_len = asn1_get_int(buf, &offset, &priv_exp);
00170 
00171     if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
00172         return X509_INVALID_PRIV_KEY;
00173 
00174 #ifdef CONFIG_BIGINT_CRT
00175     p_len = asn1_get_int(buf, &offset, &p);
00176     q_len = asn1_get_int(buf, &offset, &q);
00177     dP_len = asn1_get_int(buf, &offset, &dP);
00178     dQ_len = asn1_get_int(buf, &offset, &dQ);
00179     qInv_len = asn1_get_int(buf, &offset, &qInv);
00180 
00181     if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
00182         return X509_INVALID_PRIV_KEY;
00183 
00184     RSA_priv_key_new(rsa_ctx, 
00185             modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
00186             p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
00187 
00188     free(p);
00189     free(q);
00190     free(dP);
00191     free(dQ);
00192     free(qInv);
00193 #else
00194     RSA_priv_key_new(rsa_ctx, 
00195             modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
00196 #endif
00197 
00198     free(modulus);
00199     free(priv_exp);
00200     free(pub_exp);
00201     return X509_OK;
00202 }
00203 
00204 /**
00205  * Get the time of a certificate. Ignore hours/minutes/seconds.
00206  */
00207 static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
00208 {
00209     int ret = X509_NOT_OK, len, t_offset;
00210     struct tm tm;
00211 
00212     if (buf[(*offset)++] != ASN1_UTC_TIME)
00213         goto end_utc_time;
00214 
00215     len = get_asn1_length(buf, offset);
00216     t_offset = *offset;
00217 
00218     memset(&tm, 0, sizeof(struct tm));
00219     tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
00220 
00221     if (tm.tm_year <= 50)    /* 1951-2050 thing */
00222     {
00223         tm.tm_year += 100;
00224     }
00225 
00226     tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
00227     tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
00228     *t = mktime(&tm);
00229     *offset += len;
00230     ret = X509_OK;
00231 
00232 end_utc_time:
00233     return ret;
00234 }
00235 
00236 /**
00237  * Get the version type of a certificate (which we don't actually care about)
00238  */
00239 int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00240 {
00241     int ret = X509_NOT_OK;
00242 
00243     (*offset) += 2;        /* get past explicit tag */
00244     if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
00245         goto end_version;
00246 
00247     ret = X509_OK;
00248 end_version:
00249     return ret;
00250 }
00251 
00252 /**
00253  * Retrieve the notbefore and notafter certificate times.
00254  */
00255 int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00256 {
00257     return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
00258               asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
00259               asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
00260 }
00261 
00262 /**
00263  * Get the components of a distinguished name 
00264  */
00265 static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
00266 {
00267     int dn_type = 0;
00268     int len;
00269 
00270     if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
00271         goto end_oid;
00272 
00273     /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
00274        components we are interested in. */
00275     if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
00276         dn_type = buf[(*offset)++];
00277     else
00278     {
00279         *offset += len;     /* skip over it */
00280     }
00281 
00282 end_oid:
00283     return dn_type;
00284 }
00285 
00286 /**
00287  * Obtain an ASN.1 printable string type.
00288  */
00289 static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
00290 {
00291     int len = X509_NOT_OK;
00292     int asn1_type = buf[*offset];
00293 
00294     /* some certs have this awful crud in them for some reason */
00295     if (asn1_type != ASN1_PRINTABLE_STR &&  
00296             asn1_type != ASN1_PRINTABLE_STR2 &&  
00297             asn1_type != ASN1_TELETEX_STR &&  
00298             asn1_type != ASN1_IA5_STR &&  
00299             asn1_type != ASN1_UNICODE_STR)
00300         goto end_pnt_str;
00301 
00302     (*offset)++;
00303     len = get_asn1_length(buf, offset);
00304 
00305     if (asn1_type == ASN1_UNICODE_STR)
00306     {
00307         int i;
00308         *str = (char *)malloc(len/2+1);     /* allow for null */
00309 
00310         for (i = 0; i < len; i += 2)
00311             (*str)[i/2] = buf[*offset + i + 1];
00312 
00313         (*str)[len/2] = 0;                  /* null terminate */
00314     }
00315     else
00316     {
00317         *str = (char *)malloc(len+1);       /* allow for null */
00318         memcpy(*str, &buf[*offset], len);
00319         (*str)[len] = 0;                    /* null terminate */
00320     }
00321 
00322     *offset += len;
00323 
00324 end_pnt_str:
00325     return len;
00326 }
00327 
00328 /**
00329  * Get the subject name (or the issuer) of a certificate.
00330  */
00331 int asn1_name(const uint8_t *cert, int *offset, char *dn[])
00332 {
00333     int ret = X509_NOT_OK;
00334     int dn_type;
00335     char *tmp;
00336 
00337     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
00338         goto end_name;
00339 
00340     while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
00341     {
00342         int i, found = 0;
00343 
00344         if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
00345                (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
00346             goto end_name;
00347 
00348         tmp = NULL;
00349 
00350         if (asn1_get_printable_str(cert, offset, &tmp) < 0)
00351         {
00352             free(tmp);
00353             goto end_name;
00354         }
00355 
00356         /* find the distinguished named type */
00357         for (i = 0; i < X509_NUM_DN_TYPES; i++)
00358         {
00359             if (dn_type == g_dn_types[i])
00360             {
00361                 if (dn[i] == NULL)
00362                 {
00363                     dn[i] = tmp;
00364                     found = 1;
00365                     break;
00366                 }
00367             }
00368         }
00369 
00370         if (found == 0) /* not found so get rid of it */
00371         {
00372             free(tmp);
00373         }
00374     }
00375 
00376     ret = X509_OK;
00377 end_name:
00378     return ret;
00379 }
00380 
00381 /**
00382  * Read the modulus and public exponent of a certificate.
00383  */
00384 int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00385 {
00386     int ret = X509_NOT_OK, mod_len, pub_len;
00387     uint8_t *modulus = NULL, *pub_exp = NULL;
00388 
00389     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
00390             asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
00391             asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
00392         goto end_pub_key;
00393 
00394     (*offset)++;        /* ignore the padding bit field */
00395 
00396     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
00397         goto end_pub_key;
00398 
00399     mod_len = asn1_get_int(cert, offset, &modulus);
00400     pub_len = asn1_get_int(cert, offset, &pub_exp);
00401 
00402     RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
00403 
00404     free(modulus);
00405     free(pub_exp);
00406     ret = X509_OK;
00407 
00408 end_pub_key:
00409     return ret;
00410 }
00411 
00412 #ifdef CONFIG_SSL_CERT_VERIFICATION
00413 /**
00414  * Read the signature of the certificate.
00415  */
00416 int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00417 {
00418     int ret = X509_NOT_OK;
00419 
00420     if (cert[(*offset)++] != ASN1_BIT_STRING)
00421         goto end_sig;
00422 
00423     x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
00424     (*offset)++;            /* ignore bit string padding bits */
00425     x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
00426     memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
00427     *offset += x509_ctx->sig_len;
00428     ret = X509_OK;
00429 
00430 end_sig:
00431     return ret;
00432 }
00433 
00434 /*
00435  * Compare 2 distinguished name components for equality 
00436  * @return 0 if a match
00437  */
00438 static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
00439 {
00440     int ret;
00441 
00442     if (dn1 == NULL && dn2 == NULL)
00443         ret = 0;
00444     else
00445         ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 1;
00446 
00447     return ret;
00448 }
00449 
00450 /**
00451  * Clean up all of the CA certificates.
00452  */
00453 void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
00454 {
00455     int i = 0;
00456 
00457     if (ca_cert_ctx == NULL)
00458         return;
00459 
00460     while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
00461     {
00462         x509_free(ca_cert_ctx->cert[i]);
00463         ca_cert_ctx->cert[i++] = NULL;
00464     }
00465 
00466     free(ca_cert_ctx);
00467 }
00468 
00469 /*
00470  * Compare 2 distinguished names for equality 
00471  * @return 0 if a match
00472  */
00473 int asn1_compare_dn(char * const dn1[], char * const dn2[])
00474 {
00475     int i;
00476 
00477     for (i = 0; i < X509_NUM_DN_TYPES; i++)
00478     {
00479         if (asn1_compare_dn_comp(dn1[i], dn2[i]))
00480             return 1;
00481     }
00482 
00483     return 0;       /* all good */
00484 }
00485 
00486 int asn1_find_oid(const uint8_t* cert, int* offset, 
00487                     const uint8_t* oid, int oid_length)
00488 {
00489     int seqlen;
00490     if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
00491     {
00492         int end = *offset + seqlen;
00493 
00494         while (*offset < end)
00495         {
00496             int type = cert[(*offset)++];
00497             int length = get_asn1_length(cert, offset);
00498             int noffset = *offset + length;
00499 
00500             if (type == ASN1_SEQUENCE)
00501             {
00502                 type = cert[(*offset)++];
00503                 length = get_asn1_length(cert, offset);
00504 
00505                 if (type == ASN1_OID && length == oid_length && 
00506                               memcmp(cert + *offset, oid, oid_length) == 0)
00507                 {
00508                     *offset += oid_length;
00509                     return 1;
00510                 }
00511             }
00512 
00513             *offset = noffset;
00514         }
00515     }
00516 
00517     return 0;
00518 }
00519 
00520 int asn1_find_subjectaltname(const uint8_t* cert, int offset)
00521 {
00522     if (asn1_find_oid(cert, &offset, sig_subject_alt_name, 
00523                                 SIG_SUBJECT_ALT_NAME_SIZE))
00524     {
00525         return offset;
00526     }
00527 
00528     return 0;
00529 }
00530 
00531 #endif /* CONFIG_SSL_CERT_VERIFICATION */
00532 
00533 /**
00534  * Read the signature type of the certificate. We only support RSA-MD5 and
00535  * RSA-SHA1 signature types.
00536  */
00537 int asn1_signature_type(const uint8_t *cert, 
00538                                 int *offset, X509_CTX *x509_ctx)
00539 {
00540     int ret = X509_NOT_OK, len;
00541 
00542     if (cert[(*offset)++] != ASN1_OID)
00543         goto end_check_sig;
00544 
00545     len = get_asn1_length(cert, offset);
00546 
00547     if (len == 5 && memcmp(sig_sha1WithRSAEncrypt, &cert[*offset], 
00548                                     SIG_IIS6_OID_SIZE) == 0)
00549     {
00550         x509_ctx->sig_type = SIG_TYPE_SHA1;
00551     }
00552     else
00553     {
00554         if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
00555             goto end_check_sig;     /* unrecognised cert type */
00556 
00557         x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
00558     }
00559 
00560     *offset += len;
00561     asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
00562     ret = X509_OK;
00563 
00564 end_check_sig:
00565     return ret;
00566 }
00567