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