diff options
Diffstat (limited to 'lib/vtls/mbedtls.c')
-rw-r--r-- | lib/vtls/mbedtls.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index cfebedf53..05af46212 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com> - * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -141,6 +141,53 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = 1024, /* RSA min key len */ }; +/* 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 * MBEDTLS_MPI_MAX_SIZE) +#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_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) + +static int +mbedtls_verify_pinned_crt(void *p, mbedtls_x509_crt *crt, + int depth, unsigned int *flags) +{ + struct SessionHandle *data = p; + unsigned char pubkey[PUB_DER_MAX_BYTES]; + int ret; + int size; + char *pinned_cert = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + + /* Skip intermediate and root certificates */ + if(depth) { + return 0; + } + + if(pinned_cert == NULL || crt == NULL) { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return 1; + } + + /* Extract pubkey */ + size = mbedtls_pk_write_pubkey_der(&crt->pk, pubkey, PUB_DER_MAX_BYTES); + if(size <= 0) { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return 1; + } + + /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ + ret = Curl_pin_peer_pubkey(data, pinned_cert, + &pubkey[PUB_DER_MAX_BYTES - size], size); + if(ret == CURLE_OK) { + return 0; + } + + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return 1; +} + static Curl_recv mbedtls_recv; static Curl_send mbedtls_send; @@ -636,6 +683,10 @@ mbedtls_connect_common(struct connectdata *conn, long timeout_ms; int what; + if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + mbedtls_ssl_conf_verify(&connssl->config, mbedtls_verify_pinned_crt, data); + } + /* check if the connection has already been established */ if(ssl_connection_complete == connssl->state) { *done = TRUE; |