int ca_X509_verify(void *certificate, void *chain, const char *CAfile, const char *CRLfile, const char **errstr) { X509_STORE *store = NULL; X509_STORE_CTX *xsc = NULL; int ret = 0; if ((store = X509_STORE_new()) == NULL) goto end; if (!X509_STORE_load_locations(store, CAfile, NULL)) { log_warn("warn: unable to load CA file %s", CAfile); goto end; } X509_STORE_set_default_paths(store); if ((xsc = X509_STORE_CTX_new()) == NULL) goto end; if (X509_STORE_CTX_init(xsc, store, certificate, chain) != 1) goto end; X509_STORE_CTX_set_verify_cb(xsc, ca_verify_cb); ret = X509_verify_cert(xsc); end: *errstr = NULL; if (ret != 1) { if (xsc) *errstr = X509_verify_cert_error_string(xsc->error); else if (ERR_peek_last_error()) *errstr = ERR_error_string(ERR_peek_last_error(), NULL); } if (xsc) X509_STORE_CTX_free(xsc); if (store) X509_STORE_free(store); return ret > 0 ? 1 : 0; }
static int ssl_ca_store_init(const char *my_ca) { int ret; if (!ca_store) { if (!my_ca) { printf("no global ca string provided \n"); return -1; } ca_store = X509_STORE_new(); ca = ssl_load_cert(my_ca); ret = X509_STORE_add_cert(ca_store, ca); if (ret != 1) { printf("failed to X509_STORE_add_cert ret = %d \n", ret); return -1; } } return 0; }
static X509_STORE *create_cert_store(char *CApath, char *CAfile, X509_VERIFY_PARAM *vpm) { X509_STORE *cert_ctx = NULL; X509_LOOKUP *lookup = NULL; int i; cert_ctx = X509_STORE_new(); X509_STORE_set_verify_cb(cert_ctx, verify_cb); if (CApath != NULL) { lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir()); if (lookup == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } i = X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM); if (!i) { BIO_printf(bio_err, "Error loading directory %s\n", CApath); goto err; } } if (CAfile != NULL) { lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file()); if (lookup == NULL) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } i = X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM); if (!i) { BIO_printf(bio_err, "Error loading file %s\n", CAfile); goto err; } } if (vpm != NULL) X509_STORE_set1_param(cert_ctx, vpm); return cert_ctx; err: X509_STORE_free(cert_ctx); return NULL; }
static int do_store(SSL_CONF_CTX *cctx, const char *CAfile, const char *CApath, int verify_store) { CERT *cert; X509_STORE **st; if (cctx->ctx) cert = cctx->ctx->cert; else if (cctx->ssl) cert = cctx->ssl->cert; else return 1; st = verify_store ? &cert->verify_store : &cert->chain_store; if (*st == NULL) { *st = X509_STORE_new(); if (*st == NULL) return 0; } return X509_STORE_load_locations(*st, CAfile, CApath) > 0; }
selene_error_t* selene_conf_create_with_allloc(selene_conf_t **p_conf, selene_alloc_t *alloc) { selene_conf_t *conf; if (alloc == NULL) { alloc = &default_alloc; } conf = alloc->calloc(alloc->baton, sizeof(selene_conf_t)); conf->alloc = alloc; conf->trusted_cert_store = X509_STORE_new(); *p_conf = conf; return SELENE_SUCCESS; }
/* * Create Global X509 revocation store and use it to verify * OCSP responses * * - Load the trusted CAs * - Load the trusted issuer certificates */ static X509_STORE *init_revocation_store(EAP_TLS_CONF *conf) { X509_STORE *store = NULL; store = X509_STORE_new(); /* Load the CAs we trust */ if (conf->ca_file || conf->ca_path) if(!X509_STORE_load_locations(store, conf->ca_file, conf->ca_path)) { radlog(L_ERR, "rlm_eap: X509_STORE error %s", ERR_error_string(ERR_get_error(), NULL)); radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list %s",conf->ca_file ); return NULL; } #ifdef X509_V_FLAG_CRL_CHECK if (conf->check_crl) X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK); #endif return store; }
static int cryptoMagic(X509 *x0, X509 *x1, X509 *x2, const unsigned char *toHashData, int toHashLength, /*XXX const*/ unsigned char *rsaSigData, int rsaSigLen, DataValue *partialDigest) { int rv = 0; EVP_PKEY *pk = X509_get_pubkey(x2); if (pk) { if (pk->type == EVP_PKEY_RSA) { RSA *rsa = EVP_PKEY_get1_RSA(pk); if (rsa) { X509_STORE *store = X509_STORE_new(); if (store) { X509_STORE_CTX ctx; X509_STORE_add_cert(store, x0); X509_STORE_add_cert(store, x1); if (X509_STORE_CTX_init(&ctx, store, x2, 0) == 1) { X509_STORE_CTX_set_flags(&ctx, X509_V_FLAG_IGNORE_CRITICAL); if (X509_verify_cert(&ctx) == 1) { unsigned char md[SHA_DIGEST_LENGTH]; if (partialDigest) { // XXX we need to flip ECID back before hashing flipAppleImg3Header((AppleImg3Header *)toHashData); doPartialSHA1(md, toHashData, toHashLength, partialDigest); } else { SHA1(toHashData, toHashLength, md); } rv = RSA_verify(NID_sha1, md, SHA_DIGEST_LENGTH, rsaSigData, rsaSigLen, rsa); } X509_STORE_CTX_cleanup(&ctx); } X509_STORE_free(store); } RSA_free(rsa); } } EVP_PKEY_free(pk); } return rv ? 0 : -1; }
SEXP PKI_verify_cert(SEXP sCA, SEXP sCert) { X509 *cert; X509_STORE *store; X509_STORE_CTX *ctx; int rv; PKI_init(); cert = retrieve_cert(sCert, ""); store = X509_STORE_new(); if (TYPEOF(sCA) == VECSXP) { int i; for (i = 0; i < LENGTH(sCA); i++) X509_STORE_add_cert(store, retrieve_cert(VECTOR_ELT(sCA, i),"CA ")); } else X509_STORE_add_cert(store, retrieve_cert(sCA, "CA ")); ctx = X509_STORE_CTX_new(); X509_STORE_CTX_init(ctx, store, cert, NULL); rv = X509_verify_cert(ctx); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return ScalarLogical((rv == 1) ? TRUE : FALSE); }
void TLSConnectionPrivate::OnConnect(uv_connect_t *connect, int status) { TLSConnectionPrivate *cp = static_cast<TLSConnectionPrivate *>(connect->data); assert(cp->state_ == TLS_CONNECTION_STATE_PRE_CONNECT); // Unable to connect. if (status == -1) { cp->ShutdownError(UVUtils::ErrorFromLastUVError(cp->loop_)); return; } // Begin reading the incoming stream of data. int err = uv_read_start(connect->handle, TLSConnectionPrivate::AllocCallback, TLSConnectionPrivate::OnRead); if (err != UV_OK) { cp->ShutdownError(UVUtils::ErrorFromLastUVError(cp->loop_)); return; } // Set up the OpenSSL context const SSL_METHOD *meth = TLSv1_client_method(); cp->ctx_ = SSL_CTX_new(meth); SSL_CTX_set_verify(cp->ctx_, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_set_cert_verify_callback(cp->ctx_, TLSConnectionPrivate::SSLVerifyCallback, cp); cp->ssl_ = SSL_new(cp->ctx_); SSL_set_connect_state(cp->ssl_); cp->bio_ = BIO_new(UVBioState::GetMethod()); cp->biostate_ = new UVBioState(connect); cp->bio_->ptr = cp->biostate_; SSL_set_bio(cp->ssl_, cp->bio_, cp->bio_); // Set an empty X509_STORE as our SSL_CTX cert store. // The default store should be empty as well, but let's // make sure. X509_STORE *store = X509_STORE_new(); SSL_CTX_set_cert_store(cp->ctx_, store); cp->state_ = TLS_CONNECTION_STATE_STARVED_SSL_CONNECT; cp->HandleStarvedConnectState(); }
/** Returns status of certification: 0 for invalid, 1 for valid. */ static int valid_cert(X509 *cert, char *hostname) { int i; char buf[4096]; X509_STORE *store = X509_STORE_new(); X509_STORE_CTX *ctx = X509_STORE_CTX_new(); for (i = 0; trusted_ca[i] != NULL; i++) { X509 *cacert = get_cert_from_file(trusted_ca[i]); if (cacert) X509_STORE_add_cert(store, cacert); } X509_STORE_CTX_init(ctx, store, cert, sk_X509_new_null()); if (X509_verify_cert(ctx) == 0) return 0; X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf) - 1); // anal-retentive: make sure the hostname isn't as long as the // buffer, since we don't want to match only because of truncation if (strlen(hostname) >= sizeof(buf) - 1) return 0; return (!strcmp(buf, hostname)); }
bud_error_t bud_config_load_ca_file(X509_STORE** store, const char* filename) { BIO* b; X509* x509; bud_error_t err; b = BIO_new_file(filename, "r"); if (b == NULL) return bud_error_dstr(kBudErrLoadCert, filename); x509 = NULL; *store = X509_STORE_new(); if (*store == NULL) { err = bud_error_dstr(kBudErrNoMem, "CA store"); goto fatal; } while ((x509 = PEM_read_bio_X509(b, NULL, NULL, NULL)) != NULL) { if (x509 == NULL) { err = bud_error_dstr(kBudErrParseCert, filename); goto fatal; } if (X509_STORE_add_cert(*store, x509) != 1) { err = bud_error(kBudErrAddCert); goto fatal; } X509_free(x509); x509 = NULL; } err = bud_ok(); fatal: if (x509 != NULL) X509_free(x509); BIO_free_all(b); return bud_ok(); }
passport_t *pki_embassy_deliver_passport(embassy_t *embassy, digital_id_t *digital_id, uint32_t expiration_delay) { jlog(L_NOTICE, "pki_embassy_deliver_passport"); passport_t *passport; passport = calloc(1, sizeof(passport_t)); EVP_PKEY *keyring; X509_REQ *cert_req; X509 *certificate; X509_NAME *issuer; // generate RSA public and private keys keyring = pki_generate_keyring(); // create a certificate signing request cert_req = pki_certificate_request(keyring, digital_id); // fetch the 'Subject:' name from the certificate authority issuer = X509_get_subject_name(embassy->certificate); // create the certificate from the certificate request and keyring certificate = pki_certificate(issuer, keyring, cert_req, false, embassy->serial++, expiration_delay); // sign the certificate with the certificate authority pki_sign_certificate(embassy->keyring, certificate); // create the new passport passport->certificate = certificate; passport->keyring = keyring; passport->trusted_authority = X509_STORE_new(); // add the trusted certificate authority X509_STORE_add_cert(passport->trusted_authority, embassy->certificate); // deliver the passport return passport; }
int verify_certificate (const char* certfile, const char* ca_cert) { X509_STORE *cert_ctx=NULL; X509_LOOKUP *lookup=NULL; cert_ctx=X509_STORE_new(); if (!cert_ctx) return 0; OpenSSL_add_all_algorithms(); lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file()); if (!lookup) { if (cert_ctx) X509_STORE_free(cert_ctx); return 0; } if(!X509_LOOKUP_load_file(lookup,ca_cert,X509_FILETYPE_PEM)) { if (cert_ctx) X509_STORE_free(cert_ctx); return 0; } lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir()); if (!lookup) { if (cert_ctx) X509_STORE_free(cert_ctx); return 0; } X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT); return check(cert_ctx, certfile); }
int s2n_x509_trust_store_from_ca_file(struct s2n_x509_trust_store *store, const char *ca_pem_filename, const char *ca_dir) { if (!store->trust_store) { store->trust_store = X509_STORE_new(); notnull_check(store->trust_store); } int err_code = X509_STORE_load_locations(store->trust_store, ca_pem_filename, ca_dir); if (!err_code) { s2n_x509_trust_store_wipe(store); return -1; } /* It's a likely scenario if this function is called, a self-signed certificate is used, and that is was generated * without a trust anchor. However if you call this function, the assumption is you trust ca_file or path and if a certificate * is encountered that's in that path, it should be trusted. The following flag tells libcrypto to not care that the cert * is missing a root anchor. */ unsigned long flags = X509_VP_FLAG_DEFAULT; flags |= X509_V_FLAG_PARTIAL_CHAIN; X509_STORE_set_flags(store->trust_store, flags); return 0; }
static int tls_sc_add_trusted_cert(lua_State *L) { tls_sc_t *ctx; BIO *bio; const char *certstr = NULL; size_t clen = 0; int rv; ctx = getSC(L); if (ctx->ca_store == NULL) { /* TODO: better handling of global CA cert list */ ctx->ca_store = X509_STORE_new(); SSL_CTX_set_cert_store(ctx->ctx, ctx->ca_store); } certstr = luaL_checklstring(L, 2, &clen); bio = str2bio(certstr, clen); if (!bio) { return luaL_error(L, "tls_sc_add_trusted_cert: Failed to convert Cert into a BIO"); } ERR_clear_error(); rv = X509_STORE_load_bio(ctx->ca_store, bio); if (!rv) { BIO_free(bio); return tls_fatal_error(L); } BIO_free(bio); return 0; }
net_nfc_openssl_verify_context_s *net_nfc_util_openssl_init_verify_certificate(void) { net_nfc_openssl_verify_context_s *result = NULL; _net_nfc_util_alloc_mem(result, sizeof(net_nfc_openssl_verify_context_s)); if (result != NULL) { result->store = X509_STORE_new(); if (result->store != NULL) { OpenSSL_add_all_algorithms(); } else { DEBUG_ERR_MSG("X509_STORE_new failed"); } } else { DEBUG_ERR_MSG("alloc failed [%d]", sizeof(net_nfc_openssl_verify_context_s)); } return result; }
void ContextImpl::addCACertificate(const Certificate& trustedCert) { log_trace("adding CA certificate:" << trustedCert.subject()); _caCerts.reserve(_caCerts.size() + 1); X509* x509 = copyX509( trustedCert.impl()->x509() ); X509AutoPtr x509Ptr(x509); X509_STORE* store = SSL_CTX_get_cert_store(_ctx); if( ! store) { log_trace("creating new X509 store"); store = X509_STORE_new(); } if( ! X509_STORE_add_cert(store, x509) ) { throw InvalidCertificate("invalid CA certificate"); } _caCerts.push_back(x509); x509Ptr.release(); }
static X509_STORE * read_cacerts(char *file) { X509_STORE *store; X509_LOOKUP *lookup; if ((store = X509_STORE_new()) == NULL) { warnx("Malloc failed"); goto end; } if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL) { warnx("Unable to load CA certs from file %s", file); goto end; } if (file) { if (!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) { warnx("Unable to load CA certs from file %s", file); goto end; } } else X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) == NULL) { warnx("Unable to load CA certs from file %s", file); goto end; } X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error(); return store; end: X509_STORE_free(store); return NULL; }
static int verify_sig(char *sig, int sig_len, char *file, int (*byte_range)[2], int byte_range_len, char *ebuf, int ebufsize) { PKCS7 *pk7sig = NULL; PKCS7 *pk7cert = NULL; X509_STORE *st = NULL; BIO *bsig = NULL; BIO *bcert = NULL; BIO *bdata = NULL; BIO *bsegs = NULL; STACK_OF(X509) *certs = NULL; int t; int res = 0; bsig = BIO_new_mem_buf(sig, sig_len); pk7sig = d2i_PKCS7_bio(bsig, NULL); if (pk7sig == NULL) goto exit; bdata = BIO_new(BIO_s_file()); if (bdata == NULL) goto exit; BIO_read_filename(bdata, file); bsegs = BIO_new(BIO_f_segments()); if (bsegs == NULL) goto exit; bsegs->next_bio = bdata; BIO_set_segments(bsegs, byte_range, byte_range_len); /* Find the certificates in the pk7 file */ bcert = BIO_new_mem_buf(adobe_ca, sizeof(adobe_ca)); pk7cert = d2i_PKCS7_bio(bcert, NULL); if (pk7cert == NULL) goto exit; t = OBJ_obj2nid(pk7cert->type); switch (t) { case NID_pkcs7_signed: certs = pk7cert->d.sign->cert; break; case NID_pkcs7_signedAndEnveloped: certs = pk7cert->d.sign->cert; break; default: break; } st = X509_STORE_new(); if (st == NULL) goto exit; /* Add the certificates to the store */ if (certs != NULL) { int i, n = sk_X509_num(certs); for (i = 0; i < n; i++) { X509 *c = sk_X509_value(certs, i); X509_STORE_add_cert(st, c); } } res = pk7_verify(st, pk7sig, bsegs, ebuf, ebufsize); exit: BIO_free(bsig); BIO_free(bdata); BIO_free(bsegs); BIO_free(bcert); PKCS7_free(pk7sig); PKCS7_free(pk7cert); X509_STORE_free(st); return res; }
void PaymentServerTests::paymentServerTests() { SelectParams(CBaseChainParams::MAIN); OptionsModel optionsModel; PaymentServer* server = new PaymentServer(nullptr, false); X509_STORE* caStore = X509_STORE_new(); X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64)); PaymentServer::LoadRootCAs(caStore); server->setOptionsModel(&optionsModel); server->uiReady(); std::vector<unsigned char> data; SendCoinsRecipient r; QString merchant; // Now feed PaymentRequests to server, and observe signals it produces // This payment request validates directly against the // caCert1 certificate authority: data = DecodeBase64(paymentrequest1_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("testmerchant.org")); // Signed, but expired, merchant cert in the request: data = DecodeBase64(paymentrequest2_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // 10-long certificate chain, all intermediates valid: data = DecodeBase64(paymentrequest3_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("testmerchant8.org")); // Long certificate chain, with an expired certificate in the middle: data = DecodeBase64(paymentrequest4_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // Validly signed, but by a CA not in our root CA list: data = DecodeBase64(paymentrequest5_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // Try again with no root CA's, verifiedMerchant should be empty: caStore = X509_STORE_new(); PaymentServer::LoadRootCAs(caStore); data = DecodeBase64(paymentrequest1_cert1_BASE64); r = handleRequest(server, data); r.paymentRequest.getMerchant(caStore, merchant); QCOMPARE(merchant, QString("")); // Load second root certificate caStore = X509_STORE_new(); X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64)); PaymentServer::LoadRootCAs(caStore); QByteArray byteArray; // For the tests below we just need the payment request data from // paymentrequestdata.h parsed + stored in r.paymentRequest. // // These tests require us to bypass the following normal client execution flow // shown below to be able to explicitly just trigger a certain condition! // // handleRequest() // -> PaymentServer::eventFilter() // -> PaymentServer::handleURIOrFile() // -> PaymentServer::readPaymentRequestFromFile() // -> PaymentServer::processPaymentRequest() // Contains a testnet paytoaddress, so payment request network doesn't match client network: data = DecodeBase64(paymentrequest1_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized, because network "main" is default, even for // uninitialized payment requests and that will fail our test here. QVERIFY(r.paymentRequest.IsInitialized()); QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false); // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01): data = DecodeBase64(paymentrequest2_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // compares 1 < GetTime() == false (treated as expired payment request) QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true); // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t): // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t) // -1 is 1969-12-31 23:59:59 (for a 32 bit time values) data = DecodeBase64(paymentrequest3_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request) QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false); // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64): // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t) // 0 is 1970-01-01 00:00:00 (for a 32 bit time values) data = DecodeBase64(paymentrequest4_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // compares -9223372036854775808 < GetTime() == true (treated as expired payment request) QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true); // Test BIP70 DoS protection: unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1]; GetRandBytes(randData, sizeof(randData)); // Write data to a temp file: QTemporaryFile tempFile; tempFile.open(); tempFile.write((const char*)randData, sizeof(randData)); tempFile.close(); // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false QCOMPARE(PaymentServer::verifySize(tempFile.size()), false); // Payment request with amount overflow (amount is set to 21000001 BTC): data = DecodeBase64(paymentrequest5_cert2_BASE64); byteArray = QByteArray((const char*)data.data(), data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized QVERIFY(r.paymentRequest.IsInitialized()); // Extract address and amount from the request QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo(); for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) { CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); } delete server; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; int ret=1; X509_REQ *req=NULL; X509 *x=NULL,*xca=NULL; ASN1_OBJECT *objtmp; STACK_OF(OPENSSL_STRING) *sigopts = NULL; EVP_PKEY *Upkey=NULL,*CApkey=NULL; ASN1_INTEGER *sno = NULL; int i,num,badops=0; BIO *out=NULL; BIO *STDout=NULL; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; int informat,outformat,keyformat,CAformat,CAkeyformat; char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL; char *CAkeyfile=NULL,*CAserial=NULL; char *alias=NULL; int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0; int next_serial=0; int subject_hash=0,issuer_hash=0,ocspid=0; #ifndef OPENSSL_NO_MD5 int subject_hash_old=0,issuer_hash_old=0; #endif int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0; int ocsp_uri=0; int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0; int C=0; int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0; int pprint = 0; const char **pp; X509_STORE *ctx=NULL; X509_REQ *rq=NULL; int fingerprint=0; char buf[256]; const EVP_MD *md_alg,*digest=NULL; CONF *extconf = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL; int need_rand = 0; int checkend=0,checkoffset=0; unsigned long nmflag = 0, certflag = 0; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif reqfile=0; apps_startup(); if (bio_err == NULL) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; STDout=BIO_new_fp(stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); STDout = BIO_push(tmpbio, STDout); } #endif informat=FORMAT_PEM; outformat=FORMAT_PEM; keyformat=FORMAT_PEM; CAformat=FORMAT_PEM; CAkeyformat=FORMAT_PEM; ctx=X509_STORE_new(); if (ctx == NULL) goto end; X509_STORE_set_verify_cb(ctx,callb); argc--; argv++; num=0; while (argc >= 1) { if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-keyform") == 0) { if (--argc < 1) goto bad; keyformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-req") == 0) { reqfile=1; need_rand = 1; } else if (strcmp(*argv,"-CAform") == 0) { if (--argc < 1) goto bad; CAformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-CAkeyform") == 0) { if (--argc < 1) goto bad; CAkeyformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-sigopt") == 0) { if (--argc < 1) goto bad; if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) goto bad; } else if (strcmp(*argv,"-days") == 0) { if (--argc < 1) goto bad; days=atoi(*(++argv)); if (days == 0) { BIO_printf(STDout,"bad number of days\n"); goto bad; } } else if (strcmp(*argv,"-passin") == 0) { if (--argc < 1) goto bad; passargin= *(++argv); } else if (strcmp(*argv,"-extfile") == 0) { if (--argc < 1) goto bad; extfile= *(++argv); } else if (strcmp(*argv,"-extensions") == 0) { if (--argc < 1) goto bad; extsect= *(++argv); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (strcmp(*argv,"-signkey") == 0) { if (--argc < 1) goto bad; keyfile= *(++argv); sign_flag= ++num; need_rand = 1; } else if (strcmp(*argv,"-CA") == 0) { if (--argc < 1) goto bad; CAfile= *(++argv); CA_flag= ++num; need_rand = 1; } else if (strcmp(*argv,"-CAkey") == 0) { if (--argc < 1) goto bad; CAkeyfile= *(++argv); } else if (strcmp(*argv,"-CAserial") == 0) { if (--argc < 1) goto bad; CAserial= *(++argv); } else if (strcmp(*argv,"-set_serial") == 0) { if (--argc < 1) goto bad; if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv)))) goto bad; } else if (strcmp(*argv,"-addtrust") == 0) { if (--argc < 1) goto bad; if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { BIO_printf(bio_err, "Invalid trust object value %s\n", *argv); goto bad; } if (!trust) trust = sk_ASN1_OBJECT_new_null(); sk_ASN1_OBJECT_push(trust, objtmp); trustout = 1; } else if (strcmp(*argv,"-addreject") == 0) { if (--argc < 1) goto bad; if (!(objtmp = OBJ_txt2obj(*(++argv), 0))) { BIO_printf(bio_err, "Invalid reject object value %s\n", *argv); goto bad; } if (!reject) reject = sk_ASN1_OBJECT_new_null(); sk_ASN1_OBJECT_push(reject, objtmp); trustout = 1; } else if (strcmp(*argv,"-setalias") == 0) { if (--argc < 1) goto bad; alias= *(++argv); trustout = 1; } else if (strcmp(*argv,"-certopt") == 0) { if (--argc < 1) goto bad; if (!set_cert_ex(&certflag, *(++argv))) goto bad; } else if (strcmp(*argv,"-nameopt") == 0) { if (--argc < 1) goto bad; if (!set_name_ex(&nmflag, *(++argv))) goto bad; } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-C") == 0) C= ++num; else if (strcmp(*argv,"-email") == 0) email= ++num; else if (strcmp(*argv,"-ocsp_uri") == 0) ocsp_uri= ++num; else if (strcmp(*argv,"-serial") == 0) serial= ++num; else if (strcmp(*argv,"-next_serial") == 0) next_serial= ++num; else if (strcmp(*argv,"-modulus") == 0) modulus= ++num; else if (strcmp(*argv,"-pubkey") == 0) pubkey= ++num; else if (strcmp(*argv,"-x509toreq") == 0) x509req= ++num; else if (strcmp(*argv,"-text") == 0) text= ++num; else if (strcmp(*argv,"-hash") == 0 || strcmp(*argv,"-subject_hash") == 0) subject_hash= ++num; #ifndef OPENSSL_NO_MD5 else if (strcmp(*argv,"-subject_hash_old") == 0) subject_hash_old= ++num; #endif else if (strcmp(*argv,"-issuer_hash") == 0) issuer_hash= ++num; #ifndef OPENSSL_NO_MD5 else if (strcmp(*argv,"-issuer_hash_old") == 0) issuer_hash_old= ++num; #endif else if (strcmp(*argv,"-subject") == 0) subject= ++num; else if (strcmp(*argv,"-issuer") == 0) issuer= ++num; else if (strcmp(*argv,"-fingerprint") == 0) fingerprint= ++num; else if (strcmp(*argv,"-dates") == 0) { startdate= ++num; enddate= ++num; } else if (strcmp(*argv,"-purpose") == 0) pprint= ++num; else if (strcmp(*argv,"-startdate") == 0) startdate= ++num; else if (strcmp(*argv,"-enddate") == 0) enddate= ++num; else if (strcmp(*argv,"-checkend") == 0) { if (--argc < 1) goto bad; checkoffset=atoi(*(++argv)); checkend=1; } else if (strcmp(*argv,"-noout") == 0) noout= ++num; else if (strcmp(*argv,"-trustout") == 0) trustout= 1; else if (strcmp(*argv,"-clrtrust") == 0) clrtrust= ++num; else if (strcmp(*argv,"-clrreject") == 0) clrreject= ++num; else if (strcmp(*argv,"-alias") == 0) aliasout= ++num; else if (strcmp(*argv,"-CAcreateserial") == 0) CA_createserial= ++num; else if (strcmp(*argv,"-clrext") == 0) clrext = 1; #if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */ else if (strcmp(*argv,"-crlext") == 0) { BIO_printf(bio_err,"use -clrext instead of -crlext\n"); clrext = 1; } #endif else if (strcmp(*argv,"-ocspid") == 0) ocspid= ++num; else if ((md_alg=EVP_get_digestbyname(*argv + 1))) { /* ok */ digest=md_alg; } else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: for (pp=x509_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (need_rand) app_RAND_load_file(NULL, bio_err, 0); ERR_load_crypto_strings(); if (!app_passwd(bio_err, passargin, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (!X509_STORE_set_default_paths(ctx)) { ERR_print_errors(bio_err); goto end; } if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { CAkeyfile=CAfile; } else if ((CA_flag) && (CAkeyfile == NULL)) { BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n"); goto end; } if (extfile) { long errorline = -1; X509V3_CTX ctx2; extconf = NCONF_new(NULL); if (!NCONF_load(extconf, extfile,&errorline)) { if (errorline <= 0) BIO_printf(bio_err, "error loading the config file '%s'\n", extfile); else BIO_printf(bio_err, "error on line %ld of config file '%s'\n" ,errorline,extfile); goto end; } if (!extsect) { extsect = NCONF_get_string(extconf, "default", "extensions"); if (!extsect) { ERR_clear_error(); extsect = "default"; } } X509V3_set_ctx_test(&ctx2); X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error Loading extension section %s\n", extsect); ERR_print_errors(bio_err); goto end; } } if (reqfile) { EVP_PKEY *pkey; BIO *in; if (!sign_flag && !CA_flag) { BIO_printf(bio_err,"We need a private key to sign with\n"); goto end; } in=BIO_new(BIO_s_file()); if (in == NULL) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT); else { if (BIO_read_filename(in,infile) <= 0) { perror(infile); BIO_free(in); goto end; } } req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL); BIO_free(in); if (req == NULL) { ERR_print_errors(bio_err); goto end; } if ( (req->req_info == NULL) || (req->req_info->pubkey == NULL) || (req->req_info->pubkey->public_key == NULL) || (req->req_info->pubkey->public_key->data == NULL)) { BIO_printf(bio_err,"The certificate request appears to corrupted\n"); BIO_printf(bio_err,"It does not contain a public key\n"); goto end; } if ((pkey=X509_REQ_get_pubkey(req)) == NULL) { BIO_printf(bio_err,"error unpacking public key\n"); goto end; } i=X509_REQ_verify(req,pkey); EVP_PKEY_free(pkey); if (i < 0) { BIO_printf(bio_err,"Signature verification error\n"); ERR_print_errors(bio_err); goto end; } if (i == 0) { BIO_printf(bio_err,"Signature did not match the certificate request\n"); goto end; } else BIO_printf(bio_err,"Signature ok\n"); print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag); if ((x=X509_new()) == NULL) goto end; if (sno == NULL) { sno = ASN1_INTEGER_new(); if (!sno || !rand_serial(NULL, sno)) goto end; if (!X509_set_serialNumber(x, sno)) goto end; ASN1_INTEGER_free(sno); sno = NULL; } else if (!X509_set_serialNumber(x, sno)) goto end; if (!X509_set_issuer_name(x,req->req_info->subject)) goto end; if (!X509_set_subject_name(x,req->req_info->subject)) goto end; X509_gmtime_adj(X509_get_notBefore(x),0); X509_time_adj_ex(X509_get_notAfter(x),days, 0, NULL); pkey = X509_REQ_get_pubkey(req); X509_set_pubkey(x,pkey); EVP_PKEY_free(pkey); } else x=load_cert(bio_err,infile,informat,NULL,e,"Certificate"); if (x == NULL) goto end; if (CA_flag) { xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate"); if (xca == NULL) goto end; } if (!noout || text || next_serial) { OBJ_create("2.99999.3", "SET.ex3","SET x509v3 extension 3"); out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } } if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); if (clrtrust) X509_trust_clear(x); if (clrreject) X509_reject_clear(x); if (trust) { for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { objtmp = sk_ASN1_OBJECT_value(trust, i); X509_add1_trust_object(x, objtmp); } } if (reject) { for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { objtmp = sk_ASN1_OBJECT_value(reject, i); X509_add1_reject_object(x, objtmp); } } if (num) { for (i=1; i<=num; i++) { if (issuer == i) { print_name(STDout, "issuer= ", X509_get_issuer_name(x), nmflag); } else if (subject == i) { print_name(STDout, "subject= ", X509_get_subject_name(x), nmflag); } else if (serial == i) { BIO_printf(STDout,"serial="); i2a_ASN1_INTEGER(STDout, X509_get_serialNumber(x)); BIO_printf(STDout,"\n"); } else if (next_serial == i) { BIGNUM *bnser; ASN1_INTEGER *ser; ser = X509_get_serialNumber(x); bnser = ASN1_INTEGER_to_BN(ser, NULL); if (!bnser) goto end; if (!BN_add_word(bnser, 1)) goto end; ser = BN_to_ASN1_INTEGER(bnser, NULL); if (!ser) goto end; BN_free(bnser); i2a_ASN1_INTEGER(out, ser); ASN1_INTEGER_free(ser); BIO_puts(out, "\n"); } else if ((email == i) || (ocsp_uri == i)) { int j; STACK_OF(OPENSSL_STRING) *emlst; if (email == i) emlst = X509_get1_email(x); else emlst = X509_get1_ocsp(x); for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) BIO_printf(STDout, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); X509_email_free(emlst); } else if (aliasout == i) { unsigned char *alstr; alstr = X509_alias_get0(x, NULL); if (alstr) BIO_printf(STDout,"%s\n", alstr); else BIO_puts(STDout,"<No Alias>\n"); } else if (subject_hash == i) { BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (subject_hash_old == i) { BIO_printf(STDout,"%08lx\n",X509_subject_name_hash_old(x)); } #endif else if (issuer_hash == i) { BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (issuer_hash_old == i) { BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash_old(x)); } #endif else if (pprint == i) { X509_PURPOSE *ptmp; int j; BIO_printf(STDout, "Certificate purposes:\n"); for (j = 0; j < X509_PURPOSE_get_count(); j++) { ptmp = X509_PURPOSE_get0(j); purpose_print(STDout, x, ptmp); } } else if (modulus == i) { EVP_PKEY *pkey; pkey=X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err,"Modulus=unavailable\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(STDout,"Modulus="); #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) BN_print(STDout,pkey->pkey.rsa->n); else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) BN_print(STDout,pkey->pkey.dsa->pub_key); else #endif BIO_printf(STDout,"Wrong Algorithm type"); BIO_printf(STDout,"\n"); EVP_PKEY_free(pkey); } else if (pubkey == i) { EVP_PKEY *pkey; pkey=X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err,"Error getting public key\n"); ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(STDout, pkey); EVP_PKEY_free(pkey); } else if (C == i) { unsigned char *d; char *m; int y,z; X509_NAME_oneline(X509_get_subject_name(x), buf,sizeof buf); BIO_printf(STDout,"/* subject:%s */\n",buf); m=X509_NAME_oneline( X509_get_issuer_name(x),buf, sizeof buf); BIO_printf(STDout,"/* issuer :%s */\n",buf); z=i2d_X509(x,NULL); m=OPENSSL_malloc(z); d=(unsigned char *)m; z=i2d_X509_NAME(X509_get_subject_name(x),&d); BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d); BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); z=i2d_X509(x,&d); BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z); d=(unsigned char *)m; for (y=0; y<z; y++) { BIO_printf(STDout,"0x%02X,",d[y]); if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n"); } if (y%16 != 0) BIO_printf(STDout,"\n"); BIO_printf(STDout,"};\n"); OPENSSL_free(m); } else if (text == i) { X509_print_ex(out,x,nmflag, certflag); } else if (startdate == i) { BIO_puts(STDout,"notBefore="); ASN1_TIME_print(STDout,X509_get_notBefore(x)); BIO_puts(STDout,"\n"); } else if (enddate == i) { BIO_puts(STDout,"notAfter="); ASN1_TIME_print(STDout,X509_get_notAfter(x)); BIO_puts(STDout,"\n"); } else if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *fdig = digest; if (!fdig) fdig = EVP_sha1(); if (!X509_digest(x,fdig,md,&n)) { BIO_printf(bio_err,"out of memory\n"); goto end; } BIO_printf(STDout,"%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(fdig))); for (j=0; j<(int)n; j++) { BIO_printf(STDout,"%02X%c",md[j], (j+1 == (int)n) ?'\n':':'); } } /* should be in the library */ else if ((sign_flag == i) && (x509req == 0)) { BIO_printf(bio_err,"Getting Private key\n"); if (Upkey == NULL) { Upkey=load_key(bio_err, keyfile, keyformat, 0, passin, e, "Private key"); if (Upkey == NULL) goto end; } assert(need_rand); if (!sign(x,Upkey,days,clrext,digest, extconf, extsect)) goto end; } else if (CA_flag == i) { BIO_printf(bio_err,"Getting CA Private Key\n"); if (CAkeyfile != NULL) { CApkey=load_key(bio_err, CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); if (CApkey == NULL) goto end; } assert(need_rand); if (!x509_certify(ctx,CAfile,digest,x,xca, CApkey, sigopts, CAserial,CA_createserial,days, clrext, extconf, extsect, sno)) goto end; } else if (x509req == i) { EVP_PKEY *pk; BIO_printf(bio_err,"Getting request Private Key\n"); if (keyfile == NULL) { BIO_printf(bio_err,"no request key file specified\n"); goto end; } else { pk=load_key(bio_err, keyfile, keyformat, 0, passin, e, "request key"); if (pk == NULL) goto end; } BIO_printf(bio_err,"Generating certificate request\n"); rq=X509_to_X509_REQ(x,pk,digest); EVP_PKEY_free(pk); if (rq == NULL) { ERR_print_errors(bio_err); goto end; } if (!noout) { X509_REQ_print(out,rq); PEM_write_bio_X509_REQ(out,rq); } noout=1; } else if (ocspid == i) { X509_ocspid_print(out, x); } } } if (checkend) { time_t tcheck=time(NULL) + checkoffset; if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { BIO_printf(out,"Certificate will expire\n"); ret=1; } else { BIO_printf(out,"Certificate will not expire\n"); ret=0; } goto end; } if (noout) { ret=0; goto end; } if (outformat == FORMAT_ASN1) i=i2d_X509_bio(out,x); else if (outformat == FORMAT_PEM) { if (trustout) i=PEM_write_bio_X509_AUX(out,x); else i=PEM_write_bio_X509(out,x); } else if (outformat == FORMAT_NETSCAPE) { NETSCAPE_X509 nx; ASN1_OCTET_STRING hdr; hdr.data=(unsigned char *)NETSCAPE_CERT_HDR; hdr.length=strlen(NETSCAPE_CERT_HDR); nx.header= &hdr; nx.cert=x; i=ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509),out,&nx); } else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write certificate\n"); ERR_print_errors(bio_err); goto end; } ret=0; end: if (need_rand) app_RAND_write_file(NULL, bio_err); OBJ_cleanup(); NCONF_free(extconf); BIO_free_all(out); BIO_free_all(STDout); X509_STORE_free(ctx); X509_REQ_free(req); X509_free(x); X509_free(xca); EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); if (sigopts) sk_OPENSSL_STRING_free(sigopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); if (passin) OPENSSL_free(passin); apps_shutdown(); OPENSSL_EXIT(ret); }
/* 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; }
int main(int argc, char **argv) { BIO *in = NULL, *out = NULL, *tbio = NULL, *cont = NULL; X509_STORE *st = NULL; X509 *cacert = NULL; CMS_ContentInfo *cms = NULL; int ret = 1; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); /* Set up trusted CA certificate store */ st = X509_STORE_new(); /* Read in CA certificate */ tbio = BIO_new_file("cacert.pem", "r"); if (!tbio) goto err; cacert = PEM_read_bio_X509(tbio, NULL, 0, NULL); if (!cacert) goto err; if (!X509_STORE_add_cert(st, cacert)) goto err; /* Open message being verified */ in = BIO_new_file("smout.txt", "r"); if (!in) goto err; /* parse message */ cms = SMIME_read_CMS(in, &cont); if (!cms) goto err; /* File to output verified content to */ out = BIO_new_file("smver.txt", "w"); if (!out) goto err; if (!CMS_verify(cms, NULL, st, cont, out, 0)) { fprintf(stderr, "Verification Failure\n"); goto err; } fprintf(stderr, "Verification Successful\n"); ret = 0; err: if (ret) { fprintf(stderr, "Error Verifying Data\n"); ERR_print_errors_fp(stderr); } if (cms) CMS_ContentInfo_free(cms); if (cacert) X509_free(cacert); if (in) BIO_free(in); if (out) BIO_free(out); if (tbio) BIO_free(tbio); return ret; }
int MAIN (int argc, char **argv) { ENGINE *e = NULL; int i, ret = 1, badarg = 0; char *CApath = NULL, *CAfile = NULL; char *untfile = NULL, *trustfile = NULL, *crlfile = NULL; STACK_OF (X509) * untrusted = NULL, *trusted = NULL; STACK_OF (X509_CRL) * crls = NULL; X509_STORE *cert_ctx = NULL; X509_LOOKUP *lookup = NULL; X509_VERIFY_PARAM *vpm = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif cert_ctx = X509_STORE_new (); if (cert_ctx == NULL) goto end; X509_STORE_set_verify_cb (cert_ctx, cb); ERR_load_crypto_strings (); apps_startup (); if (bio_err == NULL) if ((bio_err = BIO_new (BIO_s_file ())) != NULL) BIO_set_fp (bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); if (!load_config (bio_err, NULL)) goto end; argc--; argv++; for (;;) { if (argc >= 1) { if (strcmp (*argv, "-CApath") == 0) { if (argc-- < 1) goto end; CApath = *(++argv); } else if (strcmp (*argv, "-CAfile") == 0) { if (argc-- < 1) goto end; CAfile = *(++argv); } else if (args_verify (&argv, &argc, &badarg, bio_err, &vpm)) { if (badarg) goto end; continue; } else if (strcmp (*argv, "-untrusted") == 0) { if (argc-- < 1) goto end; untfile = *(++argv); } else if (strcmp (*argv, "-trusted") == 0) { if (argc-- < 1) goto end; trustfile = *(++argv); } else if (strcmp (*argv, "-CRLfile") == 0) { if (argc-- < 1) goto end; crlfile = *(++argv); } #ifndef OPENSSL_NO_ENGINE else if (strcmp (*argv, "-engine") == 0) { if (--argc < 1) goto end; engine = *(++argv); } #endif else if (strcmp (*argv, "-help") == 0) goto end; else if (strcmp (*argv, "-verbose") == 0) v_verbose = 1; else if (argv[0][0] == '-') goto end; else break; argc--; argv++; } else break; } #ifndef OPENSSL_NO_ENGINE e = setup_engine (bio_err, engine, 0); #endif if (vpm) X509_STORE_set1_param (cert_ctx, vpm); lookup = X509_STORE_add_lookup (cert_ctx, X509_LOOKUP_file ()); if (lookup == NULL) abort (); if (CAfile) { i = X509_LOOKUP_load_file (lookup, CAfile, X509_FILETYPE_PEM); if (!i) { BIO_printf (bio_err, "Error loading file %s\n", CAfile); ERR_print_errors (bio_err); goto end; } } else X509_LOOKUP_load_file (lookup, NULL, X509_FILETYPE_DEFAULT); lookup = X509_STORE_add_lookup (cert_ctx, X509_LOOKUP_hash_dir ()); if (lookup == NULL) abort (); if (CApath) { i = X509_LOOKUP_add_dir (lookup, CApath, X509_FILETYPE_PEM); if (!i) { BIO_printf (bio_err, "Error loading directory %s\n", CApath); ERR_print_errors (bio_err); goto end; } } else X509_LOOKUP_add_dir (lookup, NULL, X509_FILETYPE_DEFAULT); ERR_clear_error (); if (untfile) { untrusted = load_certs (bio_err, untfile, FORMAT_PEM, NULL, e, "untrusted certificates"); if (!untrusted) goto end; } if (trustfile) { trusted = load_certs (bio_err, trustfile, FORMAT_PEM, NULL, e, "trusted certificates"); if (!trusted) goto end; } if (crlfile) { crls = load_crls (bio_err, crlfile, FORMAT_PEM, NULL, e, "other CRLs"); if (!crls) goto end; } ret = 0; if (argc < 1) { if (1 != check (cert_ctx, NULL, untrusted, trusted, crls, e)) ret = -1; } else { for (i = 0; i < argc; i++) if (1 != check (cert_ctx, argv[i], untrusted, trusted, crls, e)) ret = -1; } end: if (ret == 1) { BIO_printf (bio_err, "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]"); BIO_printf (bio_err, " [-attime timestamp]"); #ifndef OPENSSL_NO_ENGINE BIO_printf (bio_err, " [-engine e]"); #endif BIO_printf (bio_err, " cert1 cert2 ...\n"); BIO_printf (bio_err, "recognized usages:\n"); for (i = 0; i < X509_PURPOSE_get_count (); i++) { X509_PURPOSE *ptmp; ptmp = X509_PURPOSE_get0 (i); BIO_printf (bio_err, "\t%-10s\t%s\n", X509_PURPOSE_get0_sname (ptmp), X509_PURPOSE_get0_name (ptmp)); } } if (vpm) X509_VERIFY_PARAM_free (vpm); if (cert_ctx != NULL) X509_STORE_free (cert_ctx); sk_X509_pop_free (untrusted, X509_free); sk_X509_pop_free (trusted, X509_free); sk_X509_CRL_pop_free (crls, X509_CRL_free); apps_shutdown (); OPENSSL_EXIT (ret < 0 ? 2 : ret); }
// // Load OpenSSL's list of root certificate authorities // void PaymentServer::LoadRootCAs(X509_STORE* _store) { // Unit tests mostly use this, to pass in fake root CAs: if (_store) { certStore.reset(_store); return; } // Normal execution, use either -rootcertificates or system certs: certStore.reset(X509_STORE_new()); // Note: use "-system-" default here so that users can pass -rootcertificates="" // and get 'I don't like X.509 certificates, don't trust anybody' behavior: QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-")); // Empty store if (certFile.isEmpty()) { qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__); return; } QList<QSslCertificate> certList; if (certFile != "-system-") { qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile); certList = QSslCertificate::fromPath(certFile); // Use those certificates when fetching payment requests, too: QSslSocket::setDefaultCaCertificates(certList); } else certList = QSslSocket::systemCaCertificates(); int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); for (const QSslCertificate& cert : certList) { // Don't log NULL certificates if (cert.isNull()) continue; // Not yet active/valid, or expired certificate if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) { ReportInvalidCertificate(cert); continue; } #if QT_VERSION >= 0x050000 // Blacklisted certificate if (cert.isBlacklisted()) { ReportInvalidCertificate(cert); continue; } #endif QByteArray certData = cert.toDer(); const unsigned char *data = (const unsigned char *)certData.data(); std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size())); if (x509 && X509_STORE_add_cert(certStore.get(), x509.get())) { // Note: X509_STORE increases the reference count to the X509 object, // we still have to release our reference to it. ++nRootCerts; } else { ReportInvalidCertificate(cert); continue; } } qWarning() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates"; // Project for another day: // Fetch certificate revocation lists, and add them to certStore. // Issues to consider: // performance (start a thread to fetch in background?) // privacy (fetch through tor/proxy so IP address isn't revealed) // would it be easier to just use a compiled-in blacklist? // or use Qt's blacklist? // "certificate stapling" with server-side caching is more efficient }
API int nc_tls_init(const char* peer_cert, const char* peer_key, const char *CAfile, const char *CApath, const char *CRLfile, const char *CRLpath) { const char* key_ = peer_key; SSL_CTX* tls_ctx; X509_LOOKUP* lookup; X509_STORE* tls_store; int destroy = 0, ret; if (peer_cert == NULL) { ERROR("%s: Invalid parameter.", __func__); return (EXIT_FAILURE); } pthread_once(&tls_ctx_once, tls_ctx_init); tls_ctx = pthread_getspecific(tls_ctx_key); if (tls_ctx) { VERB("TLS subsystem reinitiation. Resetting certificates settings"); /* * continue with creation of a new TLS context, the current will be * destroyed after everything successes */ destroy = 1; } /* prepare global SSL context, allow only mandatory TLS 1.2 */ if ((tls_ctx = SSL_CTX_new(TLSv1_2_client_method())) == NULL) { ERROR("Unable to create OpenSSL context (%s)", ERR_reason_error_string(ERR_get_error())); return (EXIT_FAILURE); } /* force peer certificate verification (NO_PEER_CERT and CLIENT_ONCE are ignored when * acting as client, but included just in case) and optionaly set CRL checking callback */ if (CRLfile != NULL || CRLpath != NULL) { /* set the revocation store with the correct paths for the callback */ tls_store = X509_STORE_new(); tls_store->cache = 0; if (CRLfile != NULL) { if ((lookup = X509_STORE_add_lookup(tls_store, X509_LOOKUP_file())) == NULL) { ERROR("Failed to add lookup method in CRL checking"); return (EXIT_FAILURE); } if (X509_LOOKUP_add_dir(lookup, CRLfile, X509_FILETYPE_PEM) != 1) { ERROR("Failed to add revocation lookup file"); return (EXIT_FAILURE); } } if (CRLpath != NULL) { if ((lookup = X509_STORE_add_lookup(tls_store, X509_LOOKUP_hash_dir())) == NULL) { ERROR("Failed to add lookup method in CRL checking"); return (EXIT_FAILURE); } if (X509_LOOKUP_add_dir(lookup, CRLpath, X509_FILETYPE_PEM) != 1) { ERROR("Failed to add revocation lookup directory"); return (EXIT_FAILURE); } } if ((ret = pthread_key_create(&tls_store_key, (void (*)(void *))X509_STORE_free)) != 0) { ERROR("Unable to create pthread key: %s", strerror(ret)); return (EXIT_FAILURE); } if ((ret = pthread_setspecific(tls_store_key, tls_store)) != 0) { ERROR("Unable to set thread-specific data: %s", strerror(ret)); return (EXIT_FAILURE); } SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_callback); } else { /* CRL checking will be skipped */ SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, NULL); } /* get peer certificate */ if (SSL_CTX_use_certificate_file(tls_ctx, peer_cert, SSL_FILETYPE_PEM) != 1) { ERROR("Loading a peer certificate from \'%s\' failed (%s).", peer_cert, ERR_reason_error_string(ERR_get_error())); return (EXIT_FAILURE); } if (key_ == NULL) { /* * if the file with private key not specified, expect that the private * key is stored altogether with the certificate */ key_ = peer_cert; } if (SSL_CTX_use_PrivateKey_file(tls_ctx, key_, SSL_FILETYPE_PEM) != 1) { ERROR("Loading a peer certificate from \'%s\' failed (%s).", key_, ERR_reason_error_string(ERR_get_error())); return (EXIT_FAILURE); } if(! SSL_CTX_load_verify_locations(tls_ctx, CAfile, CApath)) { WARN("SSL_CTX_load_verify_locations() failed (%s).", ERR_reason_error_string(ERR_get_error())); } /* store TLS context for thread */ if (destroy) { nc_tls_destroy(); } pthread_setspecific(tls_ctx_key, tls_ctx); return (EXIT_SUCCESS); }
/* 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); }
/* verify certificate */ static unsigned long verify_cert(char *userid, X509 *cert, X509 *ca_cert, STACK_OF(X509) *chain, PVFS_credentials *credentials) { X509_STORE *trust_store; X509_STORE_CTX *ctx; int ret, verify_flag = 0; int (*save_verify_cb)(int ok, X509_STORE_CTX *ctx); char error_msg[256]; /* add CA cert to trusted store */ trust_store = X509_STORE_new(); if (trust_store == NULL) { ret = OPENSSL_CERT_ERROR; goto verify_cert_exit; } ret = X509_STORE_add_cert(trust_store, ca_cert); if (!ret) { ret = OPENSSL_CERT_ERROR; goto verify_cert_exit; } /* setup the context with the certs */ ctx = X509_STORE_CTX_new();
int x509_main(int argc, char **argv) { ASN1_INTEGER *sno = NULL; ASN1_OBJECT *objtmp; BIO *out = NULL; CONF *extconf = NULL; EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL; X509 *x = NULL, *xca = NULL; X509_REQ *req = NULL, *rq = NULL; X509_STORE *ctx = NULL; const EVP_MD *digest = NULL; char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL; char *checkhost = NULL, *checkemail = NULL, *checkip = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL; char buf[256], *prog; int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0; int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0; int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0; int checkoffset = 0, enddate = 0; unsigned long nmflag = 0, certflag = 0; OPTION_CHOICE o; ENGINE *e = NULL; #ifndef OPENSSL_NO_MD5 int subject_hash_old = 0, issuer_hash_old = 0; #endif ctx = X509_STORE_new(); if (ctx == NULL) goto end; X509_STORE_set_verify_cb(ctx, callb); prog = opt_init(argc, argv, x509_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(x509_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat)) goto opthelp; break; case OPT_KEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat)) goto opthelp; break; case OPT_CAFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat)) goto opthelp; break; case OPT_CAKEYFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAkeyformat)) goto opthelp; break; case OPT_OUT: outfile = opt_arg(); break; case OPT_REQ: reqfile = need_rand = 1; break; case OPT_SIGOPT: if (!sigopts) sigopts = sk_OPENSSL_STRING_new_null(); if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg())) goto opthelp; break; #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL case OPT_FORCE_VERSION: force_version = atoi(opt_arg()) - 1; break; #endif case OPT_DAYS: days = atoi(opt_arg()); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_EXTFILE: extfile = opt_arg(); break; case OPT_EXTENSIONS: extsect = opt_arg(); break; case OPT_SIGNKEY: keyfile = opt_arg(); sign_flag = ++num; need_rand = 1; break; case OPT_CA: CAfile = opt_arg(); CA_flag = ++num; need_rand = 1; break; case OPT_CAKEY: CAkeyfile = opt_arg(); break; case OPT_CASERIAL: CAserial = opt_arg(); break; case OPT_SET_SERIAL: if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL) goto opthelp; break; case OPT_FORCE_PUBKEY: fkeyfile = opt_arg(); break; case OPT_ADDTRUST: if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { BIO_printf(bio_err, "%s: Invalid trust object value %s\n", prog, opt_arg()); goto opthelp; } if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) goto end; sk_ASN1_OBJECT_push(trust, objtmp); trustout = 1; break; case OPT_ADDREJECT: if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { BIO_printf(bio_err, "%s: Invalid reject object value %s\n", prog, opt_arg()); goto opthelp; } if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL) goto end; sk_ASN1_OBJECT_push(reject, objtmp); trustout = 1; break; case OPT_SETALIAS: alias = opt_arg(); trustout = 1; break; case OPT_CERTOPT: if (!set_cert_ex(&certflag, opt_arg())) goto opthelp; break; case OPT_NAMEOPT: if (!set_name_ex(&nmflag, opt_arg())) goto opthelp; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_C: C = ++num; break; case OPT_EMAIL: email = ++num; break; case OPT_OCSP_URI: ocsp_uri = ++num; break; case OPT_SERIAL: serial = ++num; break; case OPT_NEXT_SERIAL: next_serial = ++num; break; case OPT_MODULUS: modulus = ++num; break; case OPT_PUBKEY: pubkey = ++num; break; case OPT_X509TOREQ: x509req = ++num; break; case OPT_TEXT: text = ++num; break; case OPT_SUBJECT: subject = ++num; break; case OPT_ISSUER: issuer = ++num; break; case OPT_FINGERPRINT: fingerprint = ++num; break; case OPT_HASH: subject_hash = ++num; break; case OPT_ISSUER_HASH: issuer_hash = ++num; break; case OPT_PURPOSE: pprint = ++num; break; case OPT_STARTDATE: startdate = ++num; break; case OPT_ENDDATE: enddate = ++num; break; case OPT_NOOUT: noout = ++num; break; case OPT_NOCERT: nocert = 1; break; case OPT_TRUSTOUT: trustout = 1; break; case OPT_CLRTRUST: clrtrust = ++num; break; case OPT_CLRREJECT: clrreject = ++num; break; case OPT_ALIAS: aliasout = ++num; break; case OPT_CACREATESERIAL: CA_createserial = ++num; break; case OPT_CLREXT: clrext = 1; break; case OPT_OCSPID: ocspid = ++num; break; case OPT_BADSIG: badsig = 1; break; #ifndef OPENSSL_NO_MD5 case OPT_SUBJECT_HASH_OLD: subject_hash_old = ++num; break; case OPT_ISSUER_HASH_OLD: issuer_hash_old = ++num; break; #endif case OPT_DATES: startdate = ++num; enddate = ++num; break; case OPT_CHECKEND: checkoffset = atoi(opt_arg()); checkend = 1; break; case OPT_CHECKHOST: checkhost = opt_arg(); break; case OPT_CHECKEMAIL: checkemail = opt_arg(); break; case OPT_CHECKIP: checkip = opt_arg(); break; case OPT_MD: if (!opt_md(opt_unknown(), &digest)) goto opthelp; } } argc = opt_num_rest(); argv = opt_rest(); if (argc != 0) { BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]); goto opthelp; } out = bio_open_default(outfile, "w"); if (out == NULL) goto end; if (need_rand) app_RAND_load_file(NULL, 0); if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } if (!X509_STORE_set_default_paths(ctx)) { ERR_print_errors(bio_err); goto end; } if (fkeyfile) { fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key"); if (fkey == NULL) goto end; } if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) { CAkeyfile = CAfile; } else if ((CA_flag) && (CAkeyfile == NULL)) { BIO_printf(bio_err, "need to specify a CAkey if using the CA command\n"); goto end; } if (extfile) { long errorline = -1; X509V3_CTX ctx2; extconf = NCONF_new(NULL); if (!NCONF_load(extconf, extfile, &errorline)) { if (errorline <= 0) BIO_printf(bio_err, "error loading the config file '%s'\n", extfile); else BIO_printf(bio_err, "error on line %ld of config file '%s'\n", errorline, extfile); goto end; } if (!extsect) { extsect = NCONF_get_string(extconf, "default", "extensions"); if (!extsect) { ERR_clear_error(); extsect = "default"; } } X509V3_set_ctx_test(&ctx2); X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error Loading extension section %s\n", extsect); ERR_print_errors(bio_err); goto end; } } if (reqfile) { EVP_PKEY *pkey; BIO *in; if (!sign_flag && !CA_flag) { BIO_printf(bio_err, "We need a private key to sign with\n"); goto end; } in = bio_open_default(infile, "r"); if (in == NULL) goto end; req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); BIO_free(in); if (req == NULL) { ERR_print_errors(bio_err); goto end; } if ((req->req_info == NULL) || (req->req_info->pubkey == NULL) || (req->req_info->pubkey->public_key == NULL) || (req->req_info->pubkey->public_key->data == NULL)) { BIO_printf(bio_err, "The certificate request appears to corrupted\n"); BIO_printf(bio_err, "It does not contain a public key\n"); goto end; } if ((pkey = X509_REQ_get_pubkey(req)) == NULL) { BIO_printf(bio_err, "error unpacking public key\n"); goto end; } i = X509_REQ_verify(req, pkey); EVP_PKEY_free(pkey); if (i < 0) { BIO_printf(bio_err, "Signature verification error\n"); ERR_print_errors(bio_err); goto end; } if (i == 0) { BIO_printf(bio_err, "Signature did not match the certificate request\n"); goto end; } else BIO_printf(bio_err, "Signature ok\n"); print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag); if ((x = X509_new()) == NULL) goto end; if (sno == NULL) { sno = ASN1_INTEGER_new(); if (!sno || !rand_serial(NULL, sno)) goto end; if (!X509_set_serialNumber(x, sno)) goto end; ASN1_INTEGER_free(sno); sno = NULL; } else if (!X509_set_serialNumber(x, sno)) goto end; if (!X509_set_issuer_name(x, req->req_info->subject)) goto end; if (!X509_set_subject_name(x, req->req_info->subject)) goto end; X509_gmtime_adj(X509_get_notBefore(x), 0); X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL); if (fkey) X509_set_pubkey(x, fkey); else { pkey = X509_REQ_get_pubkey(req); X509_set_pubkey(x, pkey); EVP_PKEY_free(pkey); } } else x = load_cert(infile, informat, NULL, e, "Certificate"); if (x == NULL) goto end; if (CA_flag) { xca = load_cert(CAfile, CAformat, NULL, e, "CA Certificate"); if (xca == NULL) goto end; } if (!noout || text || next_serial) { OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); } if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); if (clrtrust) X509_trust_clear(x); if (clrreject) X509_reject_clear(x); if (trust) { for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { objtmp = sk_ASN1_OBJECT_value(trust, i); X509_add1_trust_object(x, objtmp); } } if (reject) { for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { objtmp = sk_ASN1_OBJECT_value(reject, i); X509_add1_reject_object(x, objtmp); } } if (num) { for (i = 1; i <= num; i++) { if (issuer == i) { print_name(out, "issuer= ", X509_get_issuer_name(x), nmflag); } else if (subject == i) { print_name(out, "subject= ", X509_get_subject_name(x), nmflag); } else if (serial == i) { BIO_printf(out, "serial="); i2a_ASN1_INTEGER(out, X509_get_serialNumber(x)); BIO_printf(out, "\n"); } else if (next_serial == i) { BIGNUM *bnser; ASN1_INTEGER *ser; ser = X509_get_serialNumber(x); bnser = ASN1_INTEGER_to_BN(ser, NULL); if (!bnser) goto end; if (!BN_add_word(bnser, 1)) goto end; ser = BN_to_ASN1_INTEGER(bnser, NULL); if (!ser) goto end; BN_free(bnser); i2a_ASN1_INTEGER(out, ser); ASN1_INTEGER_free(ser); BIO_puts(out, "\n"); } else if ((email == i) || (ocsp_uri == i)) { int j; STACK_OF(OPENSSL_STRING) *emlst; if (email == i) emlst = X509_get1_email(x); else emlst = X509_get1_ocsp(x); for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); X509_email_free(emlst); } else if (aliasout == i) { unsigned char *alstr; alstr = X509_alias_get0(x, NULL); if (alstr) BIO_printf(out, "%s\n", alstr); else BIO_puts(out, "<No Alias>\n"); } else if (subject_hash == i) { BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (subject_hash_old == i) { BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); } #endif else if (issuer_hash == i) { BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); } #ifndef OPENSSL_NO_MD5 else if (issuer_hash_old == i) { BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); } #endif else if (pprint == i) { X509_PURPOSE *ptmp; int j; BIO_printf(out, "Certificate purposes:\n"); for (j = 0; j < X509_PURPOSE_get_count(); j++) { ptmp = X509_PURPOSE_get0(j); purpose_print(out, x, ptmp); } } else if (modulus == i) { EVP_PKEY *pkey; pkey = X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Modulus=unavailable\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(out, "Modulus="); #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) BN_print(out, pkey->pkey.rsa->n); else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) BN_print(out, pkey->pkey.dsa->pub_key); else #endif BIO_printf(out, "Wrong Algorithm type"); BIO_printf(out, "\n"); EVP_PKEY_free(pkey); } else if (pubkey == i) { EVP_PKEY *pkey; pkey = X509_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); ERR_print_errors(bio_err); goto end; } PEM_write_bio_PUBKEY(out, pkey); EVP_PKEY_free(pkey); } else if (C == i) { unsigned char *d; char *m; int len; X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf); BIO_printf(out, "/*\n" " * Subject: %s\n", buf); m = X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf); BIO_printf(out, " * Issuer: %s\n" " */\n", buf); len = i2d_X509(x, NULL); m = app_malloc(len, "x509 name buffer"); d = (unsigned char *)m; len = i2d_X509_NAME(X509_get_subject_name(x), &d); print_array(out, "the_subject_name", len, (unsigned char *)m); d = (unsigned char *)m; len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d); print_array(out, "the_public_key", len, (unsigned char *)m); d = (unsigned char *)m; len = i2d_X509(x, &d); print_array(out, "the_certificate", len, (unsigned char *)m); OPENSSL_free(m); } else if (text == i) { X509_print_ex(out, x, nmflag, certflag); } else if (startdate == i) { BIO_puts(out, "notBefore="); ASN1_TIME_print(out, X509_get_notBefore(x)); BIO_puts(out, "\n"); } else if (enddate == i) { BIO_puts(out, "notAfter="); ASN1_TIME_print(out, X509_get_notAfter(x)); BIO_puts(out, "\n"); } else if (fingerprint == i) { int j; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; const EVP_MD *fdig = digest; if (!fdig) fdig = EVP_sha1(); if (!X509_digest(x, fdig, md, &n)) { BIO_printf(bio_err, "out of memory\n"); goto end; } BIO_printf(out, "%s Fingerprint=", OBJ_nid2sn(EVP_MD_type(fdig))); for (j = 0; j < (int)n; j++) { BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); } } /* should be in the library */ else if ((sign_flag == i) && (x509req == 0)) { BIO_printf(bio_err, "Getting Private key\n"); if (Upkey == NULL) { Upkey = load_key(keyfile, keyformat, 0, passin, e, "Private key"); if (Upkey == NULL) goto end; } assert(need_rand); if (!sign(x, Upkey, days, clrext, digest, extconf, extsect)) goto end; } else if (CA_flag == i) { BIO_printf(bio_err, "Getting CA Private Key\n"); if (CAkeyfile != NULL) { CApkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA Private Key"); if (CApkey == NULL) goto end; } assert(need_rand); if (!x509_certify(ctx, CAfile, digest, x, xca, CApkey, sigopts, CAserial, CA_createserial, days, clrext, extconf, extsect, sno, reqfile)) goto end; } else if (x509req == i) { EVP_PKEY *pk; BIO_printf(bio_err, "Getting request Private Key\n"); if (keyfile == NULL) { BIO_printf(bio_err, "no request key file specified\n"); goto end; } else { pk = load_key(keyfile, keyformat, 0, passin, e, "request key"); if (pk == NULL) goto end; } BIO_printf(bio_err, "Generating certificate request\n"); rq = X509_to_X509_REQ(x, pk, digest); EVP_PKEY_free(pk); if (rq == NULL) { ERR_print_errors(bio_err); goto end; } if (!noout) { X509_REQ_print(out, rq); PEM_write_bio_X509_REQ(out, rq); } noout = 1; } else if (ocspid == i) { X509_ocspid_print(out, x); } } } if (checkend) { time_t tcheck = time(NULL) + checkoffset; if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) { BIO_printf(out, "Certificate will expire\n"); ret = 1; } else { BIO_printf(out, "Certificate will not expire\n"); ret = 0; } goto end; } print_cert_checks(out, x, checkhost, checkemail, checkip); if (noout || nocert) { ret = 0; goto end; } if (badsig) x->signature->data[x->signature->length - 1] ^= 0x1; if (outformat == FORMAT_ASN1) i = i2d_X509_bio(out, x); else if (outformat == FORMAT_PEM) { if (trustout) i = PEM_write_bio_X509_AUX(out, x); else i = PEM_write_bio_X509(out, x); } else if (outformat == FORMAT_NETSCAPE) { NETSCAPE_X509 nx; ASN1_OCTET_STRING hdr; hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; hdr.length = strlen(NETSCAPE_CERT_HDR); nx.header = &hdr; nx.cert = x; i = ASN1_item_i2d_bio(ASN1_ITEM_rptr(NETSCAPE_X509), out, &nx); } else { BIO_printf(bio_err, "bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err, "unable to write certificate\n"); ERR_print_errors(bio_err); goto end; } ret = 0; end: if (need_rand) app_RAND_write_file(NULL); OBJ_cleanup(); NCONF_free(extconf); BIO_free_all(out); X509_STORE_free(ctx); X509_REQ_free(req); X509_free(x); X509_free(xca); EVP_PKEY_free(Upkey); EVP_PKEY_free(CApkey); EVP_PKEY_free(fkey); sk_OPENSSL_STRING_free(sigopts); X509_REQ_free(rq); ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); OPENSSL_free(passin); return (ret); }
static int do_ca_cert_bootstrap(struct stream *stream) { struct ssl_stream *sslv = ssl_stream_cast(stream); STACK_OF(X509) *chain; X509 *cert; FILE *file; int error; int fd; chain = SSL_get_peer_cert_chain(sslv->ssl); if (!chain || !sk_X509_num(chain)) { VLOG_ERR("could not bootstrap CA cert: no certificate presented by " "peer"); return EPROTO; } cert = sk_X509_value(chain, sk_X509_num(chain) - 1); /* Check that 'cert' is self-signed. Otherwise it is not a CA * certificate and we should not attempt to use it as one. */ error = X509_check_issued(cert, cert); if (error) { VLOG_ERR("could not bootstrap CA cert: obtained certificate is " "not self-signed (%s)", X509_verify_cert_error_string(error)); if (sk_X509_num(chain) < 2) { VLOG_ERR("only one certificate was received, so probably the peer " "is not configured to send its CA certificate"); } return EPROTO; } fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { if (errno == EEXIST) { VLOG_INFO_RL(&rl, "reading CA cert %s created by another process", ca_cert.file_name); stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true); return EPROTO; } else { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", ca_cert.file_name, ovs_strerror(errno)); return errno; } } file = fdopen(fd, "w"); if (!file) { error = errno; VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", ovs_strerror(error)); unlink(ca_cert.file_name); return error; } if (!PEM_write_X509(file, cert)) { VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " "%s", ca_cert.file_name, ERR_error_string(ERR_get_error(), NULL)); fclose(file); unlink(ca_cert.file_name); return EIO; } if (fclose(file)) { error = errno; VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", ca_cert.file_name, ovs_strerror(error)); unlink(ca_cert.file_name); return error; } VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name); log_ca_cert(ca_cert.file_name, cert); bootstrap_ca_cert = false; ca_cert.read = true; /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */ SSL_CTX_add_client_CA(ctx, cert); SSL_CTX_set_cert_store(ctx, X509_STORE_new()); if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) { VLOG_ERR("SSL_CTX_load_verify_locations: %s", ERR_error_string(ERR_get_error(), NULL)); return EPROTO; } VLOG_INFO("killing successful connection to retry using CA cert"); return EPROTO; }