mirror of
https://github.com/curl/curl.git
synced 2024-11-27 05:50:21 +08:00
openssl: make certinfo available for QUIC
Curl_ossl_certchain() is now an exported function in lib/vtls/openssl.c that can also be used from quiche.c and ngtcp2.c to get the cert chain for QUIC connections as well. The *certchain function was moved to the top of the file for this reason. Reported-by: Eloy Degen Fixes #9584 Closes #9597
This commit is contained in:
parent
35cb4e0997
commit
58acc69e10
@ -1703,6 +1703,11 @@ static CURLcode ng_has_connected(struct Curl_easy *data,
|
||||
}
|
||||
else
|
||||
infof(data, "Skipped certificate verification");
|
||||
#ifdef USE_OPENSSL
|
||||
if(data->set.ssl.certinfo)
|
||||
/* asked to gather certificate info */
|
||||
(void)Curl_ossl_certchain(data, conn->quic->ssl);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -416,6 +416,10 @@ static CURLcode quiche_has_connected(struct Curl_easy *data,
|
||||
qs->cfg = NULL;
|
||||
qs->conn = NULL;
|
||||
}
|
||||
if(data->set.ssl.certinfo)
|
||||
/* asked to gather certificate info */
|
||||
(void)Curl_ossl_certchain(data, qs->ssl);
|
||||
|
||||
return CURLE_OK;
|
||||
fail:
|
||||
quiche_h3_config_free(qs->h3config);
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#if defined(USE_QUICHE) || defined(USE_OPENSSL)
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
@ -271,6 +271,344 @@ struct ssl_backend_data {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define push_certinfo(_label, _num) \
|
||||
do { \
|
||||
long info_len = BIO_get_mem_data(mem, &ptr); \
|
||||
Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
|
||||
if(1 != BIO_reset(mem)) \
|
||||
break; \
|
||||
} while(0)
|
||||
|
||||
static void pubkey_show(struct Curl_easy *data,
|
||||
BIO *mem,
|
||||
int num,
|
||||
const char *type,
|
||||
const char *name,
|
||||
const BIGNUM *bn)
|
||||
{
|
||||
char *ptr;
|
||||
char namebuf[32];
|
||||
|
||||
msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
|
||||
|
||||
if(bn)
|
||||
BN_print(mem, bn);
|
||||
push_certinfo(namebuf, num);
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
#define print_pubkey_BN(_type, _name, _num) \
|
||||
pubkey_show(data, mem, _num, #_type, #_name, _name)
|
||||
|
||||
#else
|
||||
#define print_pubkey_BN(_type, _name, _num) \
|
||||
do { \
|
||||
if(_type->_name) { \
|
||||
pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
|
||||
{
|
||||
int i, ilen;
|
||||
|
||||
ilen = (int)len;
|
||||
if(ilen < 0)
|
||||
return 1; /* buffer too big */
|
||||
|
||||
i = i2t_ASN1_OBJECT(buf, ilen, a);
|
||||
|
||||
if(i >= ilen)
|
||||
return 1; /* buffer too small */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void X509V3_ext(struct Curl_easy *data,
|
||||
int certnum,
|
||||
CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
int i;
|
||||
|
||||
if((int)sk_X509_EXTENSION_num(exts) <= 0)
|
||||
/* no extensions, bail out */
|
||||
return;
|
||||
|
||||
for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
|
||||
ASN1_OBJECT *obj;
|
||||
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
|
||||
BUF_MEM *biomem;
|
||||
char namebuf[128];
|
||||
BIO *bio_out = BIO_new(BIO_s_mem());
|
||||
|
||||
if(!bio_out)
|
||||
return;
|
||||
|
||||
obj = X509_EXTENSION_get_object(ext);
|
||||
|
||||
asn1_object_dump(obj, namebuf, sizeof(namebuf));
|
||||
|
||||
if(!X509V3_EXT_print(bio_out, ext, 0, 0))
|
||||
ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
|
||||
|
||||
BIO_get_mem_ptr(bio_out, &biomem);
|
||||
Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
|
||||
biomem->length);
|
||||
BIO_free(bio_out);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
typedef size_t numcert_t;
|
||||
#else
|
||||
typedef int numcert_t;
|
||||
#endif
|
||||
|
||||
CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
|
||||
{
|
||||
CURLcode result;
|
||||
STACK_OF(X509) *sk;
|
||||
int i;
|
||||
numcert_t numcerts;
|
||||
BIO *mem;
|
||||
|
||||
DEBUGASSERT(ssl);
|
||||
|
||||
sk = SSL_get_peer_cert_chain(ssl);
|
||||
if(!sk) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
numcerts = sk_X509_num(sk);
|
||||
|
||||
result = Curl_ssl_init_certinfo(data, (int)numcerts);
|
||||
if(result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mem = BIO_new(BIO_s_mem());
|
||||
if(!mem) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for(i = 0; i < (int)numcerts; i++) {
|
||||
ASN1_INTEGER *num;
|
||||
X509 *x = sk_X509_value(sk, i);
|
||||
EVP_PKEY *pubkey = NULL;
|
||||
int j;
|
||||
char *ptr;
|
||||
const ASN1_BIT_STRING *psig = NULL;
|
||||
|
||||
X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
|
||||
push_certinfo("Subject", i);
|
||||
|
||||
X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
|
||||
push_certinfo("Issuer", i);
|
||||
|
||||
BIO_printf(mem, "%lx", X509_get_version(x));
|
||||
push_certinfo("Version", i);
|
||||
|
||||
num = X509_get_serialNumber(x);
|
||||
if(num->type == V_ASN1_NEG_INTEGER)
|
||||
BIO_puts(mem, "-");
|
||||
for(j = 0; j < num->length; j++)
|
||||
BIO_printf(mem, "%02x", num->data[j]);
|
||||
push_certinfo("Serial Number", i);
|
||||
|
||||
#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
|
||||
{
|
||||
const X509_ALGOR *sigalg = NULL;
|
||||
X509_PUBKEY *xpubkey = NULL;
|
||||
ASN1_OBJECT *pubkeyoid = NULL;
|
||||
|
||||
X509_get0_signature(&psig, &sigalg, x);
|
||||
if(sigalg) {
|
||||
i2a_ASN1_OBJECT(mem, sigalg->algorithm);
|
||||
push_certinfo("Signature Algorithm", i);
|
||||
}
|
||||
|
||||
xpubkey = X509_get_X509_PUBKEY(x);
|
||||
if(xpubkey) {
|
||||
X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
|
||||
if(pubkeyoid) {
|
||||
i2a_ASN1_OBJECT(mem, pubkeyoid);
|
||||
push_certinfo("Public Key Algorithm", i);
|
||||
}
|
||||
}
|
||||
|
||||
X509V3_ext(data, i, X509_get0_extensions(x));
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* before OpenSSL 1.0.2 */
|
||||
X509_CINF *cinf = x->cert_info;
|
||||
|
||||
i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
|
||||
push_certinfo("Signature Algorithm", i);
|
||||
|
||||
i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
|
||||
push_certinfo("Public Key Algorithm", i);
|
||||
|
||||
X509V3_ext(data, i, cinf->extensions);
|
||||
|
||||
psig = x->signature;
|
||||
}
|
||||
#endif
|
||||
|
||||
ASN1_TIME_print(mem, X509_get0_notBefore(x));
|
||||
push_certinfo("Start date", i);
|
||||
|
||||
ASN1_TIME_print(mem, X509_get0_notAfter(x));
|
||||
push_certinfo("Expire date", i);
|
||||
|
||||
pubkey = X509_get_pubkey(x);
|
||||
if(!pubkey)
|
||||
infof(data, " Unable to load public key");
|
||||
else {
|
||||
int pktype;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
pktype = EVP_PKEY_id(pubkey);
|
||||
#else
|
||||
pktype = pubkey->type;
|
||||
#endif
|
||||
switch(pktype) {
|
||||
case EVP_PKEY_RSA:
|
||||
{
|
||||
#ifndef HAVE_EVP_PKEY_GET_PARAMS
|
||||
RSA *rsa;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
rsa = EVP_PKEY_get0_RSA(pubkey);
|
||||
#else
|
||||
rsa = pubkey->pkey.rsa;
|
||||
#endif /* HAVE_OPAQUE_EVP_PKEY */
|
||||
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
|
||||
|
||||
{
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
DECLARE_PKEY_PARAM_BIGNUM(n);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(e);
|
||||
#ifdef HAVE_EVP_PKEY_GET_PARAMS
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
|
||||
#else
|
||||
RSA_get0_key(rsa, &n, &e, NULL);
|
||||
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
|
||||
BIO_printf(mem, "%d", BN_num_bits(n));
|
||||
#else
|
||||
BIO_printf(mem, "%d", BN_num_bits(rsa->n));
|
||||
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
|
||||
push_certinfo("RSA Public Key", i);
|
||||
print_pubkey_BN(rsa, n, i);
|
||||
print_pubkey_BN(rsa, e, i);
|
||||
FREE_PKEY_PARAM_BIGNUM(n);
|
||||
FREE_PKEY_PARAM_BIGNUM(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EVP_PKEY_DSA:
|
||||
{
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
#ifndef HAVE_EVP_PKEY_GET_PARAMS
|
||||
DSA *dsa;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
dsa = EVP_PKEY_get0_DSA(pubkey);
|
||||
#else
|
||||
dsa = pubkey->pkey.dsa;
|
||||
#endif /* HAVE_OPAQUE_EVP_PKEY */
|
||||
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
|
||||
{
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
DECLARE_PKEY_PARAM_BIGNUM(p);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(q);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(g);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
#ifdef HAVE_EVP_PKEY_GET_PARAMS
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
|
||||
#else
|
||||
DSA_get0_pqg(dsa, &p, &q, &g);
|
||||
DSA_get0_key(dsa, &pub_key, NULL);
|
||||
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
|
||||
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
|
||||
print_pubkey_BN(dsa, p, i);
|
||||
print_pubkey_BN(dsa, q, i);
|
||||
print_pubkey_BN(dsa, g, i);
|
||||
print_pubkey_BN(dsa, pub_key, i);
|
||||
FREE_PKEY_PARAM_BIGNUM(p);
|
||||
FREE_PKEY_PARAM_BIGNUM(q);
|
||||
FREE_PKEY_PARAM_BIGNUM(g);
|
||||
FREE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
}
|
||||
#endif /* !OPENSSL_NO_DSA */
|
||||
break;
|
||||
}
|
||||
case EVP_PKEY_DH:
|
||||
{
|
||||
#ifndef HAVE_EVP_PKEY_GET_PARAMS
|
||||
DH *dh;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
dh = EVP_PKEY_get0_DH(pubkey);
|
||||
#else
|
||||
dh = pubkey->pkey.dh;
|
||||
#endif /* HAVE_OPAQUE_EVP_PKEY */
|
||||
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
|
||||
{
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
DECLARE_PKEY_PARAM_BIGNUM(p);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(q);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(g);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
#ifdef HAVE_EVP_PKEY_GET_PARAMS
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
|
||||
#else
|
||||
DH_get0_pqg(dh, &p, &q, &g);
|
||||
DH_get0_key(dh, &pub_key, NULL);
|
||||
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
|
||||
print_pubkey_BN(dh, p, i);
|
||||
print_pubkey_BN(dh, q, i);
|
||||
print_pubkey_BN(dh, g, i);
|
||||
#else
|
||||
print_pubkey_BN(dh, p, i);
|
||||
print_pubkey_BN(dh, g, i);
|
||||
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
|
||||
print_pubkey_BN(dh, pub_key, i);
|
||||
FREE_PKEY_PARAM_BIGNUM(p);
|
||||
FREE_PKEY_PARAM_BIGNUM(q);
|
||||
FREE_PKEY_PARAM_BIGNUM(g);
|
||||
FREE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
EVP_PKEY_free(pubkey);
|
||||
}
|
||||
|
||||
if(psig) {
|
||||
for(j = 0; j < psig->length; j++)
|
||||
BIO_printf(mem, "%02x:", psig->data[j]);
|
||||
push_certinfo("Signature", i);
|
||||
}
|
||||
|
||||
PEM_write_bio_X509(mem, x);
|
||||
push_certinfo("Cert", i);
|
||||
}
|
||||
|
||||
BIO_free(mem);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* quiche or OpenSSL */
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
|
||||
static bool ossl_associate_connection(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
@ -3392,342 +3730,6 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
|
||||
{
|
||||
int i, ilen;
|
||||
|
||||
ilen = (int)len;
|
||||
if(ilen < 0)
|
||||
return 1; /* buffer too big */
|
||||
|
||||
i = i2t_ASN1_OBJECT(buf, ilen, a);
|
||||
|
||||
if(i >= ilen)
|
||||
return 1; /* buffer too small */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define push_certinfo(_label, _num) \
|
||||
do { \
|
||||
long info_len = BIO_get_mem_data(mem, &ptr); \
|
||||
Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
|
||||
if(1 != BIO_reset(mem)) \
|
||||
break; \
|
||||
} while(0)
|
||||
|
||||
static void pubkey_show(struct Curl_easy *data,
|
||||
BIO *mem,
|
||||
int num,
|
||||
const char *type,
|
||||
const char *name,
|
||||
const BIGNUM *bn)
|
||||
{
|
||||
char *ptr;
|
||||
char namebuf[32];
|
||||
|
||||
msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
|
||||
|
||||
if(bn)
|
||||
BN_print(mem, bn);
|
||||
push_certinfo(namebuf, num);
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
#define print_pubkey_BN(_type, _name, _num) \
|
||||
pubkey_show(data, mem, _num, #_type, #_name, _name)
|
||||
|
||||
#else
|
||||
#define print_pubkey_BN(_type, _name, _num) \
|
||||
do { \
|
||||
if(_type->_name) { \
|
||||
pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
static void X509V3_ext(struct Curl_easy *data,
|
||||
int certnum,
|
||||
CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
int i;
|
||||
|
||||
if((int)sk_X509_EXTENSION_num(exts) <= 0)
|
||||
/* no extensions, bail out */
|
||||
return;
|
||||
|
||||
for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
|
||||
ASN1_OBJECT *obj;
|
||||
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
|
||||
BUF_MEM *biomem;
|
||||
char namebuf[128];
|
||||
BIO *bio_out = BIO_new(BIO_s_mem());
|
||||
|
||||
if(!bio_out)
|
||||
return;
|
||||
|
||||
obj = X509_EXTENSION_get_object(ext);
|
||||
|
||||
asn1_object_dump(obj, namebuf, sizeof(namebuf));
|
||||
|
||||
if(!X509V3_EXT_print(bio_out, ext, 0, 0))
|
||||
ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
|
||||
|
||||
BIO_get_mem_ptr(bio_out, &biomem);
|
||||
Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
|
||||
biomem->length);
|
||||
BIO_free(bio_out);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
typedef size_t numcert_t;
|
||||
#else
|
||||
typedef int numcert_t;
|
||||
#endif
|
||||
|
||||
static CURLcode get_cert_chain(struct Curl_easy *data,
|
||||
struct ssl_connect_data *connssl)
|
||||
{
|
||||
CURLcode result;
|
||||
STACK_OF(X509) *sk;
|
||||
int i;
|
||||
numcert_t numcerts;
|
||||
BIO *mem;
|
||||
struct ssl_backend_data *backend = connssl->backend;
|
||||
|
||||
DEBUGASSERT(backend);
|
||||
|
||||
sk = SSL_get_peer_cert_chain(backend->handle);
|
||||
if(!sk) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
numcerts = sk_X509_num(sk);
|
||||
|
||||
result = Curl_ssl_init_certinfo(data, (int)numcerts);
|
||||
if(result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mem = BIO_new(BIO_s_mem());
|
||||
if(!mem) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for(i = 0; i < (int)numcerts; i++) {
|
||||
ASN1_INTEGER *num;
|
||||
X509 *x = sk_X509_value(sk, i);
|
||||
EVP_PKEY *pubkey = NULL;
|
||||
int j;
|
||||
char *ptr;
|
||||
const ASN1_BIT_STRING *psig = NULL;
|
||||
|
||||
X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
|
||||
push_certinfo("Subject", i);
|
||||
|
||||
X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
|
||||
push_certinfo("Issuer", i);
|
||||
|
||||
BIO_printf(mem, "%lx", X509_get_version(x));
|
||||
push_certinfo("Version", i);
|
||||
|
||||
num = X509_get_serialNumber(x);
|
||||
if(num->type == V_ASN1_NEG_INTEGER)
|
||||
BIO_puts(mem, "-");
|
||||
for(j = 0; j < num->length; j++)
|
||||
BIO_printf(mem, "%02x", num->data[j]);
|
||||
push_certinfo("Serial Number", i);
|
||||
|
||||
#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
|
||||
{
|
||||
const X509_ALGOR *sigalg = NULL;
|
||||
X509_PUBKEY *xpubkey = NULL;
|
||||
ASN1_OBJECT *pubkeyoid = NULL;
|
||||
|
||||
X509_get0_signature(&psig, &sigalg, x);
|
||||
if(sigalg) {
|
||||
i2a_ASN1_OBJECT(mem, sigalg->algorithm);
|
||||
push_certinfo("Signature Algorithm", i);
|
||||
}
|
||||
|
||||
xpubkey = X509_get_X509_PUBKEY(x);
|
||||
if(xpubkey) {
|
||||
X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
|
||||
if(pubkeyoid) {
|
||||
i2a_ASN1_OBJECT(mem, pubkeyoid);
|
||||
push_certinfo("Public Key Algorithm", i);
|
||||
}
|
||||
}
|
||||
|
||||
X509V3_ext(data, i, X509_get0_extensions(x));
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* before OpenSSL 1.0.2 */
|
||||
X509_CINF *cinf = x->cert_info;
|
||||
|
||||
i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
|
||||
push_certinfo("Signature Algorithm", i);
|
||||
|
||||
i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
|
||||
push_certinfo("Public Key Algorithm", i);
|
||||
|
||||
X509V3_ext(data, i, cinf->extensions);
|
||||
|
||||
psig = x->signature;
|
||||
}
|
||||
#endif
|
||||
|
||||
ASN1_TIME_print(mem, X509_get0_notBefore(x));
|
||||
push_certinfo("Start date", i);
|
||||
|
||||
ASN1_TIME_print(mem, X509_get0_notAfter(x));
|
||||
push_certinfo("Expire date", i);
|
||||
|
||||
pubkey = X509_get_pubkey(x);
|
||||
if(!pubkey)
|
||||
infof(data, " Unable to load public key");
|
||||
else {
|
||||
int pktype;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
pktype = EVP_PKEY_id(pubkey);
|
||||
#else
|
||||
pktype = pubkey->type;
|
||||
#endif
|
||||
switch(pktype) {
|
||||
case EVP_PKEY_RSA:
|
||||
{
|
||||
#ifndef HAVE_EVP_PKEY_GET_PARAMS
|
||||
RSA *rsa;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
rsa = EVP_PKEY_get0_RSA(pubkey);
|
||||
#else
|
||||
rsa = pubkey->pkey.rsa;
|
||||
#endif /* HAVE_OPAQUE_EVP_PKEY */
|
||||
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
|
||||
|
||||
{
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
DECLARE_PKEY_PARAM_BIGNUM(n);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(e);
|
||||
#ifdef HAVE_EVP_PKEY_GET_PARAMS
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e);
|
||||
#else
|
||||
RSA_get0_key(rsa, &n, &e, NULL);
|
||||
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
|
||||
BIO_printf(mem, "%d", BN_num_bits(n));
|
||||
#else
|
||||
BIO_printf(mem, "%d", BN_num_bits(rsa->n));
|
||||
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
|
||||
push_certinfo("RSA Public Key", i);
|
||||
print_pubkey_BN(rsa, n, i);
|
||||
print_pubkey_BN(rsa, e, i);
|
||||
FREE_PKEY_PARAM_BIGNUM(n);
|
||||
FREE_PKEY_PARAM_BIGNUM(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EVP_PKEY_DSA:
|
||||
{
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
#ifndef HAVE_EVP_PKEY_GET_PARAMS
|
||||
DSA *dsa;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
dsa = EVP_PKEY_get0_DSA(pubkey);
|
||||
#else
|
||||
dsa = pubkey->pkey.dsa;
|
||||
#endif /* HAVE_OPAQUE_EVP_PKEY */
|
||||
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
|
||||
{
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
DECLARE_PKEY_PARAM_BIGNUM(p);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(q);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(g);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
#ifdef HAVE_EVP_PKEY_GET_PARAMS
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
|
||||
#else
|
||||
DSA_get0_pqg(dsa, &p, &q, &g);
|
||||
DSA_get0_key(dsa, &pub_key, NULL);
|
||||
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
|
||||
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
|
||||
print_pubkey_BN(dsa, p, i);
|
||||
print_pubkey_BN(dsa, q, i);
|
||||
print_pubkey_BN(dsa, g, i);
|
||||
print_pubkey_BN(dsa, pub_key, i);
|
||||
FREE_PKEY_PARAM_BIGNUM(p);
|
||||
FREE_PKEY_PARAM_BIGNUM(q);
|
||||
FREE_PKEY_PARAM_BIGNUM(g);
|
||||
FREE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
}
|
||||
#endif /* !OPENSSL_NO_DSA */
|
||||
break;
|
||||
}
|
||||
case EVP_PKEY_DH:
|
||||
{
|
||||
#ifndef HAVE_EVP_PKEY_GET_PARAMS
|
||||
DH *dh;
|
||||
#ifdef HAVE_OPAQUE_EVP_PKEY
|
||||
dh = EVP_PKEY_get0_DH(pubkey);
|
||||
#else
|
||||
dh = pubkey->pkey.dh;
|
||||
#endif /* HAVE_OPAQUE_EVP_PKEY */
|
||||
#endif /* !HAVE_EVP_PKEY_GET_PARAMS */
|
||||
{
|
||||
#ifdef HAVE_OPAQUE_RSA_DSA_DH
|
||||
DECLARE_PKEY_PARAM_BIGNUM(p);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(q);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(g);
|
||||
DECLARE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
#ifdef HAVE_EVP_PKEY_GET_PARAMS
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g);
|
||||
EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
|
||||
#else
|
||||
DH_get0_pqg(dh, &p, &q, &g);
|
||||
DH_get0_key(dh, &pub_key, NULL);
|
||||
#endif /* HAVE_EVP_PKEY_GET_PARAMS */
|
||||
print_pubkey_BN(dh, p, i);
|
||||
print_pubkey_BN(dh, q, i);
|
||||
print_pubkey_BN(dh, g, i);
|
||||
#else
|
||||
print_pubkey_BN(dh, p, i);
|
||||
print_pubkey_BN(dh, g, i);
|
||||
#endif /* HAVE_OPAQUE_RSA_DSA_DH */
|
||||
print_pubkey_BN(dh, pub_key, i);
|
||||
FREE_PKEY_PARAM_BIGNUM(p);
|
||||
FREE_PKEY_PARAM_BIGNUM(q);
|
||||
FREE_PKEY_PARAM_BIGNUM(g);
|
||||
FREE_PKEY_PARAM_BIGNUM(pub_key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
EVP_PKEY_free(pubkey);
|
||||
}
|
||||
|
||||
if(psig) {
|
||||
for(j = 0; j < psig->length; j++)
|
||||
BIO_printf(mem, "%02x:", psig->data[j]);
|
||||
push_certinfo("Signature", i);
|
||||
}
|
||||
|
||||
PEM_write_bio_X509(mem, x);
|
||||
push_certinfo("Cert", i);
|
||||
}
|
||||
|
||||
BIO_free(mem);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Heavily modified from:
|
||||
* https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
|
||||
@ -3822,8 +3824,8 @@ static CURLcode servercert(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(data->set.ssl.certinfo)
|
||||
/* we've been asked to gather certificate info! */
|
||||
(void)get_cert_chain(data, connssl);
|
||||
/* asked to gather certificate info */
|
||||
(void)Curl_ossl_certchain(data, connssl->backend->handle);
|
||||
|
||||
backend->server_cert = SSL_get1_peer_certificate(backend->handle);
|
||||
if(!backend->server_cert) {
|
||||
|
@ -31,6 +31,7 @@
|
||||
* This header should only be needed to get included by vtls.c, openssl.c
|
||||
* and ngtcp2.c
|
||||
*/
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "urldata.h"
|
||||
|
||||
@ -53,5 +54,7 @@ CURLcode Curl_ossl_set_client_cert(struct Curl_easy *data,
|
||||
const struct curl_blob *key_blob,
|
||||
const char *key_type, char *key_passwd);
|
||||
|
||||
CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl);
|
||||
|
||||
#endif /* USE_OPENSSL */
|
||||
#endif /* HEADER_CURL_SSLUSE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user