This is a fork of the mbed port of axTLS
Dependents: TLS_axTLS-Example HTTPSClientExample
x509.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 * @file x509.c 00033 * 00034 * Certificate processing. 00035 */ 00036 00037 #include <time.h> 00038 #include <stdio.h> 00039 #include <stdlib.h> 00040 #include <string.h> 00041 #include "os_port.h" 00042 #include "crypto_misc.h " 00043 #include "sockets.h" 00044 #include "config.h" 00045 #ifdef CONFIG_SSL_CERT_VERIFICATION 00046 #include "../../cert_manager.h" 00047 00048 /** 00049 * Retrieve the signature from a certificate. 00050 */ 00051 static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len) 00052 { 00053 int offset = 0; 00054 const uint8_t *ptr = NULL; 00055 00056 if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || 00057 asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE)) 00058 goto end_get_sig; 00059 00060 if (asn1_sig[offset++] != ASN1_OCTET_STRING) 00061 goto end_get_sig; 00062 *len = get_asn1_length(asn1_sig, &offset); 00063 ptr = &asn1_sig[offset]; /* all ok */ 00064 00065 end_get_sig: 00066 return ptr; 00067 } 00068 00069 #endif 00070 00071 /** 00072 * Construct a new x509 object. 00073 * @return 0 if ok. < 0 if there was a problem. 00074 */ 00075 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) 00076 { 00077 00078 int begin_tbs, end_tbs; 00079 int ret = X509_NOT_OK, offset = 0, cert_size = 0; 00080 X509_CTX *x509_ctx; 00081 BI_CTX *bi_ctx; 00082 *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX)); 00083 x509_ctx = *ctx; 00084 /* get the certificate size */ 00085 asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 00086 00087 if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) 00088 goto end_cert; 00089 00090 begin_tbs = offset; /* start of the tbs */ 00091 end_tbs = begin_tbs; /* work out the end of the tbs */ 00092 asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE); 00093 if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) 00094 goto end_cert; 00095 if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */ 00096 { 00097 if (asn1_version(cert, &offset, x509_ctx)) 00098 goto end_cert; 00099 } 00100 if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 00101 asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) 00102 { 00103 goto end_cert; 00104 } 00105 00106 /* make sure the signature is ok */ 00107 if (asn1_signature_type(cert, &offset, x509_ctx)) 00108 { 00109 ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST; 00110 goto end_cert; 00111 } 00112 if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 00113 asn1_validity(cert, &offset, x509_ctx) || 00114 asn1_name(cert, &offset, x509_ctx->cert_dn) || 00115 asn1_public_key(cert, &offset, x509_ctx)) 00116 { 00117 goto end_cert; 00118 } 00119 bi_ctx = x509_ctx->rsa_ctx->bi_ctx; 00120 00121 00122 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ 00123 00124 /* use the appropriate signature algorithm (SHA1/MD5/MD2) */ 00125 00126 if (x509_ctx->sig_type == SIG_TYPE_MD5) 00127 { 00128 MD5_CTX md5_ctx; 00129 uint8_t md5_dgst[MD5_SIZE]; 00130 MD5_Init(&md5_ctx); 00131 MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs); 00132 MD5_Final(md5_dgst, &md5_ctx); 00133 x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE); 00134 } 00135 else if (x509_ctx->sig_type == SIG_TYPE_SHA1) 00136 { 00137 SHA1_CTX sha_ctx; 00138 uint8_t sha_dgst[SHA1_SIZE]; 00139 SHA1_Init(&sha_ctx); 00140 SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs); 00141 SHA1_Final(sha_dgst, &sha_ctx); 00142 x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE); 00143 } 00144 else if (x509_ctx->sig_type == SIG_TYPE_MD2) 00145 { 00146 MD2_CTX md2_ctx; 00147 uint8_t md2_dgst[MD2_SIZE]; 00148 MD2_Init(&md2_ctx); 00149 MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs); 00150 MD2_Final(md2_dgst, &md2_ctx); 00151 x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE); 00152 } 00153 00154 if (cert[offset] == ASN1_V3_DATA) 00155 { 00156 int suboffset; 00157 00158 ++offset; 00159 get_asn1_length(cert, &offset); 00160 00161 if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0) 00162 { 00163 if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0) 00164 { 00165 int altlen; 00166 00167 if ((altlen = asn1_next_obj(cert, 00168 &suboffset, ASN1_SEQUENCE)) > 0) 00169 { 00170 int endalt = suboffset + altlen; 00171 int totalnames = 0; 00172 00173 while (suboffset < endalt) 00174 { 00175 int type = cert[suboffset++]; 00176 int dnslen = get_asn1_length(cert, &suboffset); 00177 00178 if (type == ASN1_CONTEXT_DNSNAME) 00179 { 00180 x509_ctx->subject_alt_dnsnames = (char**) 00181 realloc(x509_ctx->subject_alt_dnsnames, 00182 (totalnames + 2) * sizeof(char*)); 00183 x509_ctx->subject_alt_dnsnames[totalnames] = 00184 (char*)malloc(dnslen + 1); 00185 x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL; 00186 memcpy(x509_ctx->subject_alt_dnsnames[totalnames], 00187 cert + suboffset, dnslen); 00188 x509_ctx->subject_alt_dnsnames[ 00189 totalnames][dnslen] = 0; 00190 ++totalnames; 00191 } 00192 00193 suboffset += dnslen; 00194 } 00195 } 00196 } 00197 } 00198 } 00199 00200 offset = end_tbs; /* skip the rest of v3 data */ 00201 if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 00202 asn1_signature(cert, &offset, x509_ctx)) 00203 goto end_cert; 00204 00205 #endif 00206 ret = X509_OK; 00207 end_cert: 00208 if (len) 00209 { 00210 *len = cert_size; 00211 } 00212 00213 if (ret) 00214 { 00215 #ifdef CONFIG_SSL_FULL_MODE 00216 printf("Error: Invalid X509 ASN.1 file (%s)\n", 00217 x509_display_error(ret)); 00218 #endif 00219 x509_free(x509_ctx); 00220 *ctx = NULL; 00221 } 00222 return ret; 00223 } 00224 00225 /** 00226 * Free an X.509 object's resources. 00227 */ 00228 void x509_free(X509_CTX *x509_ctx) 00229 { 00230 X509_CTX *next; 00231 int i; 00232 00233 if (x509_ctx == NULL) /* if already null, then don't bother */ 00234 return; 00235 00236 for (i = 0; i < X509_NUM_DN_TYPES; i++) 00237 { 00238 free(x509_ctx->ca_cert_dn[i]); 00239 free(x509_ctx->cert_dn[i]); 00240 } 00241 00242 free(x509_ctx->signature); 00243 00244 #ifdef CONFIG_SSL_CERT_VERIFICATION 00245 if (x509_ctx->digest) 00246 { 00247 bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest); 00248 } 00249 00250 if (x509_ctx->subject_alt_dnsnames) 00251 { 00252 for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i) 00253 free(x509_ctx->subject_alt_dnsnames[i]); 00254 00255 free(x509_ctx->subject_alt_dnsnames); 00256 } 00257 #endif 00258 00259 RSA_free(x509_ctx->rsa_ctx); 00260 next = x509_ctx->next; 00261 free(x509_ctx); 00262 x509_free(next); /* clear the chain */ 00263 } 00264 00265 #ifdef CONFIG_SSL_CERT_VERIFICATION 00266 /** 00267 * Take a signature and decrypt it. 00268 */ 00269 bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, 00270 bigint *modulus, bigint *pub_exp) 00271 { 00272 int i, size; 00273 bigint *decrypted_bi, *dat_bi; 00274 bigint *bir = NULL; 00275 uint8_t *block = (uint8_t *)alloca(sig_len); 00276 00277 /* decrypt */ 00278 dat_bi = bi_import(ctx, sig, sig_len); 00279 ctx->mod_offset = BIGINT_M_OFFSET; 00280 00281 /* convert to a normal block */ 00282 decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp); 00283 00284 bi_export(ctx, decrypted_bi, block, sig_len); 00285 ctx->mod_offset = BIGINT_M_OFFSET; 00286 00287 i = 10; /* start at the first possible non-padded byte */ 00288 while (block[i++] && i < sig_len); 00289 size = sig_len - i; 00290 00291 /* get only the bit we want */ 00292 if (size > 0) 00293 { 00294 int len = 0; 00295 const uint8_t *sig_ptr = get_signature(&block[i], &len); 00296 00297 if (sig_ptr) 00298 { 00299 bir = bi_import(ctx, sig_ptr, len); 00300 } 00301 } 00302 00303 /* save a few bytes of memory */ 00304 bi_clear_cache(ctx); 00305 return bir; 00306 } 00307 00308 00309 /** 00310 * Do some basic checks on the certificate chain. 00311 * 00312 * Certificate verification consists of a number of checks: 00313 * - The date of the certificate is after the start date. 00314 * - The date of the certificate is before the finish date. 00315 * - A root certificate exists in the certificate store. 00316 * - That the certificate(s) are not self-signed. 00317 * - The certificate chain is valid. 00318 * - The signature of the certificate is valid. 00319 */ 00320 int x509_verify(PrecomputedCertificate *cert) 00321 { 00322 00323 int ret = X509_OK; 00324 PrecomputedCertificate *next_cert = NULL; 00325 int match_ca_cert = 0; 00326 uint8_t is_self_signed = 0; 00327 uint8_t *mod = NULL, *expn = NULL; 00328 bigint *bi_mod = NULL, *bi_expn = NULL; 00329 BI_CTX *bi_ctx = NULL; 00330 char precomputed = is_precomputed(); 00331 00332 if (cert == NULL) 00333 { 00334 ret = X509_VFY_ERROR_NO_TRUSTED_CERT; 00335 goto end_verify; 00336 } 00337 /* a self-signed certificate that is not in the CA store - use this 00338 to check the signature */ 00339 if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0) 00340 { 00341 is_self_signed = 1; 00342 if(precomputed) 00343 { 00344 mod = cert->mod; 00345 expn = cert->expn; 00346 } 00347 else 00348 { 00349 bi_ctx = bi_initialize(); 00350 bi_mod = bi_import(bi_ctx, cert->mod, cert->mod_len); 00351 bi_expn = bi_import(bi_ctx, cert->expn, cert->expn_len); 00352 } 00353 } 00354 00355 next_cert = cert->next; 00356 00357 /* last cert in the chain - look for a trusted cert */ 00358 if (next_cert == NULL) 00359 { 00360 if(precomputed) 00361 { 00362 PrecomputedCertificate tmp = get_precomputed_cert(cert->cert_dn, cert->ca_cert_dn); 00363 mod = tmp.mod; 00364 expn = tmp.expn; 00365 } 00366 else 00367 { 00368 X509_CTX *root = get_cert(cert->ca_cert_dn); 00369 bi_ctx = root->rsa_ctx->bi_ctx; 00370 bi_mod = bi_clone(bi_ctx,root->rsa_ctx->m); 00371 bi_expn = bi_clone(bi_ctx, root->rsa_ctx->e); 00372 } 00373 } 00374 else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0) 00375 { 00376 /* check the chain */ 00377 ret = X509_VFY_ERROR_INVALID_CHAIN; 00378 goto end_verify; 00379 } 00380 else /* use the next certificate in the chain for signature verify */ 00381 { 00382 if(precomputed) 00383 { 00384 mod = next_cert->mod; 00385 expn = next_cert->expn; 00386 } 00387 else 00388 { 00389 bi_ctx = bi_initialize(); 00390 bi_mod = bi_import(bi_ctx, next_cert->mod, next_cert->mod_len); 00391 bi_expn = bi_import(bi_ctx, next_cert->expn, next_cert->expn_len); 00392 } 00393 } 00394 00395 /* cert is self signed */ 00396 if (!match_ca_cert && is_self_signed) 00397 { 00398 ret = X509_VFY_ERROR_SELF_SIGNED; 00399 goto end_verify; 00400 } 00401 00402 /* check the signature */ 00403 if(precomputed) 00404 { 00405 PrecomputedCertificate pc = get_precomputed_cert(cert->cert_dn, cert->ca_cert_dn); 00406 00407 if(memcmp(cert->sig, pc.sig, pc.sig_len) 00408 || memcmp(cert->digest, pc.digest, pc.digest_len) 00409 || memcmp(mod, pc.mod, pc.mod_len) 00410 || memcmp(expn, pc.expn, pc.expn_len)) 00411 ret = X509_VFY_ERROR_BAD_SIGNATURE; 00412 } 00413 else 00414 { 00415 bigint* cert_sig = sig_verify(bi_ctx, cert->sig, cert->sig_len, 00416 bi_mod, bi_expn); 00417 00418 if (cert_sig && cert->digest) 00419 { 00420 uint8_t paddingLength = 0; 00421 uint8_t digest[64]; 00422 bi_export(bi_ctx, cert_sig, digest, sizeof(digest)); 00423 while(digest[paddingLength] == 0) paddingLength++; 00424 uint8_t digest_len = 64 - paddingLength; 00425 if (memcmp(digest, cert->digest, digest_len) != 0) 00426 ret = X509_VFY_ERROR_BAD_SIGNATURE; 00427 } 00428 else 00429 { 00430 ret = X509_VFY_ERROR_BAD_SIGNATURE; 00431 } 00432 if(is_self_signed || next_cert != NULL) 00433 bi_terminate(bi_ctx); 00434 } 00435 00436 00437 if (ret) 00438 goto end_verify; 00439 00440 /* go down the certificate chain using recursion. */ 00441 if (next_cert != NULL) 00442 { 00443 ret = x509_verify(next_cert); 00444 } 00445 00446 end_verify: 00447 return ret; 00448 } 00449 #endif 00450 00451 #if defined (CONFIG_SSL_FULL_MODE) 00452 /** 00453 * Used for diagnostics. 00454 */ 00455 static const char *not_part_of_cert = "<Not Part Of Certificate>"; 00456 void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) 00457 { 00458 if (cert == NULL) 00459 return; 00460 00461 printf("=== CERTIFICATE ISSUED TO ===\n"); 00462 printf("Common Name (CN):\t\t"); 00463 printf("%s\r\n", cert->cert_dn[X509_COMMON_NAME] ? 00464 cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert); 00465 00466 printf("Organization (O):\t\t"); 00467 printf("%s\r\n", cert->cert_dn[X509_ORGANIZATION] ? 00468 cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert); 00469 00470 printf("Organizational Unit (OU):\t"); 00471 printf("%s\r\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ? 00472 cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert); 00473 00474 printf("=== CERTIFICATE ISSUED BY ===\r\n"); 00475 printf("Common Name (CN):\t\t"); 00476 printf("%s\r\n", cert->ca_cert_dn[X509_COMMON_NAME] ? 00477 cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert); 00478 00479 printf("Organization (O):\t\t"); 00480 printf("%s\r\n", cert->ca_cert_dn[X509_ORGANIZATION] ? 00481 cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert); 00482 00483 printf("Organizational Unit (OU):\t"); 00484 printf("%s\r\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ? 00485 cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert); 00486 00487 printf("Not Before:\t\t\t%s\r\n", ctime(&cert->not_before)); 00488 printf("Not After:\t\t\t%s\r\n", ctime(&cert->not_after)); 00489 printf("RSA bitsize:\t\t\t%d\r\n", cert->rsa_ctx->num_octets*8); 00490 printf("Sig Type:\t\t\t"); 00491 switch (cert->sig_type) 00492 { 00493 case SIG_TYPE_MD5: 00494 printf("MD5\r\n"); 00495 break; 00496 case SIG_TYPE_SHA1: 00497 printf("SHA1\r\n"); 00498 break; 00499 case SIG_TYPE_MD2: 00500 printf("MD2\r\n"); 00501 break; 00502 default: 00503 printf("Unrecognized: %d\r\n", cert->sig_type); 00504 break; 00505 } 00506 00507 if (ca_cert_ctx) 00508 { 00509 // printf("Verify:\t\t\t\t%s\r\n", 00510 // x509_display_error(x509_verify(cert))); 00511 } 00512 00513 #if 0 00514 print_blob("Signature", cert->signature, cert->sig_len); 00515 bi_print("Modulus", cert->rsa_ctx->m); 00516 bi_print("Pub Exp", cert->rsa_ctx->e); 00517 #endif 00518 00519 if (ca_cert_ctx) 00520 { 00521 x509_print(cert->next, ca_cert_ctx); 00522 } 00523 00524 TTY_FLUSH(); 00525 } 00526 00527 const char * x509_display_error(int error) 00528 { 00529 switch (error) 00530 { 00531 case X509_OK: 00532 return "Certificate verify successful"; 00533 00534 case X509_NOT_OK: 00535 return "X509 not ok"; 00536 00537 case X509_VFY_ERROR_NO_TRUSTED_CERT: 00538 return "No trusted cert is available"; 00539 00540 case X509_VFY_ERROR_BAD_SIGNATURE: 00541 return "Bad signature"; 00542 00543 case X509_VFY_ERROR_NOT_YET_VALID: 00544 return "Cert is not yet valid"; 00545 00546 case X509_VFY_ERROR_EXPIRED: 00547 return "Cert has expired"; 00548 00549 case X509_VFY_ERROR_SELF_SIGNED: 00550 return "Cert is self-signed"; 00551 00552 case X509_VFY_ERROR_INVALID_CHAIN: 00553 return "Chain is invalid (check order of certs)"; 00554 00555 case X509_VFY_ERROR_UNSUPPORTED_DIGEST: 00556 return "Unsupported digest"; 00557 00558 case X509_INVALID_PRIV_KEY: 00559 return "Invalid private key"; 00560 00561 case X509_KEY_SIZE_TOO_BIG: 00562 return "Only keys less or equal to 1024 bits are supported"; 00563 00564 default: 00565 return "Unknown"; 00566 } 00567 } 00568 #endif /* CONFIG_SSL_FULL_MODE */ 00569 00570 00571
Generated on Wed Jul 13 2022 19:30:08 by 1.7.2