diff options
author | moparisthebest <admin@moparisthebest.com> | 2015-06-30 20:23:54 -0400 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2015-07-01 19:43:47 +0200 |
commit | 55b78c5ae94852ffb942ff979e6f25aebfeedb16 (patch) | |
tree | 73c9f909baac1e3f6bc9c3f09ed5819d4be18653 /lib | |
parent | c00b18d5406375627b98b47e68261ace85d1a581 (diff) |
SSL: Pinned public key hash support
Diffstat (limited to 'lib')
-rw-r--r-- | lib/vtls/cyassl.c | 13 | ||||
-rw-r--r-- | lib/vtls/cyassl.h | 5 | ||||
-rw-r--r-- | lib/vtls/gtls.c | 20 | ||||
-rw-r--r-- | lib/vtls/gtls.h | 5 | ||||
-rw-r--r-- | lib/vtls/nss.c | 13 | ||||
-rw-r--r-- | lib/vtls/nssg.h | 6 | ||||
-rw-r--r-- | lib/vtls/openssl.c | 12 | ||||
-rw-r--r-- | lib/vtls/openssl.h | 5 | ||||
-rw-r--r-- | lib/vtls/vtls.c | 66 | ||||
-rw-r--r-- | lib/vtls/vtls.h | 4 |
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" |