static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY *pkey; int i; pkey = X509_get0_pubkey(x); if (pkey == NULL) { SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB); return (0); } i = ssl_cert_type(x, pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return 0; } #ifndef OPENSSL_NO_EC if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) { SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING); return 0; } #endif if (c->pkeys[i].privatekey != NULL) { /* * The return code from EVP_PKEY_copy_parameters is deliberately * ignored. Some EVP_PKEY types cannot do this. */ EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* * Don't check the public/private key, this is mostly for smart * cards. */ if (EVP_PKEY_id(c->pkeys[i].privatekey) == EVP_PKEY_RSA && RSA_flags(EVP_PKEY_get0_RSA(c->pkeys[i].privatekey)) & RSA_METHOD_FLAG_NO_CHECK) ; else #endif /* OPENSSL_NO_RSA */ if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { /* * don't fail for a cert/key mismatch, just free current private * key (when switching to a different cert & key, first this * function should be used, then ssl_set_pkey */ EVP_PKEY_free(c->pkeys[i].privatekey); c->pkeys[i].privatekey = NULL; /* clear error queue */ ERR_clear_error(); } } X509_free(c->pkeys[i].x509); X509_up_ref(x); c->pkeys[i].x509 = x; c->key = &(c->pkeys[i]); return 1; }
static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY *pkey; int i; pkey = X509_get_pubkey(x); if (pkey == NULL) { SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB); return (0); } i = ssl_cert_type(x, pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pkey); return (0); } if (c->pkeys[i].privatekey != NULL) { /* * The return code from EVP_PKEY_copy_parameters is deliberately * ignored. Some EVP_PKEY types cannot do this. */ EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* * Don't check the public/private key, this is mostly for smart * cards. */ if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ; else #endif /* OPENSSL_NO_RSA */ if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { /* * don't fail for a cert/key mismatch, just free current private * key (when switching to a different cert & key, first this * function should be used, then ssl_set_pkey */ EVP_PKEY_free(c->pkeys[i].privatekey); c->pkeys[i].privatekey = NULL; /* clear error queue */ ERR_clear_error(); } } EVP_PKEY_free(pkey); if (c->pkeys[i].x509 != NULL) X509_free(c->pkeys[i].x509); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); c->pkeys[i].x509 = x; c->key = &(c->pkeys[i]); c->valid = 0; return (1); }
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i; /* Special case for DH: check two DH certificate types for a match. * This means for DH certificates we must set the certificate first. */ if (pkey->type == EVP_PKEY_DH) { X509 *x; i = -1; x = c->pkeys[SSL_PKEY_DH_RSA].x509; if (x && X509_check_private_key(x, pkey)) i = SSL_PKEY_DH_RSA; x = c->pkeys[SSL_PKEY_DH_DSA].x509; if (i == -1 && x && X509_check_private_key(x, pkey)) i = SSL_PKEY_DH_DSA; ERR_clear_error(); } else i=ssl_cert_type(NULL,pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE); return(0); } if (c->pkeys[i].x509 != NULL) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(c->pkeys[i].x509); EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_free(pktmp); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* Don't check the public/private key, this is mostly * for smart cards. */ if ((pkey->type == EVP_PKEY_RSA) && (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ; else #endif if (!X509_check_private_key(c->pkeys[i].x509,pkey)) { X509_free(c->pkeys[i].x509); c->pkeys[i].x509 = NULL; return 0; } } if (c->pkeys[i].privatekey != NULL) EVP_PKEY_free(c->pkeys[i].privatekey); CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); c->pkeys[i].privatekey=pkey; c->key= &(c->pkeys[i]); c->valid=0; return(1); }
static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY *pkey; int i; pkey = X509_get_pubkey(x); if (pkey == NULL) { SSLerrorx(SSL_R_X509_LIB); return (0); } i = ssl_cert_type(x, pkey); if (i < 0) { SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pkey); return (0); } if (c->pkeys[i].privatekey != NULL) { EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); ERR_clear_error(); /* * Don't check the public/private key, this is mostly * for smart cards. */ if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ; else if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { /* * don't fail for a cert/key mismatch, just free * current private key (when switching to a different * cert & key, first this function should be used, * then ssl_set_pkey */ EVP_PKEY_free(c->pkeys[i].privatekey); c->pkeys[i].privatekey = NULL; /* clear error queue */ ERR_clear_error(); } } EVP_PKEY_free(pkey); X509_free(c->pkeys[i].x509); CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); c->pkeys[i].x509 = x; c->key = &(c->pkeys[i]); c->valid = 0; return (1); }
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i; i = ssl_cert_type(NULL, pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return (0); } #ifndef OPENSSL_NO_GMTLS if (i == SSL_PKEY_SM2 && c->pkeys[SSL_PKEY_SM2_ENC].x509) i = SSL_PKEY_SM2_ENC; #endif if (c->pkeys[i].x509 != NULL) { EVP_PKEY *pktmp; pktmp = X509_get0_pubkey(c->pkeys[i].x509); if (pktmp == NULL) { SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE); return 0; } /* * The return code from EVP_PKEY_copy_parameters is deliberately * ignored. Some EVP_PKEY types cannot do this. */ EVP_PKEY_copy_parameters(pktmp, pkey); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* * Don't check the public/private key, this is mostly for smart * cards. */ if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK) ; else #endif if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { X509_free(c->pkeys[i].x509); c->pkeys[i].x509 = NULL; return 0; } } EVP_PKEY_free(c->pkeys[i].privatekey); EVP_PKEY_up_ref(pkey); c->pkeys[i].privatekey = pkey; c->key = &(c->pkeys[i]); return (1); }
static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DH *dh = NULL; if (ctx->pkey == NULL) { DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET); return 0; } dh = DH_new(); if (!dh) return 0; EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); /* Note: if error return, pkey is freed by parent routine */ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) return 0; return DH_generate_key(pkey->pkey.dh); }
static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DSA *dsa = NULL; if (ctx->pkey == NULL) { DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET); return 0; } dsa = DSA_new(); if (dsa == NULL) return 0; EVP_PKEY_assign_DSA(pkey, dsa); /* Note: if error return, pkey is freed by parent routine */ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) return 0; return DSA_generate_key(pkey->pkey.dsa); }
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i; i = ssl_cert_type(NULL, pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return (0); } if (c->pkeys[i].x509 != NULL) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(c->pkeys[i].x509); if (pktmp == NULL) { SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE); EVP_PKEY_free(pktmp); return 0; } /* * The return code from EVP_PKEY_copy_parameters is deliberately * ignored. Some EVP_PKEY types cannot do this. */ EVP_PKEY_copy_parameters(pktmp, pkey); EVP_PKEY_free(pktmp); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* * Don't check the public/private key, this is mostly for smart * cards. */ if ((pkey->type == EVP_PKEY_RSA) && (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ; else #endif if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { X509_free(c->pkeys[i].x509); c->pkeys[i].x509 = NULL; return 0; } } EVP_PKEY_free(c->pkeys[i].privatekey); CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); c->pkeys[i].privatekey = pkey; c->key = &(c->pkeys[i]); return (1); }
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { EC_KEY *ec = NULL; if (ctx->pkey == NULL) { ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); return 0; } ec = EC_KEY_new(); if (!ec) return 0; EVP_PKEY_assign_EC_KEY(pkey, ec); /* Note: if error return, pkey is freed by parent routine */ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) return 0; return EC_KEY_generate_key(pkey->pkey.ec); }
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i; i = ssl_cert_type(NULL, pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); return (0); } if (c->pkeys[i].x509 != NULL) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(c->pkeys[i].x509); EVP_PKEY_copy_parameters(pktmp, pkey); EVP_PKEY_free(pktmp); ERR_clear_error(); /* * Don't check the public/private key, this is mostly * for smart cards. */ if ((pkey->type == EVP_PKEY_RSA) && (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ; else if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { X509_free(c->pkeys[i].x509); c->pkeys[i].x509 = NULL; return 0; } } if (c->pkeys[i].privatekey != NULL) EVP_PKEY_free(c->pkeys[i].privatekey); CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); c->pkeys[i].privatekey = pkey; c->key = &(c->pkeys[i]); c->valid = 0; return (1); }
/* self sign */ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, CONF *conf, char *section) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(x); EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_save_parameters(pktmp,1); EVP_PKEY_free(pktmp); if (!X509_set_issuer_name(x,X509_get_subject_name(x))) goto err; if (X509_gmtime_adj(X509_get_notBefore(x),0) == NULL) goto err; /* Lets just make it 12:00am GMT, Jan 1 1970 */ /* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */ /* 28 days to be certified */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto err; if (!X509_set_pubkey(x,pkey)) goto err; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0); X509V3_set_nconf(&ctx, conf); if (!X509V3_EXT_add_nconf(conf, &ctx, section, x)) goto err; } if (!X509_sign(x,pkey,digest)) goto err; return 1; err: ERR_print_errors(bio_err); return 0; }
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { EC_KEY *ec = NULL; EC_PKEY_CTX *dctx = ctx->data; if (ctx->pkey == NULL && dctx->gen_group == NULL) { ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET); return 0; } ec = EC_KEY_new(); if (!ec) return 0; EVP_PKEY_assign_EC_KEY(pkey, ec); if (ctx->pkey != NULL) { /* Note: if error return, pkey is freed by parent routine */ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) return 0; } else { if (!EC_KEY_set_group(ec, dctx->gen_group)) return 0; } return EC_KEY_generate_key(pkey->pkey.ec); }
int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key, size_t key_len) { GOST_KEY_TRANSPORT *gkt = NULL; EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); const struct gost_cipher_info *param = get_encryption_params(NULL); unsigned char ukm[8], shared_key[32], crypted_key[44]; int ret = 0; int key_is_ephemeral = 1; gost_ctx cctx; EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx); if (data->shared_ukm) { memcpy(ukm, data->shared_ukm, 8); } else if (out) { if (RAND_bytes(ukm, 8) <= 0) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); return 0; } } /* Check for private key in the peer_key of context */ if (sec_key) { key_is_ephemeral = 0; if (!gost_get0_priv_key(sec_key)) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { key_is_ephemeral = 1; if (out) { sec_key = EVP_PKEY_new(); EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk), EC_KEY_new()); EVP_PKEY_copy_parameters(sec_key, pubk); if (!gost2001_keygen(EVP_PKEY_get0(sec_key))) { goto err; } } } if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param = gost_cipher_list + 1; } if (out) { VKO_compute_key(shared_key, 32, EC_KEY_get0_public_key(EVP_PKEY_get0(pubk)), EVP_PKEY_get0(sec_key), ukm); gost_init(&cctx, param->sblock); keyWrapCryptoPro(&cctx, shared_key, ukm, key, crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8)) { goto err; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40, 4)) { goto err; } if (!ASN1_OCTET_STRING_set (gkt->key_info->encrypted_key, crypted_key + 8, 32)) { goto err; } if (key_is_ephemeral) { if (!X509_PUBKEY_set (&gkt->key_agreement_info->ephem_key, out ? sec_key : pubk)) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); if (key_is_ephemeral) EVP_PKEY_free(sec_key); if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0) ret = 1; GOST_KEY_TRANSPORT_free(gkt); return ret; err: if (key_is_ephemeral) EVP_PKEY_free(sec_key); GOST_KEY_TRANSPORT_free(gkt); return -1; }
static void setup_ssl(tcptest_t *item) { static int ssl_init_complete = 0; struct servent *sp; char portinfo[100]; X509 *peercert; char *certcn, *certstart, *certend; int err; strbuffer_t *sslinfo; char msglin[2048]; item->sslrunning = 1; if (!ssl_init_complete) { /* Setup entropy */ if (RAND_status() != 1) { char path[PATH_MAX]; /* Path for the random file */ /* load entropy from files */ RAND_load_file(RAND_file_name(path, sizeof (path)), -1); /* load entropy from egd sockets */ RAND_egd("/var/run/egd-pool"); RAND_egd("/dev/egd-pool"); RAND_egd("/etc/egd-pool"); RAND_egd("/var/spool/prngd/pool"); /* shuffle $RANDFILE (or ~/.rnd if unset) */ RAND_write_file(RAND_file_name(path, sizeof (path))); if (RAND_status() != 1) { errprintf("Failed to find enough entropy on your system"); item->errcode = CONTEST_ESSL; return; } } SSL_load_error_strings(); SSL_library_init(); ssl_init_complete = 1; } if (item->sslctx == NULL) { switch (item->ssloptions->sslversion) { case SSLVERSION_V2: item->sslctx = SSL_CTX_new(SSLv2_client_method()); break; case SSLVERSION_V3: item->sslctx = SSL_CTX_new(SSLv3_client_method()); break; case SSLVERSION_TLS1: item->sslctx = SSL_CTX_new(TLSv1_client_method()); break; default: item->sslctx = SSL_CTX_new(SSLv23_client_method()); break; } if (!item->sslctx) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Cannot create SSL context - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } /* Workaround SSL bugs */ SSL_CTX_set_options(item->sslctx, SSL_OP_ALL); SSL_CTX_set_quiet_shutdown(item->sslctx, 1); /* Limit set of ciphers, if user wants to */ if (item->ssloptions->cipherlist) SSL_CTX_set_cipher_list(item->sslctx, item->ssloptions->cipherlist); if (item->ssloptions->clientcert) { int status; char certfn[PATH_MAX]; SSL_CTX_set_default_passwd_cb(item->sslctx, cert_password_cb); SSL_CTX_set_default_passwd_cb_userdata(item->sslctx, item); sprintf(certfn, "%s/certs/%s", xgetenv("XYMONHOME"), item->ssloptions->clientcert); status = SSL_CTX_use_certificate_chain_file(item->sslctx, certfn); if (status == 1) { status = SSL_CTX_use_PrivateKey_file(item->sslctx, certfn, SSL_FILETYPE_PEM); } if (status != 1) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Cannot load SSL client certificate/key %s: %s\n", item->ssloptions->clientcert, sslerrmsg); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } } } if (item->ssldata == NULL) { item->ssldata = SSL_new(item->sslctx); if (!item->ssldata) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("SSL_new failed - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; SSL_CTX_free(item->sslctx); item->errcode = CONTEST_ESSL; return; } /* Verify that the client certificate is working */ if (item->ssloptions->clientcert) { X509 *x509; x509 = SSL_get_certificate(item->ssldata); if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(item->ssldata)); EVP_PKEY_free(pktmp); } if (!SSL_CTX_check_private_key(item->sslctx)) { errprintf("Private/public key mismatch for certificate %s\n", item->ssloptions->clientcert); item->sslrunning = 0; item->errcode = CONTEST_ESSL; return; } } /* SSL setup is done. Now attach the socket FD to the SSL protocol handler */ if (SSL_set_fd(item->ssldata, item->fd) != 1) { char sslerrmsg[256]; ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Could not initiate SSL on connection - IP %s, service %s: %s\n", inet_ntoa(item->addr.sin_addr), item->svcinfo->svcname, sslerrmsg); item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); item->errcode = CONTEST_ESSL; return; } } sp = getservbyport(item->addr.sin_port, "tcp"); if (sp) { sprintf(portinfo, "%s (%d/tcp)", sp->s_name, item->addr.sin_port); } else { sprintf(portinfo, "%d/tcp", item->addr.sin_port); } if ((err = SSL_connect(item->ssldata)) != 1) { char sslerrmsg[256]; switch (SSL_get_error (item->ssldata, err)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: item->sslrunning = SSLSETUP_PENDING; break; case SSL_ERROR_SYSCALL: ERR_error_string(ERR_get_error(), sslerrmsg); /* Filter out the bogus SSL error */ if (strstr(sslerrmsg, "error:00000000:") == NULL) { errprintf("IO error in SSL_connect to %s on host %s: %s\n", portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); } item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; case SSL_ERROR_SSL: ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Unspecified SSL error in SSL_connect to %s on host %s: %s\n", portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; default: ERR_error_string(ERR_get_error(), sslerrmsg); errprintf("Unknown error %d in SSL_connect to %s on host %s: %s\n", err, portinfo, inet_ntoa(item->addr.sin_addr), sslerrmsg); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); break; } return; } /* If we get this far, the SSL handshake has completed. So grab the certificate */ peercert = SSL_get_peer_certificate(item->ssldata); if (!peercert) { errprintf("Cannot get peer certificate for %s on host %s\n", portinfo, inet_ntoa(item->addr.sin_addr)); item->errcode = CONTEST_ESSL; item->sslrunning = 0; SSL_free(item->ssldata); SSL_CTX_free(item->sslctx); return; } sslinfo = newstrbuffer(0); certcn = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0); certstart = strdup(xymon_ASN1_UTCTIME(X509_get_notBefore(peercert))); certend = strdup(xymon_ASN1_UTCTIME(X509_get_notAfter(peercert))); snprintf(msglin, sizeof(msglin), "Server certificate:\n\tsubject:%s\n\tstart date: %s\n\texpire date:%s\n", certcn, certstart, certend); addtobuffer(sslinfo, msglin); item->certsubject = strdup(certcn); item->certexpires = sslcert_expiretime(certend); xfree(certcn); xfree(certstart); xfree(certend); X509_free(peercert); /* We list the available ciphers in the SSL cert data */ { int i; STACK_OF(SSL_CIPHER) *sk; addtobuffer(sslinfo, "\nAvailable ciphers:\n"); sk = SSL_get_ciphers(item->ssldata); for (i=0; i<sk_SSL_CIPHER_num(sk); i++) { int b1, b2; char *cph; b1 = SSL_CIPHER_get_bits(sk_SSL_CIPHER_value(sk,i), &b2); cph = SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk,i)); snprintf(msglin, sizeof(msglin), "Cipher %d: %s (%d bits)\n", i, cph, b1); addtobuffer(sslinfo, msglin); if ((item->mincipherbits == 0) || (b1 < item->mincipherbits)) item->mincipherbits = b1; } } item->certinfo = grabstrbuffer(sslinfo); }
static int cert_stuff(struct connectdata *conn, char *cert_file, const char *cert_type, char *key_file, const char *key_type) { struct SessionHandle *data = conn->data; int file_type; if (cert_file != NULL) { SSL *ssl; X509 *x509; if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ strcpy(global_passwd, data->set.key_passwd); #else /* * We set the password in the callback userdata */ SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, data->set.key_passwd); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback); } #if 0 if (SSL_CTX_use_certificate_file(conn->ssl.ctx, cert_file, SSL_FILETYPE_PEM) != 1) { failf(data, "unable to set certificate file (wrong password?)"); return(0); } if (key_file == NULL) key_file=cert_file; if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, key_file, SSL_FILETYPE_PEM) != 1) { failf(data, "unable to set public key file"); return(0); } #else /* The '#ifdef 0' section above was removed on 17-dec-2001 */ file_type = do_file_type(cert_type); switch(file_type) { case SSL_FILETYPE_PEM: case SSL_FILETYPE_ASN1: if (SSL_CTX_use_certificate_file(conn->ssl.ctx, cert_file, file_type) != 1) { failf(data, "unable to set certificate file (wrong password?)"); return 0; } break; case SSL_FILETYPE_ENGINE: failf(data, "file type ENG for certificate not implemented"); return 0; default: failf(data, "not supported file type '%s' for certificate", cert_type); return 0; } file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if (key_file == NULL) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; case SSL_FILETYPE_ASN1: if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, key_file, file_type) != 1) { failf(data, "unable to set private key file\n"); return 0; } break; case SSL_FILETYPE_ENGINE: #ifdef HAVE_OPENSSL_ENGINE_H { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if (conn && conn->data && conn->data->engine) { if (!key_file || !key_file[0]) { failf(data, "no key set to load from crypto engine\n"); return 0; } priv_key = ENGINE_load_private_key(conn->data->engine,key_file, data->set.key_passwd); if (!priv_key) { failf(data, "failed to load private key from crypto engine\n"); return 0; } if (SSL_CTX_use_PrivateKey(conn->ssl.ctx, priv_key) != 1) { failf(data, "unable to set private key\n"); EVP_PKEY_free(priv_key); return 0; } EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ } else { failf(data, "crypto engine not set, can't load private key\n"); return 0; } } #else failf(data, "file type ENG for private key not supported\n"); return 0; #endif break; default: failf(data, "not supported file type for private key\n"); return 0; } #endif ssl=SSL_new(conn->ssl.ctx); x509=SSL_get_certificate(ssl); if (x509 != NULL) EVP_PKEY_copy_parameters(X509_get_pubkey(x509), SSL_get_privatekey(ssl)); SSL_free(ssl); /* If we are using DSA, we can copy the parameters from * the private key */ /* Now we know that a key and cert have been set against * the SSL context */ if (!SSL_CTX_check_private_key(conn->ssl.ctx)) { failf(data, "Private key does not match the certificate public key"); return(0); } #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* erase it now */ memset(global_passwd, 0, sizeof(global_passwd)); #endif } return(1); }
static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY *pkey; int i; pkey=X509_get_pubkey(x); if (pkey == NULL) { SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB); return(0); } i=ssl_cert_type(x,pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pkey); return(0); } if (c->pkeys[i].privatekey != NULL) { EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* Don't check the public/private key, this is mostly * for smart cards. */ if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ; else #endif /* OPENSSL_NO_RSA */ if (!X509_check_private_key(x,c->pkeys[i].privatekey)) { /* don't fail for a cert/key mismatch, just free * current private key (when switching to a different * cert & key, first this function should be used, * then ssl_set_pkey */ EVP_PKEY_free(c->pkeys[i].privatekey); c->pkeys[i].privatekey=NULL; /* clear error queue */ ERR_clear_error(); } } EVP_PKEY_free(pkey); if (c->pkeys[i].x509 != NULL) X509_free(c->pkeys[i].x509); CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); c->pkeys[i].x509=x; #ifndef OPENSSL_NO_TLSEXT /* Free the old authz data, if it exists. */ if (c->pkeys[i].authz != NULL) { OPENSSL_free(c->pkeys[i].authz); c->pkeys[i].authz = NULL; c->pkeys[i].authz_length = 0; } /* Free the old serverinfo data, if it exists. */ if (c->pkeys[i].serverinfo != NULL) { OPENSSL_free(c->pkeys[i].serverinfo); c->pkeys[i].serverinfo = NULL; c->pkeys[i].serverinfo_length = 0; } #endif c->key= &(c->pkeys[i]); c->valid=0; return(1); }
int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ) { GOST_KEY_TRANSPORT *gkt=NULL; unsigned char shared_key[32], ukm[8],crypted_key[44]; const struct gost_cipher_info *param=get_encryption_params(NULL); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); struct gost_pmeth_data *data = (gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); gost_ctx cctx; int key_is_ephemeral=1; EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx); /* Do not use vizir cipher parameters with cryptopro */ if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list) { param= gost_cipher_list+1; } if (mykey) { /* If key already set, it is not ephemeral */ key_is_ephemeral=0; if (!gost_get0_priv_key(mykey)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR); goto err; } } else { /* Otherwise generate ephemeral key */ key_is_ephemeral = 1; if (out) { mykey = EVP_PKEY_new(); EVP_PKEY_assign(mykey, EVP_PKEY_base_id(pubk),DSA_new()); EVP_PKEY_copy_parameters(mykey,pubk); if (!gost_sign_keygen((DSA*)EVP_PKEY_get0(mykey))) { goto err; } } } if (out) make_cp_exchange_key(gost_get0_priv_key(mykey),pubk,shared_key); if (data->shared_ukm) { TINYCLR_SSL_MEMCPY(ukm,data->shared_ukm,8); } else if (out) { if (RAND_bytes(ukm,8)<=0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_RANDOM_GENERATOR_FAILURE); goto err; } } if (out) { gost_init(&cctx,param->sblock); keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); } gkt = GOST_KEY_TRANSPORT_new(); if (!gkt) { goto memerr; } if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm,8)) { goto memerr; } if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { goto memerr; } if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { goto memerr; } if (key_is_ephemeral) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,out?mykey:pubk)) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); goto err; } if (out) EVP_PKEY_free(mykey); } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,out?&out:NULL); if (*outlen == 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); goto err; } if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_CTRL_CALL_FAILED); goto err; } } GOST_KEY_TRANSPORT_free(gkt); return 1; memerr: if (key_is_ephemeral) { EVP_PKEY_free(mykey); } GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_MALLOC_FAILURE); err: GOST_KEY_TRANSPORT_free(gkt); return -1; }
static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { int i,ok=0,bad=0; i=ssl_cert_type(NULL,pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE); return(0); } if (c->pkeys[i].x509 != NULL) { EVP_PKEY *pktmp; pktmp = X509_get_pubkey(c->pkeys[i].x509); EVP_PKEY_copy_parameters(pktmp,pkey); EVP_PKEY_free(pktmp); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* Don't check the public/private key, this is mostly * for smart cards. */ if ((pkey->type == EVP_PKEY_RSA) && (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ok=1; else #endif if (!X509_check_private_key(c->pkeys[i].x509,pkey)) { if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA)) { i=(i == SSL_PKEY_DH_RSA)? SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA; if (c->pkeys[i].x509 == NULL) ok=1; else { if (!X509_check_private_key( c->pkeys[i].x509,pkey)) bad=1; else ok=1; } } else bad=1; } else ok=1; } else ok=1; if (bad) { X509_free(c->pkeys[i].x509); c->pkeys[i].x509=NULL; return(0); } ERR_clear_error(); /* make sure no error from X509_check_private_key() * is left if we have chosen to ignore it */ if (c->pkeys[i].privatekey != NULL) EVP_PKEY_free(c->pkeys[i].privatekey); CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); c->pkeys[i].privatekey=pkey; c->key= &(c->pkeys[i]); c->valid=0; return(1); }
static int ssl_set_cert(CERT *c, X509 *x) { EVP_PKEY *pkey; int i,ok=0,bad=0; pkey=X509_get_pubkey(x); if (pkey == NULL) { SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB); return(0); } i=ssl_cert_type(x,pkey); if (i < 0) { SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE); EVP_PKEY_free(pkey); return(0); } if (c->pkeys[i].privatekey != NULL) { EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey); ERR_clear_error(); #ifndef OPENSSL_NO_RSA /* Don't check the public/private key, this is mostly * for smart cards. */ if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) ok=1; else #endif { if (!X509_check_private_key(x,c->pkeys[i].privatekey)) { if ((i == SSL_PKEY_DH_RSA) || (i == SSL_PKEY_DH_DSA)) { i=(i == SSL_PKEY_DH_RSA)? SSL_PKEY_DH_DSA:SSL_PKEY_DH_RSA; if (c->pkeys[i].privatekey == NULL) ok=1; else { if (!X509_check_private_key(x, c->pkeys[i].privatekey)) bad=1; else ok=1; } } else bad=1; } else ok=1; } /* OPENSSL_NO_RSA */ } else ok=1; EVP_PKEY_free(pkey); if (bad) { EVP_PKEY_free(c->pkeys[i].privatekey); c->pkeys[i].privatekey=NULL; } if (c->pkeys[i].x509 != NULL) X509_free(c->pkeys[i].x509); CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); c->pkeys[i].x509=x; c->key= &(c->pkeys[i]); c->valid=0; return(1); }
static int cert_stuff(struct connectdata *conn, SSL_CTX* ctx, char *cert_file, const char *cert_type, char *key_file, const char *key_type) { struct SessionHandle *data = conn->data; int file_type; if(cert_file != NULL) { SSL *ssl; X509 *x509; if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ size_t len = strlen(data->set.key_passwd); if(len < sizeof(global_passwd)) memcpy(global_passwd, data->set.key_passwd, len+1); #else /* * We set the password in the callback userdata */ SSL_CTX_set_default_passwd_cb_userdata(ctx, data->set.key_passwd); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } file_type = do_file_type(cert_type); switch(file_type) { case SSL_FILETYPE_PEM: /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ if(SSL_CTX_use_certificate_chain_file(ctx, cert_file) != 1) { failf(data, "unable to set certificate file (wrong password?)"); return 0; } break; case SSL_FILETYPE_ASN1: /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but we use the case above for PEM so this can only be performed with ASN1 files. */ if(SSL_CTX_use_certificate_file(ctx, cert_file, file_type) != 1) { failf(data, "unable to set certificate file (wrong password?)"); return 0; } break; case SSL_FILETYPE_ENGINE: failf(data, "file type ENG for certificate not implemented"); return 0; default: failf(data, "not supported file type '%s' for certificate", cert_type); return 0; } file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(key_file == NULL) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { failf(data, "unable to set private key file: '%s' type %s\n", key_file, key_type?key_type:"PEM"); return 0; } break; case SSL_FILETYPE_ENGINE: #ifdef HAVE_OPENSSL_ENGINE_H { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if(conn && conn->data && conn->data->engine) { #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS UI_METHOD *ui_method = UI_OpenSSL(); #endif if(!key_file || !key_file[0]) { failf(data, "no key set to load from crypto engine\n"); return 0; } /* the typecast below was added to please mingw32 */ priv_key = (EVP_PKEY *) ENGINE_load_private_key(conn->data->engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS ui_method, #endif data->set.key_passwd); if(!priv_key) { failf(data, "failed to load private key from crypto engine\n"); return 0; } if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { failf(data, "unable to set private key\n"); EVP_PKEY_free(priv_key); return 0; } EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ } else { failf(data, "crypto engine not set, can't load private key\n"); return 0; } } break; #else failf(data, "file type ENG for private key not supported\n"); return 0; #endif default: failf(data, "not supported file type for private key\n"); return 0; } ssl=SSL_new(ctx); x509=SSL_get_certificate(ssl); /* This version was provided by Evan Jordan and is supposed to not leak memory as the previous version: */ if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl)); EVP_PKEY_free(pktmp); } SSL_free(ssl); /* If we are using DSA, we can copy the parameters from * the private key */ /* Now we know that a key and cert have been set against * the SSL context */ if(!SSL_CTX_check_private_key(ctx)) { failf(data, "Private key does not match the certificate public key"); return(0); } #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* erase it now */ memset(global_passwd, 0, sizeof(global_passwd)); #endif } return(1); }
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create, int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno) { int ret=0; ASN1_INTEGER *bs=NULL; X509_STORE_CTX xsc; EVP_PKEY *upkey; upkey = X509_get_pubkey(xca); EVP_PKEY_copy_parameters(upkey,pkey); EVP_PKEY_free(upkey); if(!X509_STORE_CTX_init(&xsc,ctx,x,NULL)) { BIO_printf(bio_err,"Error initialising X509 store\n"); goto end; } if (sno) bs = sno; else if (!(bs = load_serial(CAfile, serialfile, create))) goto end; if (!X509_STORE_add_cert(ctx,x)) goto end; /* NOTE: this certificate can/should be self signed, unless it was * a certificate request in which case it is not. */ X509_STORE_CTX_set_cert(&xsc,x); if (!reqfile && !X509_verify_cert(&xsc)) goto end; if (!X509_check_private_key(xca,pkey)) { BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); goto end; } if (!X509_set_issuer_name(x,X509_get_subject_name(xca))) goto end; if (!X509_set_serialNumber(x,bs)) goto end; if (X509_gmtime_adj(X509_get_notBefore(x),0L) == NULL) goto end; /* hardwired expired */ if (X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days) == NULL) goto end; if (clrext) { while (X509_get_ext_count(x) > 0) X509_delete_ext(x, 0); } if (conf) { X509V3_CTX ctx2; X509_set_version(x,2); /* version 3 certificate */ X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0); X509V3_set_nconf(&ctx2, conf); if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end; } if (!X509_sign(x,pkey,digest)) goto end; ret=1; end: X509_STORE_CTX_cleanup(&xsc); if (!ret) ERR_print_errors(bio_err); if (!sno) ASN1_INTEGER_free(bs); return ret; }
SSL *SSLSocket::createSSL(SSL_CTX *ctx) { ERR_clear_error(); /* look at options in the stream and set appropriate verification flags */ if (m_context[s_verify_peer].toBoolean()) { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verifyCallback); /* CA stuff */ String cafile = m_context[s_cafile].toString(); String capath = m_context[s_capath].toString(); if (!cafile.empty() || !capath.empty()) { if (!SSL_CTX_load_verify_locations(ctx, cafile.data(), capath.data())) { raise_warning("Unable to set verify locations `%s' `%s'", cafile.data(), capath.data()); return nullptr; } } int64_t depth = m_context[s_verify_depth].toInt64(); if (depth) { SSL_CTX_set_verify_depth(ctx, depth); } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr); } /* callback for the passphrase (for localcert) */ if (!m_context[s_passphrase].toString().empty()) { SSL_CTX_set_default_passwd_cb_userdata(ctx, this); SSL_CTX_set_default_passwd_cb(ctx, passwdCallback); } String cipherlist = m_context[s_ciphers].toString(); if (cipherlist.empty()) { cipherlist = "DEFAULT"; } SSL_CTX_set_cipher_list(ctx, cipherlist.data()); String certfile = m_context[s_local_cert].toString(); if (!certfile.empty()) { String resolved_path_buff = File::TranslatePath(certfile); if (!resolved_path_buff.empty()) { /* a certificate to use for authentication */ if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data()) != 1) { raise_warning("Unable to set local cert chain file `%s'; Check " "that your cafile/capath settings include details of " "your certificate and its issuer", certfile.data()); return nullptr; } if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(), SSL_FILETYPE_PEM) != 1) { raise_warning("Unable to set private key file `%s'", resolved_path_buff.data()); return nullptr; } SSL *tmpssl = SSL_new(ctx); X509 *cert = SSL_get_certificate(tmpssl); if (cert) { EVP_PKEY *key = X509_get_pubkey(cert); EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); EVP_PKEY_free(key); } SSL_free(tmpssl); if (!SSL_CTX_check_private_key(ctx)) { raise_warning("Private key does not match certificate!"); } } } SSL *ssl = SSL_new(ctx); if (ssl) { SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */ } return ssl; }
SSL *SSL_new_from_context(SSL_CTX *ctx, stream *stream) /* {{{ */ { zval **val = NULL; char *cafile = NULL; char *capath = NULL; char *certfile = NULL; char *cipherlist = NULL; int ok = 1; ERR_clear_error(); /* look at context options in the stream and set appropriate verification flags */ if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) { /* turn on verification callback */ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); /* CA stuff */ GET_VER_OPT_STRING("cafile", cafile); GET_VER_OPT_STRING("capath", capath); if (cafile || capath) { if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { error_docref(NULL, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath); return NULL; } } if (GET_VER_OPT("verify_depth")) { convert_to_long_ex(val); SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val)); } } else { SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); } /* callback for the passphrase (for localcert) */ if (GET_VER_OPT("passphrase")) { SSL_CTX_set_default_passwd_cb_userdata(ctx, stream); SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } GET_VER_OPT_STRING("ciphers", cipherlist); if (!cipherlist) { cipherlist = "DEFAULT"; } if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) { return NULL; } GET_VER_OPT_STRING("local_cert", certfile); if (certfile) { X509 *cert = NULL; EVP_PKEY *key = NULL; SSL *tmpssl; char resolved_path_buff[MAXPATHLEN]; const char * private_key = NULL; if (VCWD_REALPATH(certfile, resolved_path_buff)) { /* a certificate to use for authentication */ if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { error_docref(NULL, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile); return NULL; } GET_VER_OPT_STRING("local_pk", private_key); if (private_key) { char resolved_path_buff_pk[MAXPATHLEN]; if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) { if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) { error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk); return NULL; } } } else { if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); return NULL; } } tmpssl = SSL_new(ctx); cert = SSL_get_certificate(tmpssl); if (cert) { key = X509_get_pubkey(cert); EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); EVP_PKEY_free(key); } SSL_free(tmpssl); if (!SSL_CTX_check_private_key(ctx)) { error_docref(NULL, E_WARNING, "Private key does not match certificate!"); } } } if (ok) { SSL *ssl = SSL_new(ctx); if (ssl) { /* map SSL => stream */ SSL_set_ex_data(ssl, ssl_stream_data_index, stream); } return ssl; } return NULL; }