diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vtls/mbedtls.c | 115 | 
1 files changed, 66 insertions, 49 deletions
| diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 05af46212..26959e041 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -148,45 +148,7 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =  #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; -} +                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)  static Curl_recv mbedtls_recv;  static Curl_send mbedtls_send; @@ -455,7 +417,7 @@ mbedtls_connect_step2(struct connectdata *conn,    int ret;    struct SessionHandle *data = conn->data;    struct ssl_connect_data* connssl = &conn->ssl[sockindex]; -  char buffer[1024]; +  const mbedtls_x509_crt *peercert;  #ifdef HAS_ALPN    const char* next_protocol; @@ -510,13 +472,72 @@ mbedtls_connect_step2(struct connectdata *conn,      return CURLE_PEER_FAILED_VERIFICATION;    } -  if(mbedtls_ssl_get_peer_cert(&(connssl->ssl))) { -    /* If the session was resumed, there will be no peer certs */ -    memset(buffer, 0, sizeof(buffer)); +  peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl); -    if(mbedtls_x509_crt_info(buffer, sizeof(buffer), (char *)"* ", -                     mbedtls_ssl_get_peer_cert(&(connssl->ssl))) != -1) +  if(peercert && data->set.verbose) { +    const size_t bufsize = 16384; +    char *buffer = malloc(bufsize); + +    if(!buffer) +      return CURLE_OUT_OF_MEMORY; + +    if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)        infof(data, "Dumping cert info:\n%s\n", buffer); +    else +      infof(data, "Unable to dump certificate information.\n"); + +    free(buffer); +  } + +  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { +    int size; +    CURLcode result; +    mbedtls_x509_crt *p; +    unsigned char pubkey[PUB_DER_MAX_BYTES]; + +    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; + +    mbedtls_x509_crt_init(p); + +    /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der +       needs a non-const key, for now. +       https://github.com/ARMmbed/mbedtls/issues/396 */ +    if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { +      failf(data, "Failed copying peer certificate"); +      mbedtls_x509_crt_free(p); +      free(p); +      return CURLE_SSL_PINNEDPUBKEYNOTMATCH; +    } + +    size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); + +    if(size <= 0) { +      failf(data, "Failed copying public key from peer certificate"); +      mbedtls_x509_crt_free(p); +      free(p); +      return CURLE_SSL_PINNEDPUBKEYNOTMATCH; +    } + +    /* mbedtls_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) { +      mbedtls_x509_crt_free(p); +      free(p); +      return result; +    } + +    mbedtls_x509_crt_free(p); +    free(p);    }  #ifdef HAS_ALPN @@ -683,10 +704,6 @@ 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; | 
