ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

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     int tmp = get_asn1_length(buf, offset);
00099     return tmp;
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     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     RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
00402     free(modulus);
00403     free(pub_exp);
00404     ret = X509_OK;
00405     
00406 end_pub_key:
00407     return ret;
00408 }
00409 
00410 #ifdef CONFIG_SSL_CERT_VERIFICATION
00411 /**
00412  * Read the signature of the certificate.
00413  */
00414 int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
00415 {
00416     int ret = X509_NOT_OK;
00417 
00418     if (cert[(*offset)++] != ASN1_BIT_STRING)
00419         goto end_sig;
00420 
00421     x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
00422     (*offset)++;            /* ignore bit string padding bits */
00423     x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
00424     memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
00425     *offset += x509_ctx->sig_len;
00426     ret = X509_OK;
00427 
00428 end_sig:
00429     return ret;
00430 }
00431 
00432 /*
00433  * Compare 2 distinguished name components for equality 
00434  * @return 0 if a match
00435  */
00436 static int asn1_compare_dn_comp(const char *dn1, const char *dn2)
00437 {
00438     int ret;
00439 
00440     if (dn1 == NULL && dn2 == NULL)
00441         ret = 0;
00442     else
00443         ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 1;
00444 
00445     return ret;
00446 }
00447 
00448 /**
00449  * Clean up all of the CA certificates.
00450  */
00451 void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx)
00452 {
00453     int i = 0;
00454 
00455     if (ca_cert_ctx == NULL)
00456         return;
00457 
00458     while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
00459     {
00460         x509_free(ca_cert_ctx->cert[i]);
00461         ca_cert_ctx->cert[i++] = NULL;
00462     }
00463 
00464     free(ca_cert_ctx);
00465 }
00466 
00467 /*
00468  * Compare 2 distinguished names for equality 
00469  * @return 0 if a match
00470  */
00471 int asn1_compare_dn(char * const dn1[], char * const dn2[])
00472 {
00473     int i;
00474 
00475     for (i = 0; i < X509_NUM_DN_TYPES; i++)
00476     {
00477         if (asn1_compare_dn_comp(dn1[i], dn2[i]))
00478             return 1;
00479     }
00480 
00481     return 0;       /* all good */
00482 }
00483 
00484 int asn1_find_oid(const uint8_t* cert, int* offset, 
00485                     const uint8_t* oid, int oid_length)
00486 {
00487     int seqlen;
00488     if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
00489     {
00490         int end = *offset + seqlen;
00491 
00492         while (*offset < end)
00493         {
00494             int type = cert[(*offset)++];
00495             int length = get_asn1_length(cert, offset);
00496             int noffset = *offset + length;
00497 
00498             if (type == ASN1_SEQUENCE)
00499             {
00500                 type = cert[(*offset)++];
00501                 length = get_asn1_length(cert, offset);
00502 
00503                 if (type == ASN1_OID && length == oid_length && 
00504                               memcmp(cert + *offset, oid, oid_length) == 0)
00505                 {
00506                     *offset += oid_length;
00507                     return 1;
00508                 }
00509             }
00510 
00511             *offset = noffset;
00512         }
00513     }
00514 
00515     return 0;
00516 }
00517 
00518 int asn1_find_subjectaltname(const uint8_t* cert, int offset)
00519 {
00520     if (asn1_find_oid(cert, &offset, sig_subject_alt_name, 
00521                                 SIG_SUBJECT_ALT_NAME_SIZE))
00522     {
00523         return offset;
00524     }
00525 
00526     return 0;
00527 }
00528 
00529 #endif /* CONFIG_SSL_CERT_VERIFICATION */
00530 
00531 /**
00532  * Read the signature type of the certificate. We only support RSA-MD5 and
00533  * RSA-SHA1 signature types.
00534  */
00535 int asn1_signature_type(const uint8_t *cert, 
00536                                 int *offset, X509_CTX *x509_ctx)
00537 {
00538     int ret = X509_NOT_OK, len;
00539 
00540     if (cert[(*offset)++] != ASN1_OID)
00541         goto end_check_sig;
00542 
00543     len = get_asn1_length(cert, offset);
00544 
00545     if (len == 5 && memcmp(sig_sha1WithRSAEncrypt, &cert[*offset], 
00546                                     SIG_IIS6_OID_SIZE) == 0)
00547     {
00548         x509_ctx->sig_type = SIG_TYPE_SHA1;
00549     }
00550     else
00551     {
00552         if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
00553             goto end_check_sig;     /* unrecognised cert type */
00554 
00555         x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
00556     }
00557 
00558     *offset += len;
00559     asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
00560     ret = X509_OK;
00561 
00562 end_check_sig:
00563     return ret;
00564 }
00565