Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented BearSSL: CURLOPT_SSL_CTX_FUNCTION #8478

Closed
wants to merge 2 commits into from

Conversation

jan2000
Copy link
Contributor

@jan2000 jan2000 commented Feb 19, 2022

Separated from: #8106

Implemented the CURLOPT_SSL_CTX_FUNCTION option for BearSSL.

Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL and in 7.54.0 for
mbedTLS. Other SSL backends are not supported.
Added in 7.11.0 for OpenSSL, in 7.42.0 for wolfSSL, in 7.54.0 for mbedTLS,
in 7.82.0 in BearSSL. Other SSL backends are not supported.
Copy link
Member

@jay jay Feb 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also change this section in CURLOPT_SSL_CTX_FUNCTION.3. and feature window is currently closed, next one is likely 7.83

return ret;
}
}

if(!br_ssl_client_reset(&backend->ctx, hostname, 0))
Copy link
Member

@jay jay Feb 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't the ctx callback call come after the reset ctx call?

Copy link
Contributor

@michaelforney michaelforney Feb 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

br_ssl_client_reset is documented as "Prepare or reset a client context for a new connection", it doesn't completely wipe the context (that's br_ssl_client_zero) or reinitialize the settings that may have been set by the callback. So this is the right place for it.

@jan2000
Copy link
Contributor Author

@jan2000 jan2000 commented Feb 20, 2022

To further clarify, my own use case for the context function is to inject entropy into the engine on an OS (ECOS) that does not support the native entropy sources supported by BearSSL. See the example below.

This must be done before br_ssl_client_reset:

A possible failure condition is when no initial entropy was injected, and none could be obtained from the OS (either OS randomness gathering is not supported, or it failed).
https://www.bearssl.org/apidoc/bearssl__ssl_8h.html#a847209e73dae3ec3a730041337c785b5

/* BearSSL specific */
#include <bearssl.h>
#include <curl/curl.h>
#include <stdio.h>
#include <time.h>

/*
 * CURLOPT_SSL_CTX_FUNCTION EXAMPLE: inject entropy into the BearSSL engine
 *
 * Inject entropy on OS/architecture that does not support an entropy
 * source that is implemented in BearSSL (RDRAND, getentropy,
 * /dev/urandom, CryptGenRandom).
 *
 * Excerpt from br_ssl_engine_inject_entropy documentation:
 *
 * In all generality, "entropy" must here be considered to mean "that which
 * the attacker cannot predict". If your OS/architecture does not have a
 * suitable source of randomness, then you can make do with the combination
 * of a large enough secret value (possibly a copy of an asymmetric private
 * key that you also store on the system) AND a non-repeating value (e.g.
 * current time, provided that the local clock cannot be reset or altered
 * by the attacker).
 */

static CURLcode my_sslctx_fn(CURL *curl, void *ssl_ctx,
                                         void *usr_ptr)
{
  br_ssl_client_context *cc = (br_ssl_client_context *) ssl_ctx;
  char *secret = (char *) usr_ptr;
  char buf[32];
  struct timespec ts;
  (void) curl;
  int i;

  if(clock_gettime(CLOCK_REALTIME, &ts))
    return CURLE_FAILED_INIT;

  /* Combine the clock and our secret to have a non-repeating value */
  for(i = 0; i < 32; i++)
    buf[i] = (char) (secret[i] ^ ((char *) &ts)[i % sizeof(ts)]);

  br_ssl_engine_inject_entropy(&cc->eng, buf, 32);
  return CURLE_OK;
}

int main(void)
{
  CURL *curl;
  CURLcode ret;
  /* If we do not have a suitable source of randomness, then we have
   * to resort to a secret string of bytes. */
  char secret[32] = "EXAMPLE \0NLY! USE A R\xEAL SECRET!!";

  curl_global_init(CURL_GLOBAL_ALL);
  curl = curl_easy_init();

  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L);
  curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");

  curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, my_sslctx_fn);
  curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, (void *) &secret);

  ret = curl_easy_perform(curl);
  if(!ret)
    printf("*** transfer succeeded ***\n");
  else
    printf("*** transfer failed %s***\n", curl_easy_strerror(ret));

  curl_easy_cleanup(curl);
  curl_global_cleanup();
  return ret;
}

@bagder
Copy link
Member

@bagder bagder commented Mar 10, 2022

This PR has conflicts now. Can you please fix those and force-push?

@jan2000 jan2000 force-pushed the bearssl-add-ssl-ctx-function branch from 256d1af to 53dba7d Compare Mar 10, 2022
bagder
bagder approved these changes Mar 12, 2022
@bagder
Copy link
Member

@bagder bagder commented Mar 12, 2022

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants