Index: lib/Net/SSLeay.pod =================================================================== diff --git a/lib/Net/SSLeay.pod b/lib/Net/SSLeay.pod --- a/lib/Net/SSLeay.pod (revision 465) +++ b/lib/Net/SSLeay.pod (revision 466) @@ -44,6 +44,8 @@ to use at least 0.9.7 (as older versions are not tested during development). Some low level API functions may be available with certain openssl versions. +It is compatible with OpenSSL 1.0 and 1.1. Some functions are not available under OpenSSL 1.1. + L module basically comprise of: =over @@ -1844,6 +1846,11 @@ # # returns: no return value +Not available with OpenSSL 1.1 and later. +Code that previously used + SESSION_set_master_key must now set $secret in the session_secret + callback set with SSL_set_session_secret_cb. + =item * SESSION_get_time Returns the time at which the session s was established. @@ -2447,6 +2454,8 @@ # # returns: result of SSL_CTRL_NEED_TMP_RSA command +Not available with OpenSSL 1.1 and later. + =item * CTX_new The same as L @@ -2457,6 +2466,8 @@ Check openssl doc L +Not available with OpenSSL 1.1 and later. + =item * CTX_v2_new Creates a new SSL_CTX object - based on SSLv2_method() - as framework to establish TLS/SSL enabled connections. @@ -2906,6 +2917,8 @@ Check openssl doc L +Not available with OpenSSL 1.1 and later. + =item * CTX_set_tmp_rsa_callback Sets the callback function for ctx to be used when a temporary/ephemeral RSA key is required to $tmp_rsa_callback. @@ -2920,6 +2933,8 @@ Check openssl doc L +Not available with OpenSSL 1.1 and later. + =item * CTX_set_trust my $rv = Net::SSLeay::CTX_set_trust($s, $trust); @@ -3436,10 +3451,10 @@ =item * get_keyblock_size +Gets the length of the TLS keyblock. + B Does not exactly correspond to any low level API function. -??? (more info needed) - my $rv = Net::SSLeay::get_keyblock_size($ssl); # $ssl - value corresponding to openssl's SSL structure # @@ -3680,6 +3695,8 @@ Net::SSLeay::set_state($ssl,Net::SSLeay::SSL_ST_ACCEPT()); +Not available with OpenSSL 1.1 and later. + =item * get_verify_depth Returns the verification depth limit currently set in $ssl. @@ -3829,6 +3846,8 @@ # # returns: command result +Not available with OpenSSL 1.1 and later. + =item * num_renegotiations Executes SSL_CTRL_GET_NUM_RENEGOTIATIONS command on $ssl. @@ -4131,6 +4150,21 @@ # # returns: no return value +The callback function will be called like: +callback_function($secret, $ciphers, $pref_cipher, $data); + +# $secret is the current master session key, usually all 0s at the beginning of a session +# $ciphers is ref to an array of peer cipher names +# $pref_cipher is a ref to an index into the list of cipher names of +# the preferred cipher. Set it if you want to specify a preferred cipher +# $data is the data passed to set_session_secret_cb + +The callback function should return 1 if it likes the suggested cipher (or has selected an alternative +by setting pref_cipher), else it should return 0 (in which case OpenSSL will select its own preferred cipher). + +With OpenSSL 1.1 and later, callback_function can change the master key for the session by +altering $secret and returning 1. + =item * set_shutdown Sets the shutdown state of $ssl to $mode. Index: SSLeay.xs =================================================================== diff --git a/SSLeay.xs b/SSLeay.xs --- a/SSLeay.xs (revision 465) +++ b/SSLeay.xs (revision 466) @@ -237,8 +237,10 @@ #ifdef USE_ITHREADS static perl_mutex LIB_init_mutex; +#if OPENSSL_VERSION_NUMBER < 0x10100000L static perl_mutex *GLOBAL_openssl_mutex = NULL; #endif +#endif static int LIB_initialized; UV get_my_thread_id(void) /* returns threads->tid() value */ @@ -277,6 +279,8 @@ */ #if defined(USE_ITHREADS) && defined(OPENSSL_THREADS) + +#if OPENSSL_VERSION_NUMBER < 0x10100000L static void openssl_locking_function(int mode, int type, const char *file, int line) { PR3("openssl_locking_function %d %d\n", mode, type); @@ -331,6 +335,7 @@ MUTEX_DESTROY(&l->mutex); Safefree(l); } +#endif void openssl_threads_init(void) { @@ -338,6 +343,7 @@ PR1("STARTED: openssl_threads_init\n"); +#if OPENSSL_VERSION_NUMBER < 0x10100000L /* initialize static locking */ if ( !CRYPTO_get_locking_callback() ) { #if OPENSSL_VERSION_NUMBER < 0x10000000L @@ -371,6 +377,7 @@ CRYPTO_set_dynlock_lock_callback(openssl_dynlocking_lock_function); CRYPTO_set_dynlock_destroy_callback(openssl_dynlocking_destroy_function); } +#endif } #endif @@ -395,7 +402,9 @@ if (!m) return; /* Skip aliases */ mname = OBJ_nid2ln(EVP_MD_type(m)); if (strcmp(from, mname)) return; /* Skip shortnames */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (EVP_MD_flags(m) & EVP_MD_FLAG_PKEY_DIGEST) return; /* Skip clones */ +#endif if (strchr(mname, ' ')) mname= EVP_MD_name(m); av_push(arg, newSVpv(mname,0)); } @@ -799,6 +808,7 @@ AV *ciphers = newAV(); SV *pref_cipher = sv_newmortal(); SV * cb_func, *cb_data; + SV * secretsv; PR1("STARTED: ssleay_session_secret_cb_invoke\n"); cb_func = cb_data_advanced_get(arg, "ssleay_session_secret_cb!!func"); @@ -811,8 +821,8 @@ SAVETMPS; PUSHMARK(SP); - - XPUSHs( sv_2mortal( newSVpv(secret, *secret_len)) ); + secretsv = sv_2mortal( newSVpv(secret, *secret_len)); + XPUSHs(secretsv); for (i=0; i= 0x10100000L + /* Use any new master secret set by the callback function in secret */ + STRLEN newsecretlen; + char* newsecretdata = SvPV(secretsv, newsecretlen); + memcpy(secret, newsecretdata, newsecretlen); +#endif } PUTBACK; @@ -1404,8 +1421,10 @@ OUTPUT: RETVAL -#ifndef OPENSSL_NO_SSL2 +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#ifndef OPENSSL_NO_SSL2 + SSL_CTX * SSL_CTX_v2_new() CODE: @@ -1414,7 +1433,7 @@ RETVAL #endif - +#endif #ifndef OPENSSL_NO_SSL3 SSL_CTX * @@ -2105,10 +2124,35 @@ SSL_want(s) SSL * s +#if OPENSSL_VERSION_NUMBER < 0x10100000L int SSL_state(s) SSL * s +int +SSL_get_state(ssl) + SSL * ssl + CODE: + RETVAL = SSL_state(ssl); + OUTPUT: + RETVAL + + +#else +int +SSL_state(s) + SSL * s + CODE: + RETVAL = SSL_get_state(s); + OUTPUT: + RETVAL + + +int +SSL_get_state(s) + SSL * s + +#endif #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) long @@ -2734,19 +2778,15 @@ X509_ATTRIBUTE * att; int count, i; ASN1_STRING * s; + ASN1_TYPE * t; PPCODE: att = X509_REQ_get_attr(req,n); - if (att->single) { - s = (att->value.single->value.asn1_string); + count = X509_ATTRIBUTE_count(att); + for (i=0; ivalue.asn1_string; XPUSHs(sv_2mortal(newSViv(PTR2IV(s)))); - } - else { - count = sk_ASN1_TYPE_num(att->value.set); - for (i=0; ivalue.set, i)->value.asn1_string); - XPUSHs(sv_2mortal(newSViv(PTR2IV(s)))); - } - } + } #endif @@ -4439,6 +4479,7 @@ const unsigned char * sid_ctx unsigned int sid_ctx_len +#if OPENSSL_VERSION_NUMBER < 0x10100000L void SSL_CTX_set_tmp_rsa_callback(ctx, cb) SSL_CTX * ctx @@ -4449,6 +4490,8 @@ SSL * ssl cb_ssl_int_int_ret_RSA * cb +#endif + void SSL_CTX_set_tmp_dh_callback(ctx, dh) SSL_CTX * ctx @@ -4526,6 +4569,7 @@ OUTPUT: RETVAL +#if OPENSSL_VERSION_NUMBER < 0x10100000L long SSL_CTX_need_tmp_RSA(ctx) SSL_CTX * ctx @@ -4534,6 +4578,8 @@ OUTPUT: RETVAL +#endif + int SSL_CTX_set_app_data(ctx,arg) SSL_CTX * ctx @@ -4575,11 +4621,14 @@ SSL_CTX * ctx DH * dh +#if OPENSSL_VERSION_NUMBER < 0x10100000L long SSL_CTX_set_tmp_rsa(ctx,rsa) SSL_CTX * ctx RSA * rsa +#endif + #if OPENSSL_VERSION_NUMBER > 0x10000000L && !defined OPENSSL_NO_EC EC_KEY * @@ -4622,25 +4671,20 @@ OUTPUT: RETVAL -int -SSL_get_state(ssl) - SSL * ssl - CODE: - RETVAL = SSL_state(ssl); - OUTPUT: - RETVAL - void SSL_set_state(ssl,state) SSL * ssl int state CODE: -#ifdef OPENSSL_NO_SSL_INTERN +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + /* not available */ +#elif defined(OPENSSL_NO_SSL_INTERN) SSL_set_state(ssl,state); #else ssl->state = state; #endif +#if OPENSSL_VERSION_NUMBER < 0x10100000L long SSL_need_tmp_RSA(ssl) SSL * ssl @@ -4649,6 +4693,9 @@ OUTPUT: RETVAL + +#endif + long SSL_num_renegotiations(ssl) SSL * ssl @@ -4668,10 +4715,6 @@ long SSL_session_reused(ssl) SSL * ssl - CODE: - RETVAL = SSL_ctrl(ssl,SSL_CTRL_GET_SESSION_REUSED,0,NULL); - OUTPUT: - RETVAL int SSL_SESSION_set_app_data(s,a) @@ -4714,6 +4757,7 @@ SSL * ssl DH * dh +#if OPENSSL_VERSION_NUMBER < 0x10100000L long SSL_set_tmp_rsa(ssl,rsa) SSL * ssl @@ -4723,6 +4767,7 @@ OUTPUT: RETVAL +#endif #ifdef __ANDROID__ @@ -4855,13 +4900,33 @@ OUTPUT: RETVAL +#if OPENSSL_VERSION_NUMBER >= 0x10100000L void SSL_SESSION_get_master_key(s) SSL_SESSION * s + PREINIT: + size_t master_key_length; + unsigned char* master_key; CODE: ST(0) = sv_newmortal(); /* Undefined to start with */ + master_key_length = SSL_SESSION_get_master_key(s, 0, 0); /* get the length */ + New(0, master_key, master_key_length, unsigned char); + SSL_SESSION_get_master_key(s, master_key, master_key_length); + sv_setpvn(ST(0), (const char*)master_key, master_key_length); + Safefree(master_key); + +#else +void +SSL_SESSION_get_master_key(s) + SSL_SESSION * s + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ sv_setpvn(ST(0), (const char*)s->master_key, s->master_key_length); +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + void SSL_SESSION_set_master_key(s,key) SSL_SESSION * s @@ -4873,24 +4938,80 @@ memcpy(s->master_key, key, len); s->master_key_length = len; +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + void SSL_get_client_random(s) SSL * s + PREINIT: + size_t random_length; + unsigned char* random_data; CODE: ST(0) = sv_newmortal(); /* Undefined to start with */ + random_length = SSL_get_client_random(s, 0, 0); /* get the length */ + New(0, random_data, random_length, unsigned char); + SSL_get_client_random(s, random_data, random_length); + sv_setpvn(ST(0), (const char*)random_data, random_length); + Safefree(random_data); + +#else + +void +SSL_get_client_random(s) + SSL * s + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ sv_setpvn(ST(0), (const char*)s->s3->client_random, SSL3_RANDOM_SIZE); +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + void SSL_get_server_random(s) SSL * s + PREINIT: + size_t random_length; + unsigned char* random_data; CODE: ST(0) = sv_newmortal(); /* Undefined to start with */ + random_length = SSL_get_server_random(s, 0, 0); /* get the length */ + New(0, random_data, random_length, unsigned char); + SSL_get_server_random(s, random_data, random_length); + sv_setpvn(ST(0), (const char*)random_data, random_length); + Safefree(random_data); + +#else + +void +SSL_get_server_random(s) + SSL * s + CODE: + ST(0) = sv_newmortal(); /* Undefined to start with */ sv_setpvn(ST(0), (const char*)s->s3->server_random, SSL3_RANDOM_SIZE); +#endif + int SSL_get_keyblock_size(s) SSL * s CODE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const SSL_CIPHER *ssl_cipher; + int cipher, digest; + const EVP_CIPHER *c; + const EVP_MD *h; + + ssl_cipher = SSL_get_current_cipher(s); + cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher); + digest = SSL_CIPHER_get_digest_nid(ssl_cipher); + c = EVP_get_cipherbynid(cipher); + h = EVP_get_digestbynid(digest); + RETVAL = 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) + + EVP_CIPHER_iv_length(c)); +#else if (s == NULL || s->enc_read_ctx == NULL || s->enc_read_ctx->cipher == NULL || @@ -4919,6 +5040,8 @@ EVP_CIPHER_iv_length(c))) : -1; } +#endif + OUTPUT: RETVAL @@ -4956,9 +5079,7 @@ else { cb_data_advanced_put(s, "ssleay_session_secret_cb!!func", newSVsv(callback)); cb_data_advanced_put(s, "ssleay_session_secret_cb!!data", newSVsv(data)); - SSL_set_session_secret_cb(s, (int (*)(SSL *s, void *secret, int *secret_len, - STACK_OF(SSL_CIPHER) *peer_ciphers, - SSL_CIPHER **cipher, void *arg))&ssleay_session_secret_cb_invoke, s); + SSL_set_session_secret_cb(s, (tls_session_secret_cb_fn)&ssleay_session_secret_cb_invoke, s); } #endif @@ -5382,7 +5503,11 @@ P_X509_get_signature_alg(x) X509 * x CODE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + RETVAL = (X509_get0_tbs_sigalg(x)->algorithm); +#else RETVAL = (x->cert_info->signature->algorithm); +#endif OUTPUT: RETVAL @@ -5389,8 +5514,17 @@ ASN1_OBJECT * P_X509_get_pubkey_alg(x) X509 * x + PREINIT: CODE: +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + { + X509_ALGOR * algor; + X509_PUBKEY_get0_param(0, 0, 0, &algor, X509_get_X509_PUBKEY(x)); + RETVAL = (algor->algorithm); + } +#else RETVAL = (x->cert_info->key->algor->algorithm); +#endif OUTPUT: RETVAL @@ -5705,8 +5839,7 @@ * response does not contain the chain up to the trusted root */ STACK_OF(X509) *chain = SSL_get_peer_cert_chain(ssl); for(i=0;icerts) bsr->certs = sk_X509_new_null(); - sk_X509_push(bsr->certs,X509_dup(sk_X509_value(chain,i))); + OCSP_basic_add1_cert(bsr, sk_X509_value(chain,i)); } TRACE(1,"run basic verify"); RETVAL = OCSP_basic_verify(bsr, NULL, store, flags); @@ -5718,7 +5851,7 @@ X509 *issuer; X509 *last = sk_X509_value(chain,sk_X509_num(chain)-1); if ( (issuer = find_issuer(last,store,chain))) { - sk_X509_push(bsr->certs,X509_dup(issuer)); + OCSP_basic_add1_cert(bsr, X509_dup(issuer)); TRACE(1,"run OCSP_basic_verify with issuer for last chain element"); RETVAL = OCSP_basic_verify(bsr, NULL, store, flags); } @@ -5736,7 +5869,6 @@ OCSP_BASICRESP *bsr; int i,want_array; time_t nextupd = 0; - STACK_OF(OCSP_SINGLERESP) *sks; int getall,sksn; bsr = OCSP_response_get1_basic(rsp); @@ -5744,8 +5876,7 @@ want_array = (GIMME == G_ARRAY); getall = (items <= 1); - sks = bsr->tbsResponseData->responses; - sksn = sk_OCSP_SINGLERESP_num(sks); + sksn = OCSP_resp_count(bsr); for(i=0; i < (getall ? sksn : items-1); i++) { const char *error = NULL; @@ -5754,9 +5885,8 @@ SV *idsv = NULL; if(getall) { - sir = sk_OCSP_SINGLERESP_value(sks,i); + sir = OCSP_resp_get0(bsr,i); } else { - int k; STRLEN len; const unsigned char *p; @@ -5767,22 +5897,36 @@ error = "failed to get OCSP certid from string"; goto end; } - for(k=0;kcertId)) { - sir = sk_OCSP_SINGLERESP_value(sks,k); - break; - } + int first = OCSP_resp_find(bsr, certid, -1); /* Find the first matching */ + if (first >= 0) + { + sir = OCSP_resp_get0(bsr,first); + break; } } - if (!sir) { - error = "cannot find entry for certificate in OCSP response"; - } else if (!OCSP_check_validity(sir->thisUpdate,sir->nextUpdate,0,-1)) { - error = "response not yet valid or expired"; - } else if (sir->certStatus->type == V_OCSP_CERTSTATUS_REVOKED) { - error = "certificate status is revoked"; - } else if (sir->certStatus->type != V_OCSP_CERTSTATUS_GOOD) { - error = "certificate status is unknown"; + int status, revocationReason; + ASN1_GENERALIZEDTIME *revocationTime, *thisupdate, *nextupdate; + if (sir) + { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + status = OCSP_single_get0_status(sir, &revocationReason, &revocationTime, &thisupdate, &nextupdate); +#else + status = sir->certStatus->type; + revocationTime = sir->certStatus->value.revoked->revocationTime; + thisupdate = sir->thisUpdate; + nextupdate = sir->nextUpdate; +#endif + if (status == V_OCSP_CERTSTATUS_REVOKED) { + error = "certificate status is revoked"; + } else if (status != V_OCSP_CERTSTATUS_GOOD) { + error = "certificate status is unknown"; + } + else if (!OCSP_check_validity(thisupdate, nextupdate, 0, -1)) { + error = "response not yet valid or expired"; + } + } else { + error = "cannot find entry for certificate in OCSP response"; } end: @@ -5791,12 +5935,20 @@ if (!idsv) { /* getall: create new SV with OCSP_CERTID */ unsigned char *pi,*pc; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + int len = i2d_OCSP_CERTID(OCSP_SINGLERESP_get0_id(sir),NULL); +#else int len = i2d_OCSP_CERTID(sir->certId,NULL); +#endif if(!len) continue; Newx(pc,len,unsigned char); if (!pc) croak("out of memory"); pi = pc; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + i2d_OCSP_CERTID(OCSP_SINGLERESP_get0_id(sir),&pi); +#else i2d_OCSP_CERTID(sir->certId,&pi); +#endif idsv = newSVpv((char*)pc,len); Safefree(pc); } else { @@ -5809,26 +5961,26 @@ HV *details = newHV(); av_push(idav,newRV_noinc((SV*)details)); hv_store(details,"statusType",10, - newSViv(sir->certStatus->type),0); - if (sir->nextUpdate) hv_store(details,"nextUpdate",10, - newSViv(ASN1_TIME_timet(sir->nextUpdate)),0); - if (sir->thisUpdate) hv_store(details,"thisUpdate",10, - newSViv(ASN1_TIME_timet(sir->thisUpdate)),0); - if (sir->certStatus->type == V_OCSP_CERTSTATUS_REVOKED) { + newSViv(status),0); + if (nextupdate) hv_store(details,"nextUpdate",10, + newSViv(ASN1_TIME_timet(nextupdate)),0); + if (thisupdate) hv_store(details,"thisUpdate",10, + newSViv(ASN1_TIME_timet(thisupdate)),0); + if (status == V_OCSP_CERTSTATUS_REVOKED) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L OCSP_REVOKEDINFO *rev = sir->certStatus->value.revoked; - hv_store(details,"revocationTime",14,newSViv( - ASN1_TIME_timet(rev->revocationTime)),0); - hv_store(details,"revocationReason",16,newSViv( - ASN1_ENUMERATED_get(rev->revocationReason)),0); + revocationReason = ASN1_ENUMERATED_get(rev->revocationReason); +#endif + hv_store(details,"revocationTime",14,newSViv(ASN1_TIME_timet(revocationTime)),0); + hv_store(details,"revocationReason",16,newSViv(revocationReason),0); hv_store(details,"revocationReason_str",20,newSVpv( - OCSP_crl_reason_str(ASN1_ENUMERATED_get( - rev->revocationReason)),0),0); + OCSP_crl_reason_str(revocationReason),0),0); } } XPUSHs(sv_2mortal(newRV_noinc((SV*)idav))); } else if (!error) { /* compute lowest nextUpdate */ - time_t nu = ASN1_TIME_timet(sir->nextUpdate); + time_t nu = ASN1_TIME_timet(nextupdate); if (!nextupd || nextupd>nu) nextupd = nu; } Index: t/local/32_x509_get_cert_info.t =================================================================== diff --git a/t/local/32_x509_get_cert_info.t b/t/local/32_x509_get_cert_info.t --- a/t/local/32_x509_get_cert_info.t (revision 465) +++ b/t/local/32_x509_get_cert_info.t (revision 466) @@ -175,7 +175,7 @@ } SKIP: { - skip('crl_distribution_points requires 0.9.7+', scalar(@{$dump->{$f}->{cdp}})+1) unless Net::SSLeay::SSLeay >= 0x0090700f; + skip('crl_distribution_points requires 0.9.7+', int(@{$dump->{$f}->{cdp}})+1) unless Net::SSLeay::SSLeay >= 0x0090700f; my @cdp = Net::SSLeay::P_X509_get_crl_distribution_points($x509); is(scalar(@cdp), scalar(@{$dump->{$f}->{cdp}}), "cdp size\t$f"); for my $i (0..$#cdp) { Index: t/local/35_ephemeral.t =================================================================== diff --git a/t/local/35_ephemeral.t b/t/local/35_ephemeral.t --- a/t/local/35_ephemeral.t (revision 465) +++ b/t/local/35_ephemeral.t (revision 466) @@ -6,7 +6,7 @@ use Net::SSLeay; BEGIN { - plan skip_all => "libressl removed support for ephemeral/temporary RSA private keys" if Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER"); + plan skip_all => "libressl and OpenSSL 1.1 removed support for ephemeral/temporary RSA private keys" if Net::SSLeay::constant("LIBRESSL_VERSION_NUMBER") || $Net::SSLeay::VERSION > 1.74; } plan tests => 3;