aboutsummaryrefslogtreecommitdiff
path: root/lib/vtls/polarssl.c
diff options
context:
space:
mode:
authormoparisthebest <admin@moparisthebest.com>2016-04-21 21:21:45 -0400
committerDaniel Stenberg <daniel@haxx.se>2016-04-24 12:27:39 +0200
commit33623d7196dd95bfeeb2b4008911459aa165d876 (patch)
tree0c4411a7dbee612ffbb734cb08feb51f15fb349d /lib/vtls/polarssl.c
parent7639a9cfc9d4e9a97ee931c1177a544b4bec8f6f (diff)
PolarSSL: Implement public key pinning
Diffstat (limited to 'lib/vtls/polarssl.c')
-rw-r--r--lib/vtls/polarssl.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index fcce60f05..0c6ef239e 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -36,6 +36,7 @@
#include <polarssl/certs.h>
#include <polarssl/x509.h>
#include <polarssl/version.h>
+#include <polarssl/sha256.h>
#if POLARSSL_VERSION_NUMBER < 0x01030000
#error too old PolarSSL
@@ -60,6 +61,15 @@
/* The last #include file should be: */
#include "memdebug.h"
+/* See https://tls.mbed.org/discussions/generic/
+ howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
+*/
+#define RSA_PUB_DER_MAX_BYTES (38 + 2 * POLARSSL_MPI_MAX_SIZE)
+#define ECP_PUB_DER_MAX_BYTES (30 + 2 * POLARSSL_ECP_MAX_BYTES)
+
+#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
+ RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
+
/* apply threading? */
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
#define THREADING_SUPPORT
@@ -453,6 +463,61 @@ polarssl_connect_step2(struct connectdata *conn,
infof(data, "Dumping cert info:\n%s\n", buffer);
}
+ /* adapted from mbedtls.c */
+ if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+ int size;
+ CURLcode result;
+ x509_crt *p;
+ unsigned char pubkey[PUB_DER_MAX_BYTES];
+ const x509_crt *peercert;
+
+ peercert = ssl_get_peer_cert(&connssl->ssl);
+
+ if(!peercert || !peercert->raw.p || !peercert->raw.len) {
+ failf(data, "Failed due to missing peer certificate");
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ p = calloc(1, sizeof(*p));
+
+ if(!p)
+ return CURLE_OUT_OF_MEMORY;
+
+ x509_crt_init(p);
+
+ /* Make a copy of our const peercert because pk_write_pubkey_der
+ needs a non-const key, for now.
+ https://github.com/ARMmbed/mbedtls/issues/396 */
+ if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
+ failf(data, "Failed copying peer certificate");
+ x509_crt_free(p);
+ free(p);
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
+
+ if(size <= 0) {
+ failf(data, "Failed copying public key from peer certificate");
+ x509_crt_free(p);
+ free(p);
+ return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ }
+
+ /* pk_write_pubkey_der writes data at the end of the buffer. */
+ result = Curl_pin_peer_pubkey(data,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ &pubkey[PUB_DER_MAX_BYTES - size], size);
+ if(result) {
+ x509_crt_free(p);
+ free(p);
+ return result;
+ }
+
+ x509_crt_free(p);
+ free(p);
+ }
+
#ifdef HAS_ALPN
if(data->set.ssl_enable_alpn) {
const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);