summaryrefslogtreecommitdiff
path: root/lib/vtls/openssl.c
diff options
context:
space:
mode:
authorAlessandro Ghedini <alessandro@ghedini.me>2015-10-07 11:05:32 +0200
committerAlessandro Ghedini <alessandro@ghedini.me>2015-10-07 11:05:32 +0200
commitece9e71f37ee07077b315c23f755d2cfe5bd013d (patch)
treead5c84f1dc1354cc0ed7622b21771e443bfce6b5 /lib/vtls/openssl.c
parent9456f51adb76b83ceb4b95c8481325de62b25ad2 (diff)
Imported Upstream version 7.45.0
Diffstat (limited to 'lib/vtls/openssl.c')
-rw-r--r--lib/vtls/openssl.c293
1 files changed, 79 insertions, 214 deletions
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 90e4c2b3..1bb99671 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -702,16 +702,6 @@ int Curl_ossl_init(void)
ENGINE_load_builtin_engines();
#endif
- /* Lets get nice error messages */
- SSL_load_error_strings();
-
- /* Init the global ciphers and digests */
- if(!SSLeay_add_ssl_algorithms())
- return 0;
-
- OpenSSL_add_all_algorithms();
-
-
/* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately
that function makes an exit() call on wrongly formatted config files
which makes it hard to use in some situations. OPENSSL_config() itself
@@ -728,6 +718,15 @@ int Curl_ossl_init(void)
CONF_MFLAGS_DEFAULT_SECTION|
CONF_MFLAGS_IGNORE_MISSING_FILE);
+ /* Lets get nice error messages */
+ SSL_load_error_strings();
+
+ /* Init the global ciphers and digests */
+ if(!SSLeay_add_ssl_algorithms())
+ return 0;
+
+ OpenSSL_add_all_algorithms();
+
return 1;
}
@@ -1015,49 +1014,6 @@ void Curl_ossl_close_all(struct SessionHandle *data)
#endif
}
-static int asn1_output(const ASN1_UTCTIME *tm,
- char *buf,
- size_t sizeofbuf)
-{
- const char *asn1_string;
- int gmt=FALSE;
- int i;
- int year=0, month=0, day=0, hour=0, minute=0, second=0;
-
- i=tm->length;
- asn1_string=(const char *)tm->data;
-
- if(i < 10)
- return 1;
- if(asn1_string[i-1] == 'Z')
- gmt=TRUE;
- for(i=0; i<10; i++)
- if((asn1_string[i] > '9') || (asn1_string[i] < '0'))
- return 2;
-
- year= (asn1_string[0]-'0')*10+(asn1_string[1]-'0');
- if(year < 50)
- year+=100;
-
- month= (asn1_string[2]-'0')*10+(asn1_string[3]-'0');
- if((month > 12) || (month < 1))
- return 3;
-
- day= (asn1_string[4]-'0')*10+(asn1_string[5]-'0');
- hour= (asn1_string[6]-'0')*10+(asn1_string[7]-'0');
- minute= (asn1_string[8]-'0')*10+(asn1_string[9]-'0');
-
- if((asn1_string[10] >= '0') && (asn1_string[10] <= '9') &&
- (asn1_string[11] >= '0') && (asn1_string[11] <= '9'))
- second= (asn1_string[10]-'0')*10+(asn1_string[11]-'0');
-
- snprintf(buf, sizeofbuf,
- "%04d-%02d-%02d %02d:%02d:%02d %s",
- year+1900, month, day, hour, minute, second, (gmt?"GMT":""));
-
- return 0;
-}
-
/* ====================================================== */
@@ -2256,43 +2212,33 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
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); \
+ BIO_reset(mem); \
+} WHILE_FALSE
+
static void pubkey_show(struct SessionHandle *data,
+ BIO *mem,
int num,
const char *type,
const char *name,
- unsigned char *raw,
- int len)
+ BIGNUM *bn)
{
- size_t left;
- int i;
+ char *ptr;
char namebuf[32];
- char *buffer;
-
- left = len*3 + 1;
- buffer = malloc(left);
- if(buffer) {
- char *ptr=buffer;
- snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
- for(i=0; i< len; i++) {
- snprintf(ptr, left, "%02x:", raw[i]);
- ptr += 3;
- left -= 3;
- }
- infof(data, " %s: %s\n", namebuf, buffer);
- Curl_ssl_push_certinfo(data, num, namebuf, buffer);
- free(buffer);
- }
+
+ snprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name);
+
+ BN_print(mem, bn);
+ push_certinfo(namebuf, num);
}
#define print_pubkey_BN(_type, _name, _num) \
do { \
if(pubkey->pkey._type->_name) { \
- int len = BN_num_bytes(pubkey->pkey._type->_name); \
- if(len < CERTBUFFERSIZE) { \
- BN_bn2bin(pubkey->pkey._type->_name, (unsigned char*)bufp); \
- bufp[len] = 0; \
- pubkey_show(data, _num, #_type, #_name, (unsigned char*)bufp, len); \
- } \
+ pubkey_show(data, mem, _num, #_type, #_name, pubkey->pkey._type->_name); \
} \
} WHILE_FALSE
@@ -2323,18 +2269,12 @@ static int X509V3_ext(struct SessionHandle *data,
asn1_object_dump(obj, namebuf, sizeof(namebuf));
- infof(data, "%s: %s\n", namebuf,
- X509_EXTENSION_get_critical(ext)?"(critical)":"");
-
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);
- /* biomem->length bytes at biomem->data, this little loop here is only
- done for the infof() call, we send the "raw" data to the certinfo
- function */
- for(j=0; j<(size_t)biomem->length; j++) {
+ for(j = 0; j < (size_t)biomem->length; j++) {
const char *sep="";
if(biomem->data[j] == '\n') {
sep=", ";
@@ -2346,7 +2286,6 @@ static int X509V3_ext(struct SessionHandle *data,
ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
biomem->data[j]);
}
- infof(data, " %s\n", buf);
Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
@@ -2356,46 +2295,6 @@ static int X509V3_ext(struct SessionHandle *data,
return 0; /* all is fine */
}
-
-static void X509_signature(struct SessionHandle *data,
- int numcert,
- ASN1_STRING *sig)
-{
- char buf[1024];
- char *ptr = buf;
- int i;
-
- for(i=0; i<sig->length; i++)
- ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]);
-
- infof(data, " Signature: %s\n", buf);
- Curl_ssl_push_certinfo(data, numcert, "Signature", buf);
-}
-
-static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
-{
- BIO *bio_out = BIO_new(BIO_s_mem());
- BUF_MEM *biomem;
-
- /* this outputs the cert in this 64 column wide style with newlines and
- -----BEGIN CERTIFICATE----- texts and more */
- PEM_write_bio_X509(bio_out, x);
-
- BIO_get_mem_ptr(bio_out, &biomem);
-
- Curl_ssl_push_certinfo_len(data, numcert,
- "Cert", biomem->data, biomem->length);
-
- BIO_free(bio_out);
-}
-
-/*
- * This size was previously 512 which has been reported "too small" without
- * any specifics, so it was enlarged to allow more data to get shown uncut.
- * The "perfect" size is yet to figure out.
- */
-#define CERTBUFFERSIZE 8192
-
static CURLcode get_cert_chain(struct connectdata *conn,
struct ssl_connect_data *connssl)
@@ -2403,17 +2302,12 @@ static CURLcode get_cert_chain(struct connectdata *conn,
CURLcode result;
STACK_OF(X509) *sk;
int i;
- char *bufp;
struct SessionHandle *data = conn->data;
int numcerts;
-
- bufp = malloc(CERTBUFFERSIZE);
- if(!bufp)
- return CURLE_OUT_OF_MEMORY;
+ BIO *mem;
sk = SSL_get_peer_cert_chain(connssl->handle);
if(!sk) {
- free(bufp);
return CURLE_OUT_OF_MEMORY;
}
@@ -2421,87 +2315,50 @@ static CURLcode get_cert_chain(struct connectdata *conn,
result = Curl_ssl_init_certinfo(data, numcerts);
if(result) {
- free(bufp);
return result;
}
- infof(data, "--- Certificate chain\n");
- for(i=0; i<numcerts; i++) {
- long value;
+ mem = BIO_new(BIO_s_mem());
+
+ for(i = 0; i < numcerts; i++) {
ASN1_INTEGER *num;
- ASN1_TIME *certdate;
- /* get the certs in "importance order" */
-#if 0
- X509 *x = sk_X509_value(sk, numcerts - i - 1);
-#else
X509 *x = sk_X509_value(sk, i);
-#endif
X509_CINF *cinf;
EVP_PKEY *pubkey=NULL;
int j;
char *ptr;
- (void)x509_name_oneline(X509_get_subject_name(x), bufp, CERTBUFFERSIZE);
- infof(data, "%2d Subject: %s\n", i, bufp);
- Curl_ssl_push_certinfo(data, i, "Subject", bufp);
-
- (void)x509_name_oneline(X509_get_issuer_name(x), bufp, CERTBUFFERSIZE);
- infof(data, " Issuer: %s\n", bufp);
- Curl_ssl_push_certinfo(data, i, "Issuer", bufp);
+ X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Subject", i);
- value = X509_get_version(x);
- infof(data, " Version: %lu (0x%lx)\n", value+1, value);
- snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
- Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */
-
- num=X509_get_serialNumber(x);
- {
- int left = CERTBUFFERSIZE;
+ X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE);
+ push_certinfo("Issuer", i);
- ptr = bufp;
- if(num->type == V_ASN1_NEG_INTEGER) {
- *ptr++='-';
- left--;
- }
+ BIO_printf(mem, "%lx", X509_get_version(x));
+ push_certinfo("Version", i);
- for(j=0; (j<num->length) && (left>=3); j++) {
- snprintf(ptr, left, "%02x", num->data[j]);
- ptr += 2;
- left -= 2;
- }
- if(num->length)
- infof(data, " Serial Number: %s\n", bufp);
- else
- bufp[0]=0;
- }
- if(bufp[0])
- Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */
+ 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);
cinf = x->cert_info;
- j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE);
- if(!j) {
- infof(data, " Signature Algorithm: %s\n", bufp);
- Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp);
- }
+ i2a_ASN1_OBJECT(mem, cinf->signature->algorithm);
+ push_certinfo("Signature Algorithm", i);
- certdate = X509_get_notBefore(x);
- asn1_output(certdate, bufp, CERTBUFFERSIZE);
- infof(data, " Start date: %s\n", bufp);
- Curl_ssl_push_certinfo(data, i, "Start date", bufp);
+ ASN1_TIME_print(mem, X509_get_notBefore(x));
+ push_certinfo("Start date", i);
- certdate = X509_get_notAfter(x);
- asn1_output(certdate, bufp, CERTBUFFERSIZE);
- infof(data, " Expire date: %s\n", bufp);
- Curl_ssl_push_certinfo(data, i, "Expire date", bufp);
+ ASN1_TIME_print(mem, X509_get_notAfter(x));
+ push_certinfo("Expire date", i);
- j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE);
- if(!j) {
- infof(data, " Public Key Algorithm: %s\n", bufp);
- Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp);
- }
+ i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm);
+ push_certinfo("Public Key Algorithm", i);
pubkey = X509_get_pubkey(x);
if(!pubkey)
@@ -2509,10 +2366,8 @@ static CURLcode get_cert_chain(struct connectdata *conn,
else {
switch(pubkey->type) {
case EVP_PKEY_RSA:
- infof(data, " RSA Public Key (%d bits)\n",
- BN_num_bits(pubkey->pkey.rsa->n));
- snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n));
- Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp);
+ BIO_printf(mem, "%d", BN_num_bits(pubkey->pkey.rsa->n));
+ push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
print_pubkey_BN(rsa, e, i);
@@ -2547,12 +2402,15 @@ static CURLcode get_cert_chain(struct connectdata *conn,
X509V3_ext(data, i, cinf->extensions);
- X509_signature(data, i, x->signature);
+ for(j = 0; j < x->signature->length; j++)
+ BIO_printf(mem, "%02x:", x->signature->data[j]);
+ push_certinfo("Signature", i);
- dumpcert(data, x, i);
+ PEM_write_bio_X509(mem, x);
+ push_certinfo("Cert", i);
}
- free(bufp);
+ BIO_free(mem);
return CURLE_OK;
}
@@ -2561,7 +2419,8 @@ static CURLcode get_cert_chain(struct connectdata *conn,
* Heavily modified from:
* https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
*/
-static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey)
+static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data, X509* cert,
+ const char *pinnedpubkey)
{
/* Scratch */
int len1 = 0, len2 = 0;
@@ -2606,7 +2465,7 @@ static CURLcode pkp_pin_peer_pubkey(X509* cert, const char *pinnedpubkey)
/* End Gyrations */
/* The one good exit point */
- result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
+ result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
} while(0);
/* https://www.openssl.org/docs/crypto/buffer.html */
@@ -2630,13 +2489,13 @@ static CURLcode servercert(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
int rc;
- long lerr;
- ASN1_TIME *certdate;
+ long lerr, len;
struct SessionHandle *data = conn->data;
X509 *issuer;
FILE *fp;
char *buffer = data->state.buffer;
const char *ptr;
+ BIO *mem = BIO_new(BIO_s_mem());
if(data->set.ssl.certinfo)
/* we've been asked to gather certificate info! */
@@ -2644,8 +2503,10 @@ static CURLcode servercert(struct connectdata *conn,
connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
if(!connssl->server_cert) {
- if(strict)
- failf(data, "SSL: couldn't get peer certificate!");
+ if(!strict)
+ return CURLE_OK;
+
+ failf(data, "SSL: couldn't get peer certificate!");
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -2655,13 +2516,17 @@ static CURLcode servercert(struct connectdata *conn,
buffer, BUFSIZE);
infof(data, "\t subject: %s\n", rc?"[NONE]":buffer);
- certdate = X509_get_notBefore(connssl->server_cert);
- asn1_output(certdate, buffer, BUFSIZE);
- infof(data, "\t start date: %s\n", buffer);
+ ASN1_TIME_print(mem, X509_get_notBefore(connssl->server_cert));
+ len = BIO_get_mem_data(mem, &ptr);
+ infof(data, "\t start date: %.*s\n", len, ptr);
+ BIO_reset(mem);
+
+ ASN1_TIME_print(mem, X509_get_notAfter(connssl->server_cert));
+ len = BIO_get_mem_data(mem, &ptr);
+ infof(data, "\t expire date: %.*s\n", len, ptr);
+ BIO_reset(mem);
- certdate = X509_get_notAfter(connssl->server_cert);
- asn1_output(certdate, buffer, BUFSIZE);
- infof(data, "\t expire date: %s\n", buffer);
+ BIO_free(mem);
if(data->set.ssl.verifyhost) {
result = verifyhost(conn, connssl->server_cert);
@@ -2764,7 +2629,7 @@ static CURLcode servercert(struct connectdata *conn,
ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(!result && ptr) {
- result = pkp_pin_peer_pubkey(connssl->server_cert, ptr);
+ result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
if(result)
failf(data, "SSL: public key does not match pinned public key!");
}
@@ -3183,7 +3048,7 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */
MD5_Final(md5sum, &MD5pw);
}
-#ifndef OPENSSL_NO_SHA256
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,