/** * destroy function */ static void mod_destroy(void) { if(privKey_evp) { EVP_PKEY_free(privKey_evp); } if(store) { X509_STORE_free(store); } if(verify_ctx) { X509_STORE_CTX_free(verify_ctx); } EVP_cleanup(); if((verCert != verCertWithSlash) && verCertWithSlash) { pkg_free(verCertWithSlash); } }
/* This function makes sure the certificate is still valid by not having any * compromised certificates in the chain. * If there is no Certificate Revocation List (CRL) it may be that the private * keys have not been compromised or the CRL has not been generated by the * Certificate Authority (CA) * * returns: 0 if certificate is valid, X509 store error code otherwise */ static int validate_certificate(void) { X509_LOOKUP *lookup = NULL; X509_STORE_CTX *verify_ctx = NULL; /* TODO: CRL and Chains are not required for the current setup, but we may * implement them in the future if (!crl) { printf("No certificate revocation list provided\n"); } if (!chain) { printf("No certificate chain provided\n"); } */ /* create the cert store and set the verify callback */ if (!(store = X509_STORE_new())) { fprintf(stderr, "Failed X509_STORE_new() for %s\n", CERTNAME); goto error; } X509_STORE_set_verify_cb_func(store, verify_callback); /* Add the certificates to be verified to the store */ if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) { fprintf(stderr, "Failed X509_STORE_add_lookup() for %s\n", CERTNAME); goto error; } /* Load the our Root cert, which can be in either DER or PEM format */ if (!X509_load_cert_file(lookup, CERTNAME, X509_FILETYPE_PEM)) { fprintf(stderr, "Failed X509_load_cert_file() for %s\n", CERTNAME); goto error; } if (crl) { if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) || (X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) { fprintf(stderr, "Failed X509 crl init for %s\n", CERTNAME); goto error; } /* set the flags of the store so that CLRs are consulted */ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* create a verification context and initialize it */ if (!(verify_ctx = X509_STORE_CTX_new())) { fprintf(stderr, "Failed X509_STORE_CTX_new() for %s\n", CERTNAME); goto error; } if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) { fprintf(stderr, "Failed X509_STORE_CTX_init() for %s\n", CERTNAME); goto error; } /* Specify which cert to validate in the verify context. * This is required because we may add multiple certs to the X509 store, * but we want to validate a specific one out of the group/chain. */ X509_STORE_CTX_set_cert(verify_ctx, cert); /* verify the certificate */ if (X509_verify_cert(verify_ctx) != 1) { fprintf(stderr, "Failed X509_verify_cert() for %s\n", CERTNAME); goto error; } X509_STORE_CTX_free(verify_ctx); /* Certificate verified correctly */ return 0; error: ERR_print_errors_fp(stderr); if (verify_ctx) { X509_STORE_CTX_free(verify_ctx); } return verify_ctx->error; }
/* This function makes sure the certificate is still valid by not having any * compromised certificates in the chain. * If there is no Certificate Revocation List (CRL) it may be that the private * keys have not been compromised or the CRL has not been generated by the * Certificate Authority (CA) * * returns: 0 if certificate is valid, X509 store error code otherwise */ static int validate_certificate(X509 *cert, const char *certificate_path, const char *crl) { X509_LOOKUP *lookup = NULL; X509_STORE_CTX *verify_ctx = NULL; //TODO: Implement a chain verification when required /* create the cert store and set the verify callback */ if (!(store = X509_STORE_new())) { error("Failed X509_STORE_new() for %s\n", certificate_path); goto error; } X509_STORE_set_verify_cb_func(store, verify_callback); if (X509_STORE_set_purpose(store, X509_PURPOSE_ANY) != 1) { error("Failed X509_STORE_set_purpose() for %s\n", certificate_path); goto error; } /* Add the certificates to be verified to the store */ if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) { error("Failed X509_STORE_add_lookup() for %s\n", certificate_path); goto error; } /* Load the our Root cert, which can be in either DER or PEM format */ if (!X509_load_cert_file(lookup, certificate_path, X509_FILETYPE_PEM)) { error("Failed X509_load_cert_file() for %s\n", certificate_path); goto error; } if (crl) { if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) || (X509_load_crl_file(lookup, crl, X509_FILETYPE_PEM) != 1)) { error("Failed X509 crl init for %s\n", certificate_path); goto error; } /* set the flags of the store so that CLRs are consulted */ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* create a verification context and initialize it */ if (!(verify_ctx = X509_STORE_CTX_new())) { error("Failed X509_STORE_CTX_new() for %s\n", certificate_path); goto error; } if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) { error("Failed X509_STORE_CTX_init() for %s\n", certificate_path); goto error; } /* Specify which cert to validate in the verify context. * This is required because we may add multiple certs to the X509 store, * but we want to validate a specific one out of the group/chain. */ X509_STORE_CTX_set_cert(verify_ctx, cert); /* verify the certificate */ if (X509_verify_cert(verify_ctx) != 1) { error("Failed X509_verify_cert() for %s\n", certificate_path); goto error; } X509_STORE_CTX_free(verify_ctx); if (validate_authority(cert) < 0) { error("Failed to validate certificate using 'Authority Information Access'\n"); return -1; } /* Certificate verified correctly */ return 0; error: ERR_print_errors_fp(stderr); if (verify_ctx) { X509_STORE_CTX_free(verify_ctx); } return X509_STORE_CTX_get_error(verify_ctx); }
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const { merchant.clear(); if (!IsInitialized()) return false; // One day we'll support more PKI types, but just // x509 for now: const EVP_MD* digestAlgorithm = NULL; if (paymentRequest.pki_type() == "x509+sha256") { digestAlgorithm = EVP_sha256(); } else if (paymentRequest.pki_type() == "x509+sha1") { digestAlgorithm = EVP_sha1(); } else if (paymentRequest.pki_type() == "none") { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none"; return false; } else { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type()); return false; } payments::X509Certificates certChain; if (!certChain.ParseFromString(paymentRequest.pki_data())) { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data"; return false; } std::vector<X509*> certs; const QDateTime currentTime = QDateTime::currentDateTime(); for (int i = 0; i < certChain.certificate_size(); i++) { QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size()); QSslCertificate qCert(certData, QSsl::Der); if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert; return false; } #if QT_VERSION >= 0x050000 if (qCert.isBlacklisted()) { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert; return false; } #endif const unsigned char *data = (const unsigned char *)certChain.certificate(i).data(); X509 *cert = d2i_X509(NULL, &data, certChain.certificate(i).size()); if (cert) certs.push_back(cert); } if (certs.empty()) { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain"; return false; } // The first cert is the signing cert, the rest are untrusted certs that chain // to a valid root authority. OpenSSL needs them separately. STACK_OF(X509) *chain = sk_X509_new_null(); for (int i = certs.size()-1; i > 0; i--) { sk_X509_push(chain, certs[i]); } X509 *signing_cert = certs[0]; // Now create a "store context", which is a single use object for checking, // load the signing cert into it and verify. X509_STORE_CTX *store_ctx = X509_STORE_CTX_new(); if (!store_ctx) { qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX"; return false; } char *website = NULL; bool fResult = true; try { if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain)) { int error = X509_STORE_CTX_get_error(store_ctx); throw SSLVerifyError(X509_verify_cert_error_string(error)); } // Now do the verification! int result = X509_verify_cert(store_ctx); if (result != 1) { int error = X509_STORE_CTX_get_error(store_ctx); throw SSLVerifyError(X509_verify_cert_error_string(error)); } X509_NAME *certname = X509_get_subject_name(signing_cert); // Valid cert; check signature: payments::PaymentRequest rcopy(paymentRequest); // Copy rcopy.set_signature(std::string("")); std::string data_to_verify; // Everything but the signature rcopy.SerializeToString(&data_to_verify); EVP_MD_CTX ctx; EVP_PKEY *pubkey = X509_get_pubkey(signing_cert); EVP_MD_CTX_init(&ctx); if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) || !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) || !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) { throw SSLVerifyError("Bad signature, invalid PaymentRequest."); } // OpenSSL API for getting human printable strings from certs is baroque. int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0); website = new char[textlen + 1]; if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) { merchant = website; } else { throw SSLVerifyError("Bad certificate, missing common name."); } // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ? } catch (SSLVerifyError& err) { fResult = false; qDebug() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what(); } if (website) delete[] website; X509_STORE_CTX_free(store_ctx); for (unsigned int i = 0; i < certs.size(); i++) X509_free(certs[i]); return fResult; }
static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) { int i, n, rc; X509 *cert, *issuer; X509_STORE *store; X509_STORE_CTX *store_ctx; STACK_OF(X509) *chain; ngx_ssl_stapling_t *staple; staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else chain = ssl->ctx->extra_certs; #endif n = sk_X509_num(chain); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: %d extra certs", n); for (i = 0; i < n; i++) { issuer = sk_X509_value(chain, i); if (X509_check_issued(issuer, cert) == X509_V_OK) { #if OPENSSL_VERSION_NUMBER >= 0x10100001L X509_up_ref(issuer); #else CRYPTO_add(&issuer->references, 1, CRYPTO_LOCK_X509); #endif ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); staple->cert = cert; staple->issuer = issuer; return NGX_OK; } } store = SSL_CTX_get_cert_store(ssl->ctx); if (store == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_get_cert_store() failed"); return NGX_ERROR; } store_ctx = X509_STORE_CTX_new(); if (store_ctx == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_new() failed"); return NGX_ERROR; } if (X509_STORE_CTX_init(store_ctx, store, NULL, NULL) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_init() failed"); X509_STORE_CTX_free(store_ctx); return NGX_ERROR; } rc = X509_STORE_CTX_get1_issuer(&issuer, store_ctx, cert); if (rc == -1) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_STORE_CTX_get1_issuer() failed"); X509_STORE_CTX_free(store_ctx); return NGX_ERROR; } if (rc == 0) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, issuer certificate not found"); X509_STORE_CTX_free(store_ctx); return NGX_DECLINED; } X509_STORE_CTX_free(store_ctx); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in cert store", issuer); staple->cert = cert; staple->issuer = issuer; return NGX_OK; }
/*============================================================================ * OpcUa_P_OpenSSL_PKI_ValidateCertificate *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ValidateCertificate( OpcUa_PKIProvider* a_pProvider, OpcUa_ByteString* a_pCertificate, OpcUa_Void* a_pCertificateStore, OpcUa_Int* a_pValidationCode /* Validation return codes from OpenSSL */ ) { OpcUa_P_OpenSSL_CertificateStore_Config* pCertificateStoreCfg; const unsigned char* p; X509* pX509Certificate = OpcUa_Null; STACK_OF(X509)* pX509Chain = OpcUa_Null; X509_STORE_CTX* verify_ctx = OpcUa_Null; /* holds data used during verification process */ char CertFile[MAX_PATH]; struct dirent **dirlist = NULL; int numCertificates = 0, i; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ValidateCertificate"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore); OpcUa_ReturnErrorIfArgumentNull(a_pValidationCode); pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle; /* convert DER encoded bytestring certificate to openssl X509 certificate */ p = a_pCertificate->Data; if(!(pX509Certificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } while(p < a_pCertificate->Data + a_pCertificate->Length) { X509* pX509AddCertificate; if(!(pX509AddCertificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Data + a_pCertificate->Length - p))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pX509Chain == NULL) { pX509Chain = sk_X509_new_null(); OpcUa_GotoErrorIfAllocFailed(pX509Chain); } if(!sk_X509_push(pX509Chain, pX509AddCertificate)) { X509_free(pX509AddCertificate); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } /* create verification context and initialize it */ if(!(verify_ctx = X509_STORE_CTX_new())) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } #if (OPENSSL_VERSION_NUMBER > 0x00907000L) if(X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } #else X509_STORE_CTX_init(verify_ctx, (X509_STORE*)a_pCertificateStore, pX509Certificate, pX509Chain); #endif if(X509_STORE_CTX_set_app_data(verify_ctx, pCertificateStoreCfg) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL_EXCEPT_SELF_SIGNED && !verify_ctx->check_issued(verify_ctx, pX509Certificate, pX509Certificate)) { /* set the flags of the store so that CRLs are consulted */ X509_STORE_CTX_set_flags(verify_ctx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } /* verify the certificate */ *a_pValidationCode = X509_V_OK; if(X509_verify_cert(verify_ctx) <= 0) { *a_pValidationCode = verify_ctx->error; switch(verify_ctx->error) { case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: { uStatus = OpcUa_BadCertificateTimeInvalid; break; } case X509_V_ERR_CERT_REVOKED: { uStatus = OpcUa_BadCertificateRevoked; break; } case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: { uStatus = OpcUa_BadCertificateUntrusted; break; } case X509_V_ERR_CERT_SIGNATURE_FAILURE: { uStatus = OpcUa_BadSecurityChecksFailed; break; } default: { uStatus = OpcUa_BadCertificateInvalid; } } OpcUa_GotoErrorIfBad(uStatus); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REQUIRE_CHAIN_CERTIFICATE_IN_TRUST_LIST) { FILE* pCertificateFile; X509* pTrustCert; STACK_OF(X509)* chain; int trusted, n; chain = X509_STORE_CTX_get_chain(verify_ctx); trusted = 0; if(pCertificateStoreCfg->CertificateTrustListLocation == NULL || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0') { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* read DER certificates */ pCertificateFile = fopen(CertFile, "r"); if(pCertificateFile == OpcUa_Null) { continue; /* ignore access errors */ } pTrustCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null); fclose(pCertificateFile); if(pTrustCert == OpcUa_Null) { continue; /* ignore parse errors */ } for(n = 0; n < sk_X509_num(chain); n++) { if (X509_cmp(sk_X509_value(chain, n), pTrustCert) == 0) break; } X509_free(pTrustCert); if(n < sk_X509_num(chain)) { trusted = 1; break; } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; if(!trusted) { uStatus = OpcUa_BadCertificateUntrusted; OpcUa_GotoErrorIfBad(uStatus); } } X509_STORE_CTX_free(verify_ctx); X509_free(pX509Certificate); if(pX509Chain != OpcUa_Null) { sk_X509_pop_free(pX509Chain, X509_free); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(dirlist != NULL) { for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); } if(verify_ctx != OpcUa_Null) { X509_STORE_CTX_free(verify_ctx); } if(pX509Certificate != OpcUa_Null) { X509_free(pX509Certificate); } if(pX509Chain != OpcUa_Null) { sk_X509_pop_free(pX509Chain, X509_free); } OpcUa_FinishErrorHandling; }
int crl_main(int argc, char **argv) { X509_CRL *x = NULL; BIO *out = NULL; X509_STORE *store = NULL; X509_STORE_CTX *ctx = NULL; X509_LOOKUP *lookup = NULL; X509_OBJECT *xobj = NULL; EVP_PKEY *pkey; const EVP_MD *digest = EVP_sha1(); unsigned long nmflag = 0; char nmflag_set = 0; char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL; const char *CAfile = NULL, *CApath = NULL, *prog; OPTION_CHOICE o; int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; int ret = 1, num = 0, badsig = 0, fingerprint = 0, crlnumber = 0; int text = 0, do_ver = 0, noCAfile = 0, noCApath = 0; int i; #ifndef OPENSSL_NO_MD5 int hash_old = 0; #endif prog = opt_init(argc, argv, crl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(crl_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) goto opthelp; break; case OPT_KEY: keyfile = opt_arg(); break; case OPT_GENDELTA: crldiff = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); do_ver = 1; break; case OPT_CAFILE: CAfile = opt_arg(); do_ver = 1; break; case OPT_NOCAPATH: noCApath = 1; break; case OPT_NOCAFILE: noCAfile = 1; break; case OPT_HASH_OLD: #ifndef OPENSSL_NO_MD5 hash_old = ++num; #endif break; case OPT_VERIFY: do_ver = 1; break; case OPT_TEXT: text = 1; break; case OPT_HASH: hash = ++num; break; case OPT_ISSUER: issuer = ++num; break; case OPT_LASTUPDATE: lastupdate = ++num; break; case OPT_NEXTUPDATE: nextupdate = ++num; break; case OPT_NOOUT: noout = ++num; break; case OPT_FINGERPRINT: fingerprint = ++num; break; case OPT_CRLNUMBER: crlnumber = ++num; break; case OPT_BADSIG: badsig = 1; break; case OPT_NAMEOPT: nmflag_set = 1; if (!set_name_ex(&nmflag, opt_arg())) goto opthelp; break; case OPT_MD: if (!opt_md(opt_unknown(), &digest)) goto opthelp; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; if (!nmflag_set) nmflag = XN_FLAG_ONELINE; x = load_crl(infile, informat); if (x == NULL) goto end; if (do_ver) { if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL) goto end; lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (lookup == NULL) goto end; ctx = X509_STORE_CTX_new(); if (ctx == NULL || !X509_STORE_CTX_init(ctx, store, NULL, NULL)) { BIO_printf(bio_err, "Error initialising X509 store\n"); goto end; } xobj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, X509_CRL_get_issuer(x)); if (xobj == NULL) { BIO_printf(bio_err, "Error getting CRL issuer certificate\n"); goto end; } pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); X509_OBJECT_free(xobj); if (!pkey) { BIO_printf(bio_err, "Error getting CRL issuer public key\n"); goto end; } i = X509_CRL_verify(x, pkey); EVP_PKEY_free(pkey); if (i < 0) goto end; if (i == 0) BIO_printf(bio_err, "verify failure\n"); else BIO_printf(bio_err, "verify OK\n"); } if (crldiff) { X509_CRL *newcrl, *delta; if (!keyfile) { BIO_puts(bio_err, "Missing CRL signing key\n"); goto end; } newcrl = load_crl(crldiff, informat); if (!newcrl) goto end; pkey = load_key(keyfile, keyformat, 0, NULL, NULL, "CRL signing key"); if (!pkey) { X509_CRL_free(newcrl); goto end; } delta = X509_CRL_diff(x, newcrl, pkey, digest, 0); X509_CRL_free(newcrl); EVP_PKEY_free(pkey); if (delta) { X509_CRL_free(x); x = delta; } else { BIO_puts(bio_err, "Error creating delta CRL\n"); goto end; } } if (badsig) { const ASN1_BIT_STRING *sig; X509_CRL_get0_signature(x, &sig, NULL); corrupt_signature(sig); } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(bio_out, "issuer=", X509_CRL_get_issuer(x), nmflag); } if (crlnumber == i) { ASN1_INTEGER *crlnum; crlnum = X509_CRL_get_ext_d2i(x, NID_crl_number, NULL, NULL); BIO_printf(bio_out, "crlNumber="); if (crlnum) { i2a_ASN1_INTEGER(bio_out, crlnum); ASN1_INTEGER_free(crlnum); } else BIO_puts(bio_out, "<NONE>"); BIO_printf(bio_out, "\n"); } if (hash == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash(X509_CRL_get_issuer(x))); } #ifndef OPENSSL_NO_MD5 if (hash_old == i) { BIO_printf(bio_out, "%08lx\n", X509_NAME_hash_old(X509_CRL_get_issuer(x))); } #endif if (lastupdate == i) { BIO_printf(bio_out, "lastUpdate="); ASN1_TIME_print(bio_out, X509_CRL_get0_lastUpdate(x)); BIO_printf(bio_out, "\n"); } if (nextupdate == i) { BIO_printf(bio_out, "nextUpdate="); if (X509_CRL_get0_nextUpdate(x)) ASN1_TIME_print(bio_out, X509_CRL_get0_nextUpdate(x)); else BIO_printf(bio_out, "NONE"); BIO_printf(bio_out, "\n"); } if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!X509_CRL_digest(x, digest, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(bio_out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(digest))); for (j = 0; j < (int)n; j++) { BIO_printf(bio_out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } } } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (text) X509_CRL_print(out, x); if (noout) { ret = 0; goto end; } if (outformat == FORMAT_ASN1) i = (int)i2d_X509_CRL_bio(out, x); else i = PEM_write_bio_X509_CRL(out, x); if (!i) { BIO_printf(bio_err, "unable to write CRL\n"); goto end; } ret = 0; end: if (ret != 0) ERR_print_errors(bio_err); BIO_free_all(out); X509_CRL_free(x); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return (ret); }
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) { CMS_ContentInfo *cms = NULL; STACK_OF(X509) *signers = NULL; STACK_OF(X509) *intercerts = NULL; X509_STORE *cert_store = NULL; X509_LOOKUP *lookup = NULL; X509_STORE_CTX *store_ctx = NULL; BIO *message_bio = NULL; BIO *signature_bio = NULL; BUF_MEM *buf_mem = NULL; int32_t signer_count = 0; int32_t result = 0; int32_t i = 0; int32_t err = MZ_SIGN_ERROR; if (message == NULL || message_size == 0 || signature == NULL || signature_size == 0) return MZ_PARAM_ERROR; mz_crypt_init(); cert_store = X509_STORE_new(); X509_STORE_load_locations(cert_store, "cacert.pem", NULL); X509_STORE_set_default_paths(cert_store); #if 0 BIO *yy = BIO_new_file("xyz", "wb"); BIO_write(yy, signature, signature_size); BIO_flush(yy); BIO_free(yy); #endif lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file()); if (lookup != NULL) X509_LOOKUP_load_file(lookup, "cacert.pem", X509_FILETYPE_PEM); lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_hash_dir()); if (lookup != NULL) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); signature_bio = BIO_new_mem_buf(signature, signature_size); message_bio = BIO_new(BIO_s_mem()); cms = d2i_CMS_bio(signature_bio, NULL); if (cms) { result = CMS_verify(cms, NULL, cert_store, NULL, message_bio, CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY); if (result) signers = CMS_get0_signers(cms); if (signers) intercerts = CMS_get1_certs(cms); if (intercerts) { /* Verify signer certificates */ signer_count = sk_X509_num(signers); if (signer_count > 0) err = MZ_OK; for (i = 0; i < signer_count; i++) { store_ctx = X509_STORE_CTX_new(); X509_STORE_CTX_init(store_ctx, cert_store, sk_X509_value(signers, i), intercerts); result = X509_verify_cert(store_ctx); if (store_ctx) X509_STORE_CTX_free(store_ctx); if (!result) { err = MZ_SIGN_ERROR; break; } } } BIO_get_mem_ptr(message_bio, &buf_mem); if (err == MZ_OK) { /* Verify the message */ if (((int32_t)buf_mem->length != message_size) || (memcmp(buf_mem->data, message, message_size) != 0)) err = MZ_SIGN_ERROR; } } #if 0 if (!result) printf(ERR_error_string(ERR_get_error(), NULL)); #endif if (cms) CMS_ContentInfo_free(cms); if (message_bio) BIO_free(message_bio); if (signature_bio) BIO_free(signature_bio); if (cert_store) X509_STORE_free(cert_store); return err; }
int check_validity_of_cert( const char *cFile, const unsigned char *md5_md, unsigned char *sfileMsg, const int sfsize, const char* caPath ) { int retval = 0; X509 *cert; X509_STORE *store; X509_LOOKUP *lookup; X509_STORE_CTX *ctx = 0; EVP_PKEY *pubKey; BIO *bio; bio = BIO_new(BIO_s_file()); BIO_read_filename(bio, cFile); if (NULL == (cert = PEM_read_bio_X509(bio, NULL, 0, NULL))) { BIO_vfree(bio); return 0; } // verify certificate store = X509_STORE_new(); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); X509_LOOKUP_add_dir(lookup, (char *)caPath, X509_FILETYPE_PEM); if ((ctx = X509_STORE_CTX_new()) != 0) { if (X509_STORE_CTX_init(ctx, store, cert, 0) == 1) retval = X509_verify_cert(ctx); X509_STORE_CTX_free(ctx); } X509_STORE_free(store); if (retval != 1) { fprintf(stderr,"ERROR: Cannot verify certificate ('%s')\n", cFile); return 0; } pubKey = X509_get_pubkey(cert); if (!pubKey) { X509_free(cert); BIO_vfree(bio); return 0; } if (pubKey->type == EVP_PKEY_RSA) { BN_CTX *c = BN_CTX_new(); if (!c) { X509_free(cert); EVP_PKEY_free(pubKey); BIO_vfree(bio); return 0; } if (!RSA_blinding_on(pubKey->pkey.rsa, c)) { X509_free(cert); EVP_PKEY_free(pubKey); BIO_vfree(bio); BN_CTX_free(c); return 0; } retval = RSA_verify(NID_md5, md5_md, MD5_DIGEST_LENGTH, sfileMsg, sfsize, pubKey->pkey.rsa); RSA_blinding_off(pubKey->pkey.rsa); BN_CTX_free(c); } if (pubKey->type == EVP_PKEY_DSA) { fprintf(stderr, "ERROR: DSA keys are not supported.\n"); return 0; } EVP_PKEY_free(pubKey); X509_free(cert); BIO_vfree(bio); return retval; }
/** * xmlSecOpenSSLX509StoreVerify: * @store: the pointer to X509 key data store klass. * @certs: the untrusted certificates stack. * @crls: the crls stack. * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. * * Verifies @certs list. * * Returns: pointer to the first verified certificate from @certs. */ X509* xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs, XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) { xmlSecOpenSSLX509StoreCtxPtr ctx; STACK_OF(X509)* certs2 = NULL; STACK_OF(X509_CRL)* crls2 = NULL; X509 * res = NULL; X509 * cert; X509 * err_cert = NULL; X509_STORE_CTX *xsc; char buf[256]; int err = 0; int i; int ret; xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL); xmlSecAssert2(certs != NULL, NULL); xmlSecAssert2(keyInfoCtx != NULL, NULL); xsc = X509_STORE_CTX_new(); if(xsc == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_STORE_CTX_new"); goto done; } ctx = xmlSecOpenSSLX509StoreGetCtx(store); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->xst != NULL, NULL); /* dup certs */ certs2 = sk_X509_dup(certs); if(certs2 == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_dup"); goto done; } /* add untrusted certs from the store */ if(ctx->untrusted != NULL) { for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) { ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i)); if(ret < 1) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_push"); goto done; } } } /* dup crls but remove all non-verified */ if(crls != NULL) { crls2 = sk_X509_CRL_dup(crls); if(crls2 == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_CRL_dup"); goto done; } for(i = 0; i < sk_X509_CRL_num(crls2); ) { ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i)); if(ret == 1) { ++i; } else if(ret == 0) { (void)sk_X509_CRL_delete(crls2, i); } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCRL", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } } /* remove all revoked certs */ for(i = 0; i < sk_X509_num(certs2);) { cert = sk_X509_value(certs2, i); if(crls2 != NULL) { ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert); if(ret == 0) { (void)sk_X509_delete(certs2, i); continue; } else if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCertAgainstCrls", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } if(ctx->crls != NULL) { ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert); if(ret == 0) { (void)sk_X509_delete(certs2, i); continue; } else if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCertAgainstCrls", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } ++i; } /* get one cert after another and try to verify */ for(i = 0; i < sk_X509_num(certs2); ++i) { cert = sk_X509_value(certs2, i); if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) { ret = X509_STORE_CTX_init(xsc, ctx->xst, cert, certs2); if(ret != 1) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_STORE_CTX_init"); goto done; } if(keyInfoCtx->certsVerificationTime > 0) { X509_STORE_CTX_set_time(xsc, 0, keyInfoCtx->certsVerificationTime); } { X509_VERIFY_PARAM * vpm = NULL; unsigned long vpm_flags = 0; vpm = X509_VERIFY_PARAM_new(); if(vpm == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_VERIFY_PARAM_new"); goto done; } vpm_flags = X509_VERIFY_PARAM_get_flags(vpm); vpm_flags &= (~X509_V_FLAG_CRL_CHECK); if(keyInfoCtx->certsVerificationTime > 0) { vpm_flags |= X509_V_FLAG_USE_CHECK_TIME; X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime); } X509_VERIFY_PARAM_set_depth(vpm, keyInfoCtx->certsVerificationDepth); X509_VERIFY_PARAM_set_flags(vpm, vpm_flags); X509_STORE_CTX_set0_param(xsc, vpm); } ret = X509_verify_cert(xsc); err_cert = X509_STORE_CTX_get_current_cert(xsc); err = X509_STORE_CTX_get_error(xsc); X509_STORE_CTX_cleanup (xsc); if(ret == 1) { res = cert; goto done; } else if(ret < 0) { const char* err_msg; buf[0] = '\0'; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); err_msg = X509_verify_cert_error_string(err); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_verify_cert", XMLSEC_ERRORS_R_CRYPTO_FAILED, "subj=%s;err=%d;msg=%s", xmlSecErrorsSafeString(buf), err, xmlSecErrorsSafeString(err_msg)); goto done; } else if(ret == 0) { const char* err_msg; buf[0] = '\0'; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); err_msg = X509_verify_cert_error_string(err); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_verify_cert", XMLSEC_ERRORS_R_CRYPTO_FAILED, "subj=%s;err=%d;msg=%s", xmlSecErrorsSafeString(buf), err, xmlSecErrorsSafeString(err_msg)); } } } /* if we came here then we found nothing. do we have any error? */ if((err != 0) && (err_cert != NULL)) { const char* err_msg; err_msg = X509_verify_cert_error_string(err); switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "err=%d;msg=%s;issuer=%s", err, xmlSecErrorsSafeString(err_msg), xmlSecErrorsSafeString(buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); break; default: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); } } done: if(certs2 != NULL) { sk_X509_free(certs2); } if(crls2 != NULL) { sk_X509_CRL_free(crls2); } if(xsc != NULL) { X509_STORE_CTX_free(xsc); } return(res); }
void openssl_x509_verify() { FILE *fp; int uCert1Len; X509_CRL *Crl = NULL; X509_STORE_CTX *ctx = NULL; X509_STORE *rootCertStore = NULL; STACK_OF(X509) * caCertStack = NULL; X509 *usrCert1 = NULL, *usrCert2 = NULL, *rootCert = NULL; unsigned char tmp[MAX4_LEN]; unsigned long uCert2Len, derCrlLen, derRootCertLen; const unsigned char *derCrl, *derRootCert, *uCert1, *uCert2; OpenSSL_add_all_algorithms(); printf("\nX509_Verify info:\n"); fp = fopen(RCERTF, "rb"); derRootCertLen = fread(tmp, 1, 4096, fp); derRootCert = tmp; fclose(fp); rootCert = d2i_X509(NULL, &derRootCert, derRootCertLen); fp = fopen(CRLCRL, "rb"); derCrlLen = fread(tmp, 1, 4096, fp); derCrl = tmp; fclose(fp); Crl = d2i_X509_CRL(NULL, &derCrl, derCrlLen); rootCertStore = X509_STORE_new(); X509_STORE_add_cert(rootCertStore, rootCert); X509_STORE_set_flags(rootCertStore, X509_V_FLAG_CRL_CHECK); X509_STORE_add_crl(rootCertStore, Crl); ctx = X509_STORE_CTX_new(); fp = fopen(U1CERTF, "rb"); uCert1Len = fread(tmp, 1, 4096, fp); uCert1 = tmp; fclose(fp); usrCert1 = d2i_X509(NULL, &uCert1, uCert1Len); if (X509_STORE_CTX_init(ctx, rootCertStore, usrCert1, caCertStack) != 1) { perror("X509_STORE_CTX_init"); return; } if (X509_verify_cert(ctx) != 1) { printf("user1.cer %s\n", X509_verify_cert_error_string(ctx->error)); return; } fp = fopen(U2CERTF, "rb"); uCert2Len = fread(tmp, 1, 4096, fp); uCert2 = tmp; fclose(fp); usrCert2 = d2i_X509(NULL, &uCert2, uCert2Len); if (X509_STORE_CTX_init(ctx, rootCertStore, usrCert2, caCertStack) != 1) { perror("X509_STORE_CTX_init"); return; } if (X509_verify_cert(ctx) != 1) { printf("user2.cer %s\n", X509_verify_cert_error_string(ctx->error)); return; } X509_free(usrCert1); X509_free(usrCert2); X509_free(rootCert); X509_STORE_CTX_cleanup(ctx); X509_STORE_CTX_free(ctx); X509_STORE_free(rootCertStore); return; }
/* * This function verifies the validity of the certificate and the matching of the * other part's name with the certificate. * It also checks the sign validity of a message. * It returns -1 on generic error, -3 on mismatching on certificate, 1 on success. * It closes the passed file pointer fp (which should have already been opened). * The last argument is used to distinguish if we are initializing or accepting * a connection and so which is the correct name to verify. * After verifying, It leaves the public parameter of DH and the nonce of the * other part respectively in **pub_buf (which is allocated) and *nonce. */ int verify_name(FILE* fp,unsigned char *hello_buf,unsigned int hello_len,unsigned char *sign_buf,unsigned int sign_len,unsigned char** pub_buf,unsigned int *pubbuf_len,X509_STORE* str,int* nonce,int init){ int sheet_len,ret; uint32_t tmp; char read_mail[DIM_MAIL],temp_mail[DIM_MAIL],*cert_mail = NULL; X509_STORE_CTX* cert_ctx = NULL; EVP_PKEY* evp = EVP_PKEY_new(); EVP_MD_CTX* ctx = NULL; *pub_buf = NULL; if (!fp) { ret = -1; goto fail; } //We must come back to the start of fp rewind(fp); X509* cert = PEM_read_X509(fp,NULL,NULL,NULL); *pub_buf = NULL; //the following function is needed to correctly verify the certificate OpenSSL_add_all_algorithms(); if((cert_ctx=X509_STORE_CTX_new())==NULL){ ret = -1; goto fail; } if(X509_STORE_CTX_init(cert_ctx,str,cert,NULL)<=0){ ret = -1; goto fail; } if(X509_verify_cert(cert_ctx)==0){ //fprintf(stderr, "Error verifying certificate: %s\n", X509_verify_cert_error_string(X509_STORE_CTX_get_error(cert_ctx))); ret = -3; goto fail; } X509_STORE_CTX_cleanup(cert_ctx); X509_STORE_CTX_free(cert_ctx); cert_ctx = NULL; ctx = (EVP_MD_CTX*)calloc(1,sizeof(EVP_MD_CTX)); EVP_MD_CTX_init(ctx); evp = X509_get_pubkey(cert); if(EVP_VerifyInit(ctx,EVP_sha512())==0){ ret = -1; goto fail; } if(EVP_VerifyUpdate(ctx,hello_buf,hello_len)==0){ ret = -1; goto fail; } ret=EVP_VerifyFinal(ctx,sign_buf,sign_len,evp); if(ret == 0){ ret = -3; goto fail; } if (ret == -1) { goto fail; } rewind(fp); cert_mail = read_common_name(fp);//set it free later if(init == 1){ sscanf((char *)hello_buf,"%s%s",temp_mail,read_mail); } else{ sscanf((char *)hello_buf,"%s%s",read_mail,temp_mail); } sheet_len = strlen(temp_mail)+strlen(read_mail)+2; *pubbuf_len = hello_len - sheet_len; tmp = *((uint32_t *)(hello_buf+sheet_len)); *nonce = ntohl(tmp); sheet_len+=sizeof(tmp); *pub_buf = (unsigned char*)calloc(1,*pubbuf_len); memcpy(*pub_buf,hello_buf+sheet_len,*pubbuf_len); if(strlen(cert_mail)!=strlen(read_mail)){ ret = -3; goto fail; } if(strncmp(cert_mail,read_mail,strlen(cert_mail))!=0){ ret = -3; goto fail; } free(ctx); fclose(fp); EVP_PKEY_free(evp); free(cert_mail); return 1; fail: fclose(fp); if(cert_mail!=NULL){ free(cert_mail); } if(cert_ctx!=NULL){ X509_STORE_CTX_cleanup(cert_ctx); X509_STORE_CTX_free(cert_ctx); } if(ctx!=NULL){ free(ctx); } if(*pub_buf!=NULL){ free(*pub_buf); } EVP_PKEY_free(evp); return ret; }
/* Helper function to trace the signing cert to a trusted CA root * in the OpenSSL Trust Store. */ static int checkCertOpenSSL(const GTPublicationsFile *publications_file) { int res = GT_UNKNOWN_ERROR; unsigned char *cert_der = NULL; size_t cert_der_len; unsigned char *cert_tmp; X509 *cert = NULL; X509_STORE_CTX *store_ctx = NULL; X509_NAME *subj = NULL; ASN1_OBJECT *oid = NULL; char tmp_name[256]; int rc; res = GTPublicationsFile_getSigningCert(publications_file, &cert_der, &cert_der_len); if (res != GT_OK) { goto cleanup; } /* Note that d2i_X509() spoils the pointer to the buffer, use a temporary copy. */ cert_tmp = cert_der; cert = d2i_X509(NULL, (const unsigned char **) &cert_tmp, cert_der_len); if (cert == NULL) { res = GT_NOT_VALID_PUBLICATION; goto cleanup; } #ifdef MAGIC_EMAIL subj = X509_get_subject_name(cert); if (subj == NULL) { res = GT_CRYPTO_FAILURE; goto cleanup; } oid = OBJ_txt2obj("1.2.840.113549.1.9.1", 1); if (oid == NULL) { res = GT_OUT_OF_MEMORY; goto cleanup; } rc = X509_NAME_get_text_by_OBJ(subj, oid, tmp_name, sizeof(tmp_name)); if (rc < 0) { res = GT_INVALID_SIGNATURE; goto cleanup; } if (strcmp(tmp_name, MAGIC_EMAIL) != 0) { res = GT_INVALID_SIGNATURE; goto cleanup; } #endif store_ctx = X509_STORE_CTX_new(); if (store_ctx == NULL) { res = GT_OUT_OF_MEMORY; goto cleanup; } /* The truststore is not initialized by default. */ if (GT_truststore == NULL) { res = GTTruststore_init(1); if (res != GT_OK) goto cleanup; } if (!X509_STORE_CTX_init(store_ctx, GT_truststore, cert, publications_file->signature->d.sign->cert)) { res = GT_OUT_OF_MEMORY; goto cleanup; } rc = X509_verify_cert(store_ctx); if (rc < 0) { res = GT_CRYPTO_FAILURE; goto cleanup; } if (rc != 1) { res = GT_CERT_NOT_TRUSTED; goto cleanup; } res = GT_OK; cleanup: GT_free(cert_der); /* Do not free subj, it points into cert. */ ASN1_OBJECT_free(oid); if (cert != NULL) { X509_free(cert); } if (store_ctx != NULL) { X509_STORE_CTX_free(store_ctx); } return res; }
// take certificate hashes, check their validity and output json that // will indicate which certificate were used for verification, whatever // the chain was trusted and if all certificates needed for verification // (with the exception of root CA) were present in hashes int process_chain(const char **cert_hashes) { int ret; int rc; // return code from function char *f_name; X509 *cert; X509 *x509; X509_STORE *store; X509_STORE_CTX *csc; STACK_OF(X509) *ustack; STACK_OF(X509) *vstack; // load certificates to temp structures // first the end entity cert // (EE cert needs to be passed separately to OpenSSL verification context) f_name = hash_to_filename(cert_hashes[0]); if (f_name == NULL) return 1; cert = load_cert(f_name); free(f_name); if (cert == NULL) { printf("can't load certificate!\n"); return 1; } // then the intermediate certificates ustack = sk_X509_new_null(); for (int i=1; cert_hashes[i]!=NULL; i++) { //printf(".\n"); f_name = hash_to_filename(cert_hashes[i]); if (f_name == NULL) { // file not found continue; } x509 = load_cert(f_name); if (x509 == NULL) { // loading cert failed continue; } sk_X509_push(ustack, x509); free(f_name); } // first try with just trusted certificates store = SSL_CTX_get_cert_store(trusted_only); if (store == NULL) { fprintf(stderr, "store init failed\n"); return 1; } X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST); csc = X509_STORE_CTX_new(); ret = X509_STORE_CTX_init(csc, store, cert, ustack); if (ret != 1) { return 1; } ret = X509_verify_cert(csc); if (ret != 1) { // printf("%s\n", X509_verify_cert_error_string(csc->error)); } else { // chain is complete, output certificate hashes printf("{\"chain\":\"complete\",\"certificates\":["); vstack = X509_STORE_CTX_get_chain(csc); for(int i=0; i<sk_X509_num(vstack); i++) { X509 *c = sk_X509_value(vstack, i); const EVP_MD *digest; unsigned char md[EVP_MAX_MD_SIZE]; int n; digest = EVP_get_digestbyname("sha256"); X509_digest(c, digest, md, &n); printf("\""); for(int i=0; i<n; i++) { printf("%02x", md[i]); } printf("\""); if (i+1 < sk_X509_num(vstack)) { printf(","); } } printf("]}"); X509_STORE_CTX_free(csc); sk_X509_pop_free(ustack, X509_free); X509_free(cert); return 0; } X509_STORE_CTX_free(csc); // validation failed with just the trust anchors, retry with all // known intermediate certificates store = SSL_CTX_get_cert_store(all_CAs); if (store == NULL) { fprintf(stderr, "store init failed\n"); return 1; } X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST); csc = X509_STORE_CTX_new(); ret = X509_STORE_CTX_init(csc, store, cert, ustack); if (ret != 1) { return 1; } ret = X509_verify_cert(csc); if (ret != 1) { // certificate untrusted printf("{\"chain\":\"untrusted\"}"); } else { // chain successfully verified using all certificates, // print all the certs used to verify it printf("{\"chain\":\"incomplete\",\"certificates\":["); vstack = X509_STORE_CTX_get_chain(csc); for(int i=0; i<sk_X509_num(vstack); i++) { X509 *c = sk_X509_value(vstack, i); const EVP_MD *digest; unsigned char md[EVP_MAX_MD_SIZE]; int n; digest = EVP_get_digestbyname("sha256"); X509_digest(c, digest, md, &n); printf("\""); for(int i=0; i<n; i++) { printf("%02x", md[i]); } printf("\""); if (i+1 < sk_X509_num(vstack)) { printf(","); } } printf("]}"); } X509_STORE_CTX_free(csc); sk_X509_pop_free(ustack, X509_free); X509_free(cert); return 0; }