This is a fork of the mbed port of axTLS

Dependents:   TLS_axTLS-Example HTTPSClientExample

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 
00043 #define SIG_OID_PREFIX_SIZE 8
00044 #define SIG_IIS6_OID_SIZE   5
00045 #define SIG_SUBJECT_ALT_NAME_SIZE 3
00046 
00047 /* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */
00048 static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] = 
00049 {
00050     0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01
00051 };
00052 
00053 static const uint8_t sig_sha1WithRSAEncrypt[SIG_IIS6_OID_SIZE] =
00054 {
00055     0x2b, 0x0e, 0x03, 0x02, 0x1d
00056 };
00057 
00058 static const uint8_t sig_subject_alt_name[SIG_SUBJECT_ALT_NAME_SIZE] =
00059 {
00060     0x55, 0x1d, 0x11
00061 };
00062 
00063 /* CN, O, OU */
00064 static const uint8_t g_dn_types[] = { 3, 10, 11 };
00065 
00066 static const uint8_t rsaOID[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
00067 
00068 
00069 int get_asn1_length(const uint8_t *buf, int *offset)
00070 {
00071     int len, i;
00072 
00073     if (!(buf[*offset] & 0x80)) /* short form */
00074     {
00075         len = buf[(*offset)++];
00076     }
00077     else  /* long form */
00078     {
00079         int length_bytes = buf[(*offset)++]&0x7f;
00080         len = 0;
00081         for (i = 0; i < length_bytes; i++)
00082         {
00083             len <<= 8;
00084             len += buf[(*offset)++];
00085         }
00086     }
00087     return len;
00088 }
00089 
00090 /**
00091  * Skip the ASN1.1 object type and its length. Get ready to read the object's
00092  * data.
00093  */
00094 int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
00095 {
00096     if (buf[*offset] != obj_type)
00097         return X509_NOT_OK;
00098     (*offset)++;
00099     return get_asn1_length(buf, offset);
00100 }
00101 
00102 /**
00103  * Skip over an ASN.1 object type completely. Get ready to read the next
00104  * object.
00105  */
00106 int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
00107 {
00108     int len;
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 
00140     return len;
00141 }
00142 
00143 /**
00144  * Get all the RSA private key specifics from an ASN.1 encoded file 
00145  */
00146 int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
00147 {
00148     int offset = 7;
00149     uint8_t *modulus = NULL, *priv_exp = NULL, *pub_exp = NULL;
00150     int mod_len, priv_len, pub_len;
00151 #ifdef CONFIG_BIGINT_CRT
00152     uint8_t *p = NULL, *q = NULL, *dP = NULL, *dQ = NULL, *qInv = NULL;
00153     int p_len, q_len, dP_len, dQ_len, qInv_len;
00154 #endif
00155 
00156     /* not in der format */
00157     if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */
00158     {
00159 #ifdef CONFIG_SSL_FULL_MODE
00160         printf("Error: This is not a valid ASN.1 file\n");
00161 #endif
00162         return X509_INVALID_PRIV_KEY;
00163     }
00164 
00165     /* Use the private key to mix up the RNG if possible. */
00166     RNG_custom_init(buf, len);
00167 
00168     mod_len = asn1_get_int(buf, &offset, &modulus);
00169     pub_len = asn1_get_int(buf, &offset, &pub_exp);
00170     priv_len = asn1_get_int(buf, &offset, &priv_exp);
00171 
00172     if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
00173         return X509_INVALID_PRIV_KEY;
00174 
00175 #ifdef CONFIG_BIGINT_CRT
00176     p_len = asn1_get_int(buf, &offset, &p);
00177     q_len = asn1_get_int(buf, &offset, &q);
00178     dP_len = asn1_get_int(buf, &offset, &dP);
00179     dQ_len = asn1_get_int(buf, &offset, &dQ);
00180     qInv_len = asn1_get_int(buf, &offset, &qInv);
00181 
00182     if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
00183         return X509_INVALID_PRIV_KEY;
00184 
00185     RSA_priv_key_new(rsa_ctx, 
00186             modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len,
00187             p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len);
00188 
00189     free(p);
00190     free(q);
00191     free(dP);
00192     free(dQ);
00193     free(qInv);
00194 #else
00195     RSA_priv_key_new(rsa_ctx, 
00196             modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len);
00197 #endif
00198 
00199     free(modulus);
00200     free(priv_exp);
00201     free(pub_exp);
00202     return X509_OK;
00203 }
00204 
00205 /**
00206  * Get the time of a certificate. Ignore hours/minutes/seconds.
00207  */
00208 static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
00209 {
00210     int ret = X509_NOT_OK, len, t_offset;
00211     struct tm tm;
00212 
00213     if (buf[(*offset)++] != ASN1_UTC_TIME)
00214         goto end_utc_time;
00215 
00216     len = get_asn1_length(buf, offset);
00217     t_offset = *offset;
00218 
00219     memset(&tm, 0, sizeof(struct tm));
00220     tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
00221 
00222     if (tm.tm_year <= 50)    /* 1951-2050 thing */
00223     {
00224         tm.tm_year += 100;
00225     }
00226 
00227     tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
00228     tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
00229     *t = mktime(&tm);
00230     *offset += len;
00231     ret = X509_OK;
00232 
00233 end_utc_time:
00234     return ret;
00235 }
00236 
00237 /**
00238  * Get the version type of a certificate (which we don't actually care about)
00239  */
00240 int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00241 {
00242 
00243     int ret = X509_NOT_OK;
00244 
00245     (*offset) += 2;        /* get past explicit tag */
00246     if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
00247         goto end_version;
00248 
00249     ret = X509_OK;
00250 end_version:
00251     return ret;
00252 }
00253 
00254 /**
00255  * Retrieve the notbefore and notafter certificate times.
00256  */
00257 int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00258 {
00259     return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
00260               asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
00261               asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
00262 }
00263 
00264 /**
00265  * Get the components of a distinguished name 
00266  */
00267 static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
00268 {
00269     int dn_type = 0;
00270     int len;
00271 
00272     if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
00273         goto end_oid;
00274 
00275     /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
00276        components we are interested in. */
00277     if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
00278         dn_type = buf[(*offset)++];
00279     else
00280     {
00281         *offset += len;     /* skip over it */
00282     }
00283 
00284 end_oid:
00285     return dn_type;
00286 }
00287 
00288 /**
00289  * Obtain an ASN.1 printable string type.
00290  */
00291 static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
00292 {
00293     int len = X509_NOT_OK;
00294     int asn1_type = buf[*offset];
00295 
00296     /* some certs have this awful crud in them for some reason */
00297     if (asn1_type != ASN1_PRINTABLE_STR &&  
00298             asn1_type != ASN1_PRINTABLE_STR2 &&  
00299             asn1_type != ASN1_TELETEX_STR &&  
00300             asn1_type != ASN1_IA5_STR &&  
00301             asn1_type != ASN1_UNICODE_STR)
00302         goto end_pnt_str;
00303 
00304     (*offset)++;
00305     len = get_asn1_length(buf, offset);
00306 
00307     if (asn1_type == ASN1_UNICODE_STR)
00308     {
00309         int i;
00310         *str = (char *)malloc(len/2+1);     /* allow for null */
00311 
00312         for (i = 0; i < len; i += 2)
00313             (*str)[i/2] = buf[*offset + i + 1];
00314 
00315         (*str)[len/2] = 0;                  /* null terminate */
00316     }
00317     else
00318     {
00319         *str = (char *)malloc(len+1);       /* allow for null */
00320         memcpy(*str, &buf[*offset], len);
00321         (*str)[len] = 0;                    /* null terminate */
00322     }
00323 
00324     *offset += len;
00325 
00326 end_pnt_str:
00327     return len;
00328 }
00329 
00330 /**
00331  * Get the subject name (or the issuer) of a certificate.
00332  */
00333 int asn1_name(const uint8_t *cert, int *offset, char *dn[])
00334 {
00335     int ret = X509_NOT_OK;
00336     int dn_type;
00337     char *tmp;
00338 
00339     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
00340         goto end_name;
00341 
00342     while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
00343     {
00344         int i, found = 0;
00345 
00346         if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
00347                (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
00348             goto end_name;
00349 
00350         tmp = NULL;
00351 
00352         if (asn1_get_printable_str(cert, offset, &tmp) < 0)
00353         {
00354             free(tmp);
00355             goto end_name;
00356         }
00357 
00358         /* find the distinguished named type */
00359         for (i = 0; i < X509_NUM_DN_TYPES; i++)
00360         {
00361             if (dn_type == g_dn_types[i])
00362             {
00363                 if (dn[i] == NULL)
00364                 {
00365                     dn[i] = tmp;
00366                     found = 1;
00367                     break;
00368                 }
00369             }
00370         }
00371 
00372         if (found == 0) /* not found so get rid of it */
00373         {
00374             free(tmp);
00375         }
00376     }
00377 
00378     ret = X509_OK;
00379 end_name:
00380     return ret;
00381 }
00382 
00383 /**
00384  * Read the modulus and public exponent of a certificate.
00385  */
00386 int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00387 {
00388     int ret = X509_NOT_OK, mod_len, pub_len;
00389     int offset2 = 0, oid_len = 0;
00390     uint8_t *modulus = NULL, *pub_exp = NULL;
00391  
00392     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
00393         goto end_pub_key;
00394     
00395     offset2 = *offset;
00396     if(asn1_next_obj(cert, &offset2, ASN1_SEQUENCE) < 0)
00397         goto end_pub_key;
00398     oid_len = asn1_next_obj(cert, &offset2, ASN1_OID);
00399     if(oid_len < 0)
00400         goto end_pub_key;
00401     if(memcmp(rsaOID, &cert[offset2], oid_len))
00402     {
00403         printf("Only RSA public key algorithm is supported\n");
00404         goto end_pub_key;
00405     }
00406     
00407     if (asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
00408         asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
00409         goto end_pub_key;
00410  
00411     (*offset)++;        /* ignore the padding bit field */
00412  
00413     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
00414         goto end_pub_key;
00415  
00416     mod_len = asn1_get_int(cert, offset, &modulus);
00417     pub_len = asn1_get_int(cert, offset, &pub_exp);
00418  
00419     RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
00420  
00421     free(modulus);
00422     free(pub_exp);
00423     ret = X509_OK;
00424  
00425 end_pub_key:
00426     return ret;
00427 }
00428 
00429 #ifdef CONFIG_SSL_CERT_VERIFICATION
00430 /**
00431  * Read the signature of the certificate.
00432  */
00433 int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00434 {
00435     int ret = X509_NOT_OK;
00436 
00437     if (cert[(*offset)++] != ASN1_BIT_STRING)
00438         goto end_sig;
00439 
00440     x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
00441     (*offset)++;            /* ignore bit string padding bits */
00442     x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
00443     memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
00444     *offset += x509_ctx->sig_len;
00445     ret = X509_OK;
00446 
00447 end_sig:
00448     return ret;
00449 }
00450 
00451 /*
00452  * Compare 2 distinguished name components for equality 
00453  * @return 0 if a match
00454  */
00455 static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
00456 {
00457     int ret;
00458 
00459     if (dn1 == NULL && dn2 == NULL)
00460         ret = 0;
00461     else
00462         ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 1;
00463 
00464     return ret;
00465 }
00466 
00467 /**
00468  * Clean up all of the CA certificates.
00469  */
00470 void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
00471 {
00472     int i = 0;
00473 
00474     if (ca_cert_ctx == NULL)
00475         return;
00476 
00477     while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
00478     {
00479         x509_free(ca_cert_ctx->cert[i]);
00480         ca_cert_ctx->cert[i++] = NULL;
00481     }
00482 
00483     free(ca_cert_ctx);
00484 }
00485 
00486 /*
00487  * Compare 2 distinguished names for equality 
00488  * @return 0 if a match
00489  */
00490 int asn1_compare_dn(char * const dn1[], char * const dn2[])
00491 {
00492     int i;
00493 
00494     for (i = 0; i < X509_NUM_DN_TYPES; i++)
00495     {
00496         if (asn1_compare_dn_comp(dn1[i], dn2[i]))
00497             return 1;
00498     }
00499 
00500     return 0;       /* all good */
00501 }
00502 
00503 int asn1_find_oid(const uint8_t* cert, int* offset, 
00504                     const uint8_t* oid, int oid_length)
00505 {
00506     int seqlen;
00507     if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
00508     {
00509         int end = *offset + seqlen;
00510 
00511         while (*offset < end)
00512         {
00513             int type = cert[(*offset)++];
00514             int length = get_asn1_length(cert, offset);
00515             int noffset = *offset + length;
00516 
00517             if (type == ASN1_SEQUENCE)
00518             {
00519                 type = cert[(*offset)++];
00520                 length = get_asn1_length(cert, offset);
00521 
00522                 if (type == ASN1_OID && length == oid_length && 
00523                               memcmp(cert + *offset, oid, oid_length) == 0)
00524                 {
00525                     *offset += oid_length;
00526                     return 1;
00527                 }
00528             }
00529 
00530             *offset = noffset;
00531         }
00532     }
00533 
00534     return 0;
00535 }
00536 
00537 int asn1_find_subjectaltname(const uint8_t* cert, int offset)
00538 {
00539     if (asn1_find_oid(cert, &offset, sig_subject_alt_name, 
00540                                 SIG_SUBJECT_ALT_NAME_SIZE))
00541     {
00542         return offset;
00543     }
00544 
00545     return 0;
00546 }
00547 
00548 #endif /* CONFIG_SSL_CERT_VERIFICATION */
00549 
00550 /**
00551  * Read the signature type of the certificate. We only support RSA-MD5 and
00552  * RSA-SHA1 signature types.
00553  */
00554 int asn1_signature_type(const uint8_t *cert, 
00555                                 int *offset, X509_CTX *x509_ctx)
00556 {
00557     int ret = X509_NOT_OK, len;
00558 
00559     if (cert[(*offset)++] != ASN1_OID)
00560         goto end_check_sig;
00561 
00562     len = get_asn1_length(cert, offset);
00563 
00564     if (len == 5 && memcmp(sig_sha1WithRSAEncrypt, &cert[*offset], 
00565                                     SIG_IIS6_OID_SIZE) == 0)
00566     {
00567         x509_ctx->sig_type = SIG_TYPE_SHA1;
00568     }
00569     else
00570     {
00571         if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
00572             goto end_check_sig;     /* unrecognised cert type */
00573 
00574         x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
00575     }
00576 
00577     *offset += len;
00578     asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
00579     ret = X509_OK;
00580 
00581 end_check_sig:
00582     return ret;
00583 }
00584 
00585 
00586