/** * Construct a new x509 object. * @return 0 if ok. < 0 if there was a problem. */ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) { int begin_tbs, end_tbs; int ret = X509_NOT_OK, offset = 0, cert_size = 0; X509_CTX *x509_ctx; BI_CTX *bi_ctx; *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX)); x509_ctx = *ctx; /* get the certificate size */ asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) goto end_cert; begin_tbs = offset; /* start of the tbs */ end_tbs = begin_tbs; /* work out the end of the tbs */ asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE); if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) goto end_cert; if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */ { if (asn1_version(cert, &offset, x509_ctx)) goto end_cert; } if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) goto end_cert; /* make sure the signature is ok */ if (asn1_signature_type(cert, &offset, x509_ctx)) { ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST; goto end_cert; } if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || asn1_validity(cert, &offset, x509_ctx) || asn1_name(cert, &offset, x509_ctx->cert_dn) || asn1_public_key(cert, &offset, x509_ctx)) { goto end_cert; } bi_ctx = x509_ctx->rsa_ctx->bi_ctx; x509_ctx->fingerprint = malloc(SHA1_SIZE); SHA1_CTX sha_fp_ctx; SHA1_Init(&sha_fp_ctx); SHA1_Update(&sha_fp_ctx, &cert[0], cert_size); SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx); #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ /* use the appropriate signature algorithm (SHA1/MD5/MD2) */ if (x509_ctx->sig_type == SIG_TYPE_MD5) { MD5_CTX md5_ctx; uint8_t md5_dgst[MD5_SIZE]; MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs); MD5_Final(md5_dgst, &md5_ctx); x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE); } else if (x509_ctx->sig_type == SIG_TYPE_SHA1) { SHA1_CTX sha_ctx; uint8_t sha_dgst[SHA1_SIZE]; SHA1_Init(&sha_ctx); SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs); SHA1_Final(sha_dgst, &sha_ctx); x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE); } else if (x509_ctx->sig_type == SIG_TYPE_MD2) { MD2_CTX md2_ctx; uint8_t md2_dgst[MD2_SIZE]; MD2_Init(&md2_ctx); MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs); MD2_Final(md2_dgst, &md2_ctx); x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE); } if (cert[offset] == ASN1_V3_DATA) { int suboffset; ++offset; get_asn1_length(cert, &offset); if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0) { if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0) { int altlen; if ((altlen = asn1_next_obj(cert, &suboffset, ASN1_SEQUENCE)) > 0) { int endalt = suboffset + altlen; int totalnames = 0; while (suboffset < endalt) { int type = cert[suboffset++]; int dnslen = get_asn1_length(cert, &suboffset); if (type == ASN1_CONTEXT_DNSNAME) { x509_ctx->subject_alt_dnsnames = (char**) realloc(x509_ctx->subject_alt_dnsnames, (totalnames + 2) * sizeof(char*)); x509_ctx->subject_alt_dnsnames[totalnames] = (char*)malloc(dnslen + 1); x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL; memcpy(x509_ctx->subject_alt_dnsnames[totalnames], cert + suboffset, dnslen); x509_ctx->subject_alt_dnsnames[ totalnames][dnslen] = 0; ++totalnames; } suboffset += dnslen; } } } } } offset = end_tbs; /* skip the rest of v3 data */ if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || asn1_signature(cert, &offset, x509_ctx)) goto end_cert; #endif ret = X509_OK; end_cert: if (len) { *len = cert_size; } if (ret) { #ifdef CONFIG_SSL_FULL_MODE printf("Error: Invalid X509 ASN.1 file (%s)\n", x509_display_error(ret)); #endif x509_free(x509_ctx); *ctx = NULL; } return ret; }
/** * Construct a new x509 object. * @return 0 if ok. < 0 if there was a problem. */ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) { int begin_tbs, end_tbs, begin_spki, end_spki; int ret = X509_NOT_OK, offset = 0, cert_size = 0; int version = 0; X509_CTX *x509_ctx; #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ BI_CTX *bi_ctx; #endif *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX)); x509_ctx = *ctx; /* get the certificate size */ asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) goto end_cert; begin_tbs = offset; /* start of the tbs */ end_tbs = begin_tbs; /* work out the end of the tbs */ asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE); if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) goto end_cert; /* optional version */ if (cert[offset] == ASN1_EXPLICIT_TAG && asn1_version(cert, &offset, &version) == X509_NOT_OK) goto end_cert; if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0) goto end_cert; /* make sure the signature is ok */ if (asn1_signature_type(cert, &offset, x509_ctx)) { ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST; goto end_cert; } if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || asn1_validity(cert, &offset, x509_ctx) || asn1_name(cert, &offset, x509_ctx->cert_dn)) { goto end_cert; } begin_spki = offset; if (asn1_public_key(cert, &offset, x509_ctx)) goto end_cert; end_spki = offset; x509_ctx->fingerprint = malloc(SHA1_SIZE); SHA1_CTX sha_fp_ctx; SHA1_Init(&sha_fp_ctx); SHA1_Update(&sha_fp_ctx, &cert[0], cert_size); SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx); x509_ctx->spki_sha256 = malloc(SHA256_SIZE); SHA256_CTX spki_hash_ctx; SHA256_Init(&spki_hash_ctx); SHA256_Update(&spki_hash_ctx, &cert[begin_spki], end_spki-begin_spki); SHA256_Final(x509_ctx->spki_sha256, &spki_hash_ctx); #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ bi_ctx = x509_ctx->rsa_ctx->bi_ctx; /* use the appropriate signature algorithm */ switch (x509_ctx->sig_type) { case SIG_TYPE_MD5: { MD5_CTX md5_ctx; uint8_t md5_dgst[MD5_SIZE]; MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs); MD5_Final(md5_dgst, &md5_ctx); x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE); } break; case SIG_TYPE_SHA1: { SHA1_CTX sha_ctx; uint8_t sha_dgst[SHA1_SIZE]; SHA1_Init(&sha_ctx); SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs); SHA1_Final(sha_dgst, &sha_ctx); x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE); } break; case SIG_TYPE_SHA256: { SHA256_CTX sha256_ctx; uint8_t sha256_dgst[SHA256_SIZE]; SHA256_Init(&sha256_ctx); SHA256_Update(&sha256_ctx, &cert[begin_tbs], end_tbs-begin_tbs); SHA256_Final(sha256_dgst, &sha256_ctx); x509_ctx->digest = bi_import(bi_ctx, sha256_dgst, SHA256_SIZE); } break; case SIG_TYPE_SHA384: { SHA384_CTX sha384_ctx; uint8_t sha384_dgst[SHA384_SIZE]; SHA384_Init(&sha384_ctx); SHA384_Update(&sha384_ctx, &cert[begin_tbs], end_tbs-begin_tbs); SHA384_Final(sha384_dgst, &sha384_ctx); x509_ctx->digest = bi_import(bi_ctx, sha384_dgst, SHA384_SIZE); } break; case SIG_TYPE_SHA512: { SHA512_CTX sha512_ctx; uint8_t sha512_dgst[SHA512_SIZE]; SHA512_Init(&sha512_ctx); SHA512_Update(&sha512_ctx, &cert[begin_tbs], end_tbs-begin_tbs); SHA512_Final(sha512_dgst, &sha512_ctx); x509_ctx->digest = bi_import(bi_ctx, sha512_dgst, SHA512_SIZE); } break; } if (version == 2 && asn1_next_obj(cert, &offset, ASN1_V3_DATA) > 0) { x509_v3_subject_alt_name(cert, offset, x509_ctx); x509_v3_basic_constraints(cert, offset, x509_ctx); x509_v3_key_usage(cert, offset, x509_ctx); } offset = end_tbs; /* skip the rest of v3 data */ if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || asn1_signature(cert, &offset, x509_ctx)) goto end_cert; /* Saves a few bytes of memory */ bi_clear_cache(bi_ctx); #endif ret = X509_OK; end_cert: if (len) { *len = cert_size; } if (ret) { #ifdef CONFIG_SSL_FULL_MODE char buff[64]; printf("Error: Invalid X509 ASN.1 file (%s)\n", x509_display_error(ret, buff)); #endif x509_free(x509_ctx); *ctx = NULL; } return ret; }
void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) { if (cert == NULL) return; printf("=== CERTIFICATE ISSUED TO ===\n"); printf("Common Name (CN):\t\t"); printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ? cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert); printf("Organization (O):\t\t"); printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ? cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert); printf("Organizational Unit (OU):\t"); printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ? cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert); printf("=== CERTIFICATE ISSUED BY ===\n"); printf("Common Name (CN):\t\t"); printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ? cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert); printf("Organization (O):\t\t"); printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ? cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert); printf("Organizational Unit (OU):\t"); printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ? cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert); printf("Not Before:\t\t\t%s", ctime(&cert->not_before)); printf("Not After:\t\t\t%s", ctime(&cert->not_after)); printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8); printf("Sig Type:\t\t\t"); switch (cert->sig_type) { case SIG_TYPE_MD5: printf("MD5\n"); break; case SIG_TYPE_SHA1: printf("SHA1\n"); break; case SIG_TYPE_MD2: printf("MD2\n"); break; default: printf("Unrecognized: %d\n", cert->sig_type); break; } if (ca_cert_ctx) { printf("Verify:\t\t\t\t%s\n", x509_display_error(x509_verify(ca_cert_ctx, cert))); } #if 0 print_blob("Signature", cert->signature, cert->sig_len); bi_print("Modulus", cert->rsa_ctx->m); bi_print("Pub Exp", cert->rsa_ctx->e); #endif if (ca_cert_ctx) { x509_print(cert->next, ca_cert_ctx); } TTY_FLUSH(); }
void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) { if (cert == NULL) return; printf("=== CERTIFICATE ISSUED TO ===\n"); printf("Common Name (CN):\t\t"); printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ? cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert); printf("Organization (O):\t\t"); printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ? cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert); if (cert->cert_dn[X509_ORGANIZATIONAL_UNIT]) { printf("Organizational Unit (OU):\t"); printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT]); } if (cert->cert_dn[X509_LOCATION]) { printf("Location (L):\t\t\t"); printf("%s\n", cert->cert_dn[X509_LOCATION]); } if (cert->cert_dn[X509_COUNTRY]) { printf("Country (C):\t\t\t"); printf("%s\n", cert->cert_dn[X509_COUNTRY]); } if (cert->cert_dn[X509_STATE]) { printf("State (ST):\t\t\t"); printf("%s\n", cert->cert_dn[X509_STATE]); } if (cert->basic_constraint_present) { printf("Basic Constraints:\t\t%sCA:%s, pathlen:%d\n", cert->basic_constraint_is_critical ? "critical, " : "", cert->basic_constraint_cA? "TRUE" : "FALSE", cert->basic_constraint_pathLenConstraint); } if (cert->key_usage_present) { printf("Key Usage:\t\t\t%s", cert->key_usage_is_critical ? "critical, " : ""); bool has_started = false; if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_DIGITAL_SIGNATURE)) { printf("Digital Signature"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_NON_REPUDIATION)) { if (has_started) printf(", "); printf("Non Repudiation"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_ENCIPHERMENT)) { if (has_started) printf(", "); printf("Key Encipherment"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_DATA_ENCIPHERMENT)) { if (has_started) printf(", "); printf("Data Encipherment"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_AGREEMENT)) { if (has_started) printf(", "); printf("Key Agreement"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_CERT_SIGN)) { if (has_started) printf(", "); printf("Key Cert Sign"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_CRL_SIGN)) { if (has_started) printf(", "); printf("CRL Sign"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_ENCIPHER_ONLY)) { if (has_started) printf(", "); printf("Encipher Only"); has_started = true; } if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_DECIPHER_ONLY)) { if (has_started) printf(", "); printf("Decipher Only"); has_started = true; } printf("\n"); } if (cert->subject_alt_name_present) { printf("Subject Alt Name:\t\t%s", cert->subject_alt_name_is_critical ? "critical, " : ""); if (cert->subject_alt_dnsnames) { int i = 0; while (cert->subject_alt_dnsnames[i]) printf("%s ", cert->subject_alt_dnsnames[i++]); } printf("\n"); } printf("=== CERTIFICATE ISSUED BY ===\n"); printf("Common Name (CN):\t\t"); printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ? cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert); printf("Organization (O):\t\t"); printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ? cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert); if (cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT]) { printf("Organizational Unit (OU):\t"); printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT]); } if (cert->ca_cert_dn[X509_LOCATION]) { printf("Location (L):\t\t\t"); printf("%s\n", cert->ca_cert_dn[X509_LOCATION]); } if (cert->ca_cert_dn[X509_COUNTRY]) { printf("Country (C):\t\t\t"); printf("%s\n", cert->ca_cert_dn[X509_COUNTRY]); } if (cert->ca_cert_dn[X509_STATE]) { printf("State (ST):\t\t\t"); printf("%s\n", cert->ca_cert_dn[X509_STATE]); } printf("Not Before:\t\t\t%s", ctime(&cert->not_before)); printf("Not After:\t\t\t%s", ctime(&cert->not_after)); printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8); printf("Sig Type:\t\t\t"); switch (cert->sig_type) { case SIG_TYPE_MD5: printf("MD5\n"); break; case SIG_TYPE_SHA1: printf("SHA1\n"); break; case SIG_TYPE_SHA256: printf("SHA256\n"); break; case SIG_TYPE_SHA384: printf("SHA384\n"); break; case SIG_TYPE_SHA512: printf("SHA512\n"); break; default: printf("Unrecognized: %d\n", cert->sig_type); break; } if (ca_cert_ctx) { int pathLenConstraint = 0; char buff[64]; printf("Verify:\t\t\t\t%s\n", x509_display_error(x509_verify(ca_cert_ctx, cert, &pathLenConstraint), buff)); } #if 0 print_blob("Signature", cert->signature, cert->sig_len); bi_print("Modulus", cert->rsa_ctx->m); bi_print("Pub Exp", cert->rsa_ctx->e); #endif if (ca_cert_ctx) { x509_print(cert->next, ca_cert_ctx); } TTY_FLUSH(); }