aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormoparisthebest <admin@moparisthebest.com>2015-06-30 20:23:54 -0400
committerDaniel Stenberg <daniel@haxx.se>2015-07-01 19:43:47 +0200
commit55b78c5ae94852ffb942ff979e6f25aebfeedb16 (patch)
tree73c9f909baac1e3f6bc9c3f09ed5819d4be18653 /lib
parentc00b18d5406375627b98b47e68261ace85d1a581 (diff)
SSL: Pinned public key hash support
Diffstat (limited to 'lib')
-rw-r--r--lib/vtls/cyassl.c13
-rw-r--r--lib/vtls/cyassl.h5
-rw-r--r--lib/vtls/gtls.c20
-rw-r--r--lib/vtls/gtls.h5
-rw-r--r--lib/vtls/nss.c13
-rw-r--r--lib/vtls/nssg.h6
-rw-r--r--lib/vtls/openssl.c12
-rw-r--r--lib/vtls/openssl.h5
-rw-r--r--lib/vtls/vtls.c66
-rw-r--r--lib/vtls/vtls.h4
10 files changed, 149 insertions, 0 deletions
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 40dbbe134..3ded7f11d 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -67,6 +67,7 @@ and that's a problem since options.h hasn't been included yet. */
#include <cyassl/error.h>
#endif
#include <cyassl/ctaocrypt/random.h>
+#include <cyassl/ctaocrypt/sha256.h>
/* The last #include files should be: */
#include "curl_memory.h"
@@ -770,4 +771,16 @@ int Curl_cyassl_random(struct SessionHandle *data,
return 0;
}
+void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
+{
+ Sha256 SHA256pw;
+ (void)unused;
+ InitSha256(&SHA256pw);
+ Sha256Update(&SHA256pw, tmp, tmplen);
+ Sha256Final(&SHA256pw, sha256sum);
+}
+
#endif
diff --git a/lib/vtls/cyassl.h b/lib/vtls/cyassl.h
index 12638a76d..447816b87 100644
--- a/lib/vtls/cyassl.h
+++ b/lib/vtls/cyassl.h
@@ -42,6 +42,10 @@ CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
int Curl_cyassl_random(struct SessionHandle *data,
unsigned char *entropy,
size_t length);
+void Curl_cyassl_sha256sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t unused);
/* Set the API backend definition to Schannel */
#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
@@ -65,6 +69,7 @@ int Curl_cyassl_random(struct SessionHandle *data,
#define curlssl_check_cxn(x) ((void)x, -1)
#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
+#define curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d)
#endif /* USE_CYASSL */
#endif /* HEADER_CURL_CYASSL_H */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 1db31e40c..c54dfc1d2 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -39,6 +39,7 @@
#ifdef USE_GNUTLS_NETTLE
#include <gnutls/crypto.h>
#include <nettle/md5.h>
+#include <nettle/sha2.h>
#else
#include <gcrypt.h>
#endif
@@ -1557,6 +1558,25 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
#endif
}
+void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
+{
+#if defined(USE_GNUTLS_NETTLE)
+ struct sha256_ctx SHA256pw;
+ sha256_init(&SHA256pw);
+ sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
+ sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
+#elif defined(USE_GNUTLS)
+ gcry_md_hd_t SHA256pw;
+ gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
+ gcry_md_write(SHA256pw, tmp, tmplen);
+ memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len);
+ gcry_md_close(SHA256pw);
+#endif
+}
+
bool Curl_gtls_cert_status_request(void)
{
#ifdef HAS_OCSP
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index dcae44225..0afd9b94a 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -48,6 +48,10 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum, /* output */
size_t md5len);
+void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len);
bool Curl_gtls_cert_status_request(void);
@@ -77,6 +81,7 @@ bool Curl_gtls_cert_status_request(void);
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
+#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
#endif /* USE_GNUTLS */
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 5434ce382..91727c7c3 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -2041,6 +2041,19 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
PK11_DestroyContext(MD5pw, PR_TRUE);
}
+void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
+{
+ PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
+ unsigned int SHA256out;
+
+ PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
+ PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
+ PK11_DestroyContext(SHA256pw, PR_TRUE);
+}
+
bool Curl_nss_cert_status_request(void)
{
#ifdef SSL_ENABLE_OCSP_STAPLING
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index d0e74124e..5fd72751d 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -56,6 +56,11 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
unsigned char *md5sum, /* output */
size_t md5len);
+void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len);
+
bool Curl_nss_cert_status_request(void);
bool Curl_nss_false_start(void);
@@ -89,6 +94,7 @@ bool Curl_nss_false_start(void);
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
+#define curlssl_sha256sum(a,b,c,d) Curl_nss_sha256sum(a,b,c,d)
#define curlssl_cert_status_request() Curl_nss_cert_status_request()
#define curlssl_false_start() Curl_nss_false_start()
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 37d50cb60..e41499f90 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -3183,6 +3183,18 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */
MD5_Final(md5sum, &MD5pw);
}
+void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
+{
+ SHA256_CTX SHA256pw;
+ (void)unused;
+ SHA256_Init(&SHA256pw);
+ SHA256_Update(&SHA256pw, tmp, tmplen);
+ SHA256_Final(sha256sum, &SHA256pw);
+}
+
bool Curl_ossl_cert_status_request(void)
{
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index 499b4fe29..ebac542b7 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -72,6 +72,10 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum /* output */,
size_t unused);
+void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused);
bool Curl_ossl_cert_status_request(void);
@@ -104,6 +108,7 @@ bool Curl_ossl_cert_status_request(void);
#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
+#define curlssl_sha256sum(a,b,c,d) Curl_ossl_sha256sum(a,b,c,d)
#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
#define DEFAULT_CIPHER_SELECTION \
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 42a2b58a0..01bbc6130 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -774,12 +774,78 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
size_t size, pem_len;
CURLcode pem_read;
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+#ifdef curlssl_sha256sum
+ size_t pinkeylen;
+ char *pinkeycopy, *begin_pos, *end_pos;
+ unsigned char *sha256sumdigest = NULL, *expectedsha256sumdigest = NULL;
+#endif
/* if a path wasn't specified, don't pin */
if(!pinnedpubkey)
return CURLE_OK;
if(!pubkey || !pubkeylen)
return result;
+
+#ifdef curlssl_sha256sum
+ /* only do this if pinnedpubkey starts with "sha256//", length 8 */
+ if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
+ /* compute sha256sum of public key */
+ sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
+ if(!sha256sumdigest)
+ return CURLE_OUT_OF_MEMORY;
+ curlssl_sha256sum(pubkey, pubkeylen,
+ sha256sumdigest, SHA256_DIGEST_LENGTH);
+
+ /* it starts with sha256//, copy so we can modify it */
+ pinkeylen = strlen(pinnedpubkey) + 1;
+ pinkeycopy = malloc(pinkeylen);
+ if(!pinkeycopy) {
+ Curl_safefree(sha256sumdigest);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
+ /* point begin_pos to the copy, and start extracting keys */
+ begin_pos = pinkeycopy;
+ do {
+ end_pos = strstr(begin_pos, ";sha256//");
+ /*
+ * if there is an end_pos, null terminate,
+ * otherwise it'll go to the end of the original string
+ */
+ if(end_pos)
+ end_pos[0] = '\0';
+
+ /* decode base64 pinnedpubkey, 8 is length of "sha256//" */
+ pem_read = Curl_base64_decode(begin_pos + 8,
+ &expectedsha256sumdigest, &size);
+ /* if not valid base64, don't bother comparing or freeing */
+ if(!pem_read) {
+ /* compare sha256 digests directly */
+ if(SHA256_DIGEST_LENGTH == size &&
+ !memcmp(sha256sumdigest, expectedsha256sumdigest,
+ SHA256_DIGEST_LENGTH)) {
+ result = CURLE_OK;
+ Curl_safefree(expectedsha256sumdigest);
+ break;
+ }
+ Curl_safefree(expectedsha256sumdigest);
+ }
+
+ /*
+ * change back the null-terminator we changed earlier,
+ * and look for next begin
+ */
+ if(end_pos) {
+ end_pos[0] = ';';
+ begin_pos = strstr(end_pos, "sha256//");
+ }
+ } while(end_pos && begin_pos);
+ Curl_safefree(sha256sumdigest);
+ Curl_safefree(pinkeycopy);
+ return result;
+ }
+#endif
+
fp = fopen(pinnedpubkey, "rb");
if(!fp)
return result;
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index b9741d7af..2349e5b93 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -41,6 +41,10 @@
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH 32 /* fixed size */
+#endif
+
/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
#define ALPN_HTTP_1_1_LENGTH 8
#define ALPN_HTTP_1_1 "http/1.1"