Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
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
Generated on Tue Jul 12 2022 13:15:29 by
