* evil casts, but these functions are only called if there's a library
* bug
*/
- (int (*)(SSL *, SSL3_RECORD *, unsigned int, int))ssl_undefined_function,
+ (int (*)(SSL *, SSL3_RECORD *, size_t, int))ssl_undefined_function,
(int (*)(SSL *, SSL3_RECORD *, unsigned char *, int))ssl_undefined_function,
ssl_undefined_function,
- (int (*)(SSL *, unsigned char *, unsigned char *, int))
+ (int (*)(SSL *, unsigned char *, unsigned char *, size_t, size_t *))
ssl_undefined_function,
(int (*)(SSL *, int))ssl_undefined_function,
- (int (*)(SSL *, const char *, int, unsigned char *))
+ (size_t (*)(SSL *, const char *, size_t, unsigned char *))
ssl_undefined_function,
- 0, /* finish_mac_length */
NULL, /* client_finished_label */
0, /* client_finished_label_len */
NULL, /* server_finished_label */
struct ssl_async_args {
SSL *s;
void *buf;
- int num;
- enum { READFUNC, WRITEFUNC, OTHERFUNC} type;
+ size_t num;
+ enum { READFUNC, WRITEFUNC, OTHERFUNC } type;
union {
- int (*func_read)(SSL *, void *, int);
- int (*func_write)(SSL *, const void *, int);
- int (*func_other)(SSL *);
+ int (*func_read) (SSL *, void *, size_t, size_t *);
+ int (*func_write) (SSL *, const void *, size_t, size_t *);
+ int (*func_other) (SSL *);
} f;
};
static const struct {
uint8_t mtype;
uint8_t ord;
- int nid;
+ int nid;
} dane_mds[] = {
- { DANETLS_MATCHING_FULL, 0, NID_undef },
- { DANETLS_MATCHING_2256, 1, NID_sha256 },
- { DANETLS_MATCHING_2512, 2, NID_sha512 },
+ {
+ DANETLS_MATCHING_FULL, 0, NID_undef
+ },
+ {
+ DANETLS_MATCHING_2256, 1, NID_sha256
+ },
+ {
+ DANETLS_MATCHING_2512, 2, NID_sha512
+ },
};
static int dane_ctx_enable(struct dane_ctx_st *dctx)
const EVP_MD **mdevp;
uint8_t *mdord;
uint8_t mdmax = DANETLS_MATCHING_LAST;
- int n = ((int) mdmax) + 1; /* int to handle PrivMatch(255) */
+ int n = ((int)mdmax) + 1; /* int to handle PrivMatch(255) */
size_t i;
+ if (dctx->mdevp != NULL)
+ return 1;
+
mdevp = OPENSSL_zalloc(n * sizeof(*mdevp));
mdord = OPENSSL_zalloc(n * sizeof(*mdord));
return 1;
dane_final(&to->dane);
+ to->dane.flags = from->dane.flags;
to->dane.dctx = &to->ctx->dane;
to->dane.trecs = sk_danetls_record_new_null();
return 0;
}
- num = sk_danetls_record_num(from->dane.trecs);
+ num = sk_danetls_record_num(from->dane.trecs);
for (i = 0; i < num; ++i) {
danetls_record *t = sk_danetls_record_value(from->dane.trecs, i);
return 1;
}
-static int dane_mtype_set(
- struct dane_ctx_st *dctx,
- const EVP_MD *md,
- uint8_t mtype,
- uint8_t ord)
+static int dane_mtype_set(struct dane_ctx_st *dctx,
+ const EVP_MD *md, uint8_t mtype, uint8_t ord)
{
int i;
if (mtype == DANETLS_MATCHING_FULL && md != NULL) {
- SSLerr(SSL_F_DANE_MTYPE_SET,
- SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
+ SSLerr(SSL_F_DANE_MTYPE_SET, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
return 0;
}
if (mtype > dctx->mdmax) {
const EVP_MD **mdevp;
uint8_t *mdord;
- int n = ((int) mtype) + 1;
+ int n = ((int)mtype) + 1;
mdevp = OPENSSL_realloc(dctx->mdevp, n * sizeof(*mdevp));
if (mdevp == NULL) {
dctx->mdord = mdord;
/* Zero-fill any gaps */
- for (i = dctx->mdmax+1; i < mtype; ++i) {
+ for (i = dctx->mdmax + 1; i < mtype; ++i) {
mdevp[i] = NULL;
mdord[i] = 0;
}
return dane->dctx->mdevp[mtype];
}
-static int dane_tlsa_add(
- SSL_DANE *dane,
- uint8_t usage,
- uint8_t selector,
- uint8_t mtype,
- unsigned char *data,
- size_t dlen)
+static int dane_tlsa_add(SSL_DANE *dane,
+ uint8_t usage,
+ uint8_t selector,
+ uint8_t mtype, unsigned char *data, size_t dlen)
{
danetls_record *t;
const EVP_MD *md = NULL;
t->usage = usage;
t->selector = selector;
t->mtype = mtype;
- t->data = OPENSSL_malloc(ilen);
+ t->data = OPENSSL_malloc(dlen);
if (t->data == NULL) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
return -1;
}
- memcpy(t->data, data, ilen);
- t->dlen = ilen;
+ memcpy(t->data, data, dlen);
+ t->dlen = dlen;
/* Validate and cache full certificate or public key */
if (mtype == DANETLS_MATCHING_FULL) {
switch (selector) {
case DANETLS_SELECTOR_CERT:
- if (!d2i_X509(&cert, &p, dlen) || p < data ||
+ if (!d2i_X509(&cert, &p, ilen) || p < data ||
dlen != (size_t)(p - data)) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
break;
case DANETLS_SELECTOR_SPKI:
- if (!d2i_PUBKEY(&pkey, &p, dlen) || p < data ||
+ if (!d2i_PUBKEY(&pkey, &p, ilen) || p < data ||
dlen != (size_t)(p - data)) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY);
clear_ciphers(s);
s->first_packet = 0;
+ s->key_update = SSL_KEY_UPDATE_NONE;
+
/* Reset DANE verification result state */
s->dane.mdpth = -1;
s->dane.pdpth = -1;
&(ctx->cipher_list_by_id),
SSL_DEFAULT_CIPHER_LIST, ctx->cert);
if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) {
- SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION,
- SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
+ SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
return (0);
}
return (1);
RECORD_LAYER_init(&s->rlayer, s);
s->options = ctx->options;
+ s->dane.flags = ctx->dane.flags;
s->min_proto_version = ctx->min_proto_version;
s->max_proto_version = ctx->max_proto_version;
s->mode = ctx->mode;
s->max_cert_list = ctx->max_cert_list;
s->references = 1;
+ s->max_early_data = ctx->max_early_data;
/*
* Earlier library versions used to copy the pointer to the CERT, not
SSL_CTX_up_ref(ctx);
s->ctx = ctx;
- s->tlsext_debug_cb = 0;
- s->tlsext_debug_arg = NULL;
- s->tlsext_ticket_expected = 0;
- s->tlsext_status_type = ctx->tlsext_status_type;
- s->tlsext_status_expected = 0;
- s->tlsext_ocsp_ids = NULL;
- s->tlsext_ocsp_exts = NULL;
- s->tlsext_ocsp_resp = NULL;
- s->tlsext_ocsp_resplen = -1;
+ s->ext.debug_cb = 0;
+ s->ext.debug_arg = NULL;
+ s->ext.ticket_expected = 0;
+ s->ext.status_type = ctx->ext.status_type;
+ s->ext.status_expected = 0;
+ s->ext.ocsp.ids = NULL;
+ s->ext.ocsp.exts = NULL;
+ s->ext.ocsp.resp = NULL;
+ s->ext.ocsp.resp_len = 0;
SSL_CTX_up_ref(ctx);
- s->initial_ctx = ctx;
-# ifndef OPENSSL_NO_EC
- if (ctx->tlsext_ecpointformatlist) {
- s->tlsext_ecpointformatlist =
- OPENSSL_memdup(ctx->tlsext_ecpointformatlist,
- ctx->tlsext_ecpointformatlist_length);
- if (!s->tlsext_ecpointformatlist)
+ s->session_ctx = ctx;
+#ifndef OPENSSL_NO_EC
+ if (ctx->ext.ecpointformats) {
+ s->ext.ecpointformats =
+ OPENSSL_memdup(ctx->ext.ecpointformats,
+ ctx->ext.ecpointformats_len);
+ if (!s->ext.ecpointformats)
goto err;
- s->tlsext_ecpointformatlist_length =
- ctx->tlsext_ecpointformatlist_length;
- }
- if (ctx->tlsext_ellipticcurvelist) {
- s->tlsext_ellipticcurvelist =
- OPENSSL_memdup(ctx->tlsext_ellipticcurvelist,
- ctx->tlsext_ellipticcurvelist_length);
- if (!s->tlsext_ellipticcurvelist)
+ s->ext.ecpointformats_len =
+ ctx->ext.ecpointformats_len;
+ }
+ if (ctx->ext.supportedgroups) {
+ s->ext.supportedgroups =
+ OPENSSL_memdup(ctx->ext.supportedgroups,
+ ctx->ext.supportedgroups_len);
+ if (!s->ext.supportedgroups)
goto err;
- s->tlsext_ellipticcurvelist_length =
- ctx->tlsext_ellipticcurvelist_length;
+ s->ext.supportedgroups_len = ctx->ext.supportedgroups_len;
}
-# endif
-# ifndef OPENSSL_NO_NEXTPROTONEG
- s->next_proto_negotiated = NULL;
-# endif
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ s->ext.npn = NULL;
+#endif
- if (s->ctx->alpn_client_proto_list) {
- s->alpn_client_proto_list =
- OPENSSL_malloc(s->ctx->alpn_client_proto_list_len);
- if (s->alpn_client_proto_list == NULL)
+ if (s->ctx->ext.alpn) {
+ s->ext.alpn = OPENSSL_malloc(s->ctx->ext.alpn_len);
+ if (s->ext.alpn == NULL)
goto err;
- memcpy(s->alpn_client_proto_list, s->ctx->alpn_client_proto_list,
- s->ctx->alpn_client_proto_list_len);
- s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len;
+ memcpy(s->ext.alpn, s->ctx->ext.alpn, s->ctx->ext.alpn_len);
+ s->ext.alpn_len = s->ctx->ext.alpn_len;
}
s->verified_chain = NULL;
s->method = ctx->method;
+ s->key_update = SSL_KEY_UPDATE_NONE;
+
if (!s->method->ssl_new(s))
goto err;
#ifndef OPENSSL_NO_CT
if (!SSL_set_ct_validation_callback(s, ctx->ct_validation_callback,
- ctx->ct_validation_callback_arg))
+ ctx->ct_validation_callback_arg))
goto err;
#endif
return NULL;
}
+int SSL_is_dtls(const SSL *s)
+{
+ return SSL_IS_DTLS(s) ? 1 : 0;
+}
+
int SSL_up_ref(SSL *s)
{
int i;
- if (CRYPTO_atomic_add(&s->references, 1, &i, s->lock) <= 0)
+ if (CRYPTO_UP_REF(&s->references, &i, s->lock) <= 0)
return 0;
REF_PRINT_COUNT("SSL", s);
r.session_id_length = id_len;
memcpy(r.session_id, id, id_len);
- CRYPTO_THREAD_read_lock(ssl->ctx->lock);
- p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r);
- CRYPTO_THREAD_unlock(ssl->ctx->lock);
+ CRYPTO_THREAD_read_lock(ssl->session_ctx->lock);
+ p = lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &r);
+ CRYPTO_THREAD_unlock(ssl->session_ctx->lock);
return (p != NULL);
}
return dane_ctx_enable(&ctx->dane);
}
+unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags)
+{
+ unsigned long orig = ctx->dane.flags;
+
+ ctx->dane.flags |= flags;
+ return orig;
+}
+
+unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags)
+{
+ unsigned long orig = ctx->dane.flags;
+
+ ctx->dane.flags &= ~flags;
+ return orig;
+}
+
int SSL_dane_enable(SSL *s, const char *basedomain)
{
SSL_DANE *dane = &s->dane;
* accepts them and disables host name checks. To avoid side-effects with
* invalid input, set the SNI name first.
*/
- if (s->tlsext_hostname == NULL) {
+ if (s->ext.hostname == NULL) {
if (!SSL_set_tlsext_host_name(s, basedomain)) {
SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
return -1;
return 1;
}
+unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags)
+{
+ unsigned long orig = ssl->dane.flags;
+
+ ssl->dane.flags |= flags;
+ return orig;
+}
+
+unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags)
+{
+ unsigned long orig = ssl->dane.flags;
+
+ ssl->dane.flags &= ~flags;
+ return orig;
+}
+
int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki)
{
SSL_DANE *dane = &s->dane;
return dane_tlsa_add(&s->dane, usage, selector, mtype, data, dlen);
}
-int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype, uint8_t ord)
+int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype,
+ uint8_t ord)
{
return dane_mtype_set(&ctx->dane, md, mtype, ord);
}
if (s == NULL)
return;
- CRYPTO_atomic_add(&s->references, -1, &i, s->lock);
+ CRYPTO_DOWN_REF(&s->references, &i, s->lock);
REF_PRINT_COUNT("SSL", s);
if (i > 0)
return;
dane_final(&s->dane);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
- if (s->bbio != NULL) {
- /* If the buffering BIO is in place, pop it off */
- if (s->bbio == s->wbio) {
- s->wbio = BIO_pop(s->wbio);
- }
- BIO_free(s->bbio);
- s->bbio = NULL;
- }
+ ssl_free_wbio_buffer(s);
+
+ BIO_free_all(s->wbio);
BIO_free_all(s->rbio);
- if (s->wbio != s->rbio)
- BIO_free_all(s->wbio);
BUF_MEM_free(s->init_buf);
ssl_cert_free(s->cert);
/* Free up if allocated */
- OPENSSL_free(s->tlsext_hostname);
- SSL_CTX_free(s->initial_ctx);
+ OPENSSL_free(s->ext.hostname);
+ SSL_CTX_free(s->session_ctx);
#ifndef OPENSSL_NO_EC
- OPENSSL_free(s->tlsext_ecpointformatlist);
- OPENSSL_free(s->tlsext_ellipticcurvelist);
-#endif /* OPENSSL_NO_EC */
- sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, X509_EXTENSION_free);
+ OPENSSL_free(s->ext.ecpointformats);
+ OPENSSL_free(s->ext.supportedgroups);
+#endif /* OPENSSL_NO_EC */
+ sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, X509_EXTENSION_free);
#ifndef OPENSSL_NO_OCSP
- sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+ sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
#endif
#ifndef OPENSSL_NO_CT
SCT_LIST_free(s->scts);
- OPENSSL_free(s->tlsext_scts);
+ OPENSSL_free(s->ext.scts);
#endif
- OPENSSL_free(s->tlsext_ocsp_resp);
- OPENSSL_free(s->alpn_client_proto_list);
+ OPENSSL_free(s->ext.ocsp.resp);
+ OPENSSL_free(s->ext.alpn);
+ OPENSSL_free(s->clienthello);
sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free);
ASYNC_WAIT_CTX_free(s->waitctx);
#if !defined(OPENSSL_NO_NEXTPROTONEG)
- OPENSSL_free(s->next_proto_negotiated);
+ OPENSSL_free(s->ext.npn);
#endif
#ifndef OPENSSL_NO_SRTP
OPENSSL_free(s);
}
-void SSL_set_rbio(SSL *s, BIO *rbio)
+void SSL_set0_rbio(SSL *s, BIO *rbio)
{
- if (s->rbio != rbio)
- BIO_free_all(s->rbio);
+ BIO_free_all(s->rbio);
s->rbio = rbio;
}
-void SSL_set_wbio(SSL *s, BIO *wbio)
+void SSL_set0_wbio(SSL *s, BIO *wbio)
{
/*
* If the output buffering BIO is still in place, remove it
*/
- if (s->bbio != NULL) {
- if (s->wbio == s->bbio) {
- s->wbio = BIO_next(s->wbio);
- BIO_set_next(s->bbio, NULL);
- }
- }
- if (s->wbio != wbio && s->rbio != s->wbio)
- BIO_free_all(s->wbio);
+ if (s->bbio != NULL)
+ s->wbio = BIO_pop(s->wbio);
+
+ BIO_free_all(s->wbio);
s->wbio = wbio;
+
+ /* Re-attach |bbio| to the new |wbio|. */
+ if (s->bbio != NULL)
+ s->wbio = BIO_push(s->bbio, s->wbio);
}
void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio)
{
- SSL_set_wbio(s, wbio);
- SSL_set_rbio(s, rbio);
+ /*
+ * For historical reasons, this function has many different cases in
+ * ownership handling.
+ */
+
+ /* If nothing has changed, do nothing */
+ if (rbio == SSL_get_rbio(s) && wbio == SSL_get_wbio(s))
+ return;
+
+ /*
+ * If the two arguments are equal then one fewer reference is granted by the
+ * caller than we want to take
+ */
+ if (rbio != NULL && rbio == wbio)
+ BIO_up_ref(rbio);
+
+ /*
+ * If only the wbio is changed only adopt one reference.
+ */
+ if (rbio == SSL_get_rbio(s)) {
+ SSL_set0_wbio(s, wbio);
+ return;
+ }
+ /*
+ * There is an asymmetry here for historical reasons. If only the rbio is
+ * changed AND the rbio and wbio were originally different, then we only
+ * adopt one reference.
+ */
+ if (wbio == SSL_get_wbio(s) && SSL_get_rbio(s) != SSL_get_wbio(s)) {
+ SSL_set0_rbio(s, rbio);
+ return;
+ }
+
+ /* Otherwise, adopt both references. */
+ SSL_set0_rbio(s, rbio);
+ SSL_set0_wbio(s, wbio);
}
BIO *SSL_get_rbio(const SSL *s)
{
- return (s->rbio);
+ return s->rbio;
}
BIO *SSL_get_wbio(const SSL *s)
{
- return (s->wbio);
+ if (s->bbio != NULL) {
+ /*
+ * If |bbio| is active, the true caller-configured BIO is its
+ * |next_bio|.
+ */
+ return BIO_next(s->bbio);
+ }
+ return s->wbio;
}
int SSL_get_fd(const SSL *s)
{
- return (SSL_get_rfd(s));
+ return SSL_get_rfd(s);
}
int SSL_get_rfd(const SSL *s)
int SSL_set_wfd(SSL *s, int fd)
{
- int ret = 0;
- BIO *bio = NULL;
+ BIO *rbio = SSL_get_rbio(s);
- if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_SOCKET)
- || ((int)BIO_get_fd(s->rbio, NULL) != fd)) {
- bio = BIO_new(BIO_s_socket());
+ if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET
+ || (int)BIO_get_fd(rbio, NULL) != fd) {
+ BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
SSLerr(SSL_F_SSL_SET_WFD, ERR_R_BUF_LIB);
- goto err;
+ return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
- SSL_set_bio(s, SSL_get_rbio(s), bio);
- } else
- SSL_set_bio(s, SSL_get_rbio(s), SSL_get_rbio(s));
- ret = 1;
- err:
- return (ret);
+ SSL_set0_wbio(s, bio);
+ } else {
+ BIO_up_ref(rbio);
+ SSL_set0_wbio(s, rbio);
+ }
+ return 1;
}
int SSL_set_rfd(SSL *s, int fd)
{
- int ret = 0;
- BIO *bio = NULL;
+ BIO *wbio = SSL_get_wbio(s);
- if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_SOCKET)
- || ((int)BIO_get_fd(s->wbio, NULL) != fd)) {
- bio = BIO_new(BIO_s_socket());
+ if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET
+ || ((int)BIO_get_fd(wbio, NULL) != fd)) {
+ BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
SSLerr(SSL_F_SSL_SET_RFD, ERR_R_BUF_LIB);
- goto err;
+ return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
- SSL_set_bio(s, bio, SSL_get_wbio(s));
- } else
- SSL_set_bio(s, SSL_get_wbio(s), SSL_get_wbio(s));
- ret = 1;
- err:
- return (ret);
+ SSL_set0_rbio(s, bio);
+ } else {
+ BIO_up_ref(wbio);
+ SSL_set0_rbio(s, wbio);
+ }
+
+ return 1;
}
#endif
int SSL_pending(const SSL *s)
{
+ size_t pending = s->method->ssl_pending(s);
+
/*
* SSL_pending cannot work properly if read-ahead is enabled
* (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is
* impossible to fix since SSL_pending cannot report errors that may be
* observed while scanning the new data. (Note that SSL_pending() is
* often used as a boolean value, so we'd better not return -1.)
+ *
+ * SSL_pending also cannot work properly if the value >INT_MAX. In that case
+ * we just return INT_MAX.
*/
- return (s->method->ssl_pending(s));
+ return pending < INT_MAX ? (int)pending : INT_MAX;
}
int SSL_has_pending(const SSL *s)
return 0;
}
- CRYPTO_atomic_add(&f->cert->references, 1, &i, f->cert->lock);
+ CRYPTO_UP_REF(&f->cert->references, &i, f->cert->lock);
ssl_cert_free(t->cert);
t->cert = f->cert;
- if (!SSL_set_session_id_context(t, f->sid_ctx, f->sid_ctx_length)) {
+ if (!SSL_set_session_id_context(t, f->sid_ctx, (int)f->sid_ctx_length)) {
return 0;
}
/* Fix this so it checks all the valid key/cert options */
int SSL_CTX_check_private_key(const SSL_CTX *ctx)
{
- if ((ctx == NULL) ||
- (ctx->cert->key->x509 == NULL)) {
- SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,
- SSL_R_NO_CERTIFICATE_ASSIGNED);
+ if ((ctx == NULL) || (ctx->cert->key->x509 == NULL)) {
+ SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
return (0);
}
if (ctx->cert->key->privatekey == NULL) {
- SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,
- SSL_R_NO_PRIVATE_KEY_ASSIGNED);
+ SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return (0);
}
return (X509_check_private_key
int SSL_waiting_for_async(SSL *s)
{
- if(s->job)
+ if (s->job)
return 1;
return 0;
}
static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
- int (*func)(void *)) {
+ int (*func) (void *))
+{
int ret;
if (s->waitctx == NULL) {
s->waitctx = ASYNC_WAIT_CTX_new();
if (s->waitctx == NULL)
return -1;
}
- switch(ASYNC_start_job(&s->job, s->waitctx, &ret, func, args,
- sizeof(struct ssl_async_args))) {
+ switch (ASYNC_start_job(&s->job, s->waitctx, &ret, func, args,
+ sizeof(struct ssl_async_args))) {
case ASYNC_ERR:
s->rwstate = SSL_NOTHING;
SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC);
struct ssl_async_args *args;
SSL *s;
void *buf;
- int num;
+ size_t num;
args = (struct ssl_async_args *)vargs;
s = args->s;
num = args->num;
switch (args->type) {
case READFUNC:
- return args->f.func_read(s, buf, num);
+ return args->f.func_read(s, buf, num, &s->asyncrw);
case WRITEFUNC:
- return args->f.func_write(s, buf, num);
+ return args->f.func_write(s, buf, num, &s->asyncrw);
case OTHERFUNC:
return args->f.func_other(s);
}
return -1;
}
-int SSL_read(SSL *s, void *buf, int num)
+int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
+ SSLerr(SSL_F_SSL_READ_INTERNAL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- return (0);
+ return 0;
}
- if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
+ int ret;
args.s = s;
args.buf = buf;
args.type = READFUNC;
args.f.func_read = s->method->ssl_read;
- return ssl_start_async_job(s, &args, ssl_io_intern);
+ ret = ssl_start_async_job(s, &args, ssl_io_intern);
+ *readbytes = s->asyncrw;
+ return ret;
} else {
- return s->method->ssl_read(s, buf, num);
+ return s->method->ssl_read(s, buf, num, readbytes);
}
}
-int SSL_peek(SSL *s, void *buf, int num)
+int SSL_read(SSL *s, void *buf, int num)
+{
+ int ret;
+ size_t readbytes;
+
+ if (num < 0) {
+ SSLerr(SSL_F_SSL_READ, SSL_R_BAD_LENGTH);
+ return -1;
+ }
+
+ ret = ssl_read_internal(s, buf, (size_t)num, &readbytes);
+
+ /*
+ * The cast is safe here because ret should be <= INT_MAX because num is
+ * <= INT_MAX
+ */
+ if (ret > 0)
+ ret = (int)readbytes;
+
+ return ret;
+}
+
+int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
+{
+ int ret = ssl_read_internal(s, buf, num, readbytes);
+
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_PEEK, SSL_R_UNINITIALIZED);
+ SSLerr(SSL_F_SSL_PEEK_INTERNAL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
- return (0);
+ return 0;
}
- if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
+ int ret;
args.s = s;
args.buf = buf;
args.type = READFUNC;
args.f.func_read = s->method->ssl_peek;
- return ssl_start_async_job(s, &args, ssl_io_intern);
+ ret = ssl_start_async_job(s, &args, ssl_io_intern);
+ *readbytes = s->asyncrw;
+ return ret;
} else {
- return s->method->ssl_peek(s, buf, num);
+ return s->method->ssl_peek(s, buf, num, readbytes);
}
}
-int SSL_write(SSL *s, const void *buf, int num)
+int SSL_peek(SSL *s, void *buf, int num)
+{
+ int ret;
+ size_t readbytes;
+
+ if (num < 0) {
+ SSLerr(SSL_F_SSL_PEEK, SSL_R_BAD_LENGTH);
+ return -1;
+ }
+
+ ret = ssl_peek_internal(s, buf, (size_t)num, &readbytes);
+
+ /*
+ * The cast is safe here because ret should be <= INT_MAX because num is
+ * <= INT_MAX
+ */
+ if (ret > 0)
+ ret = (int)readbytes;
+
+ return ret;
+}
+
+
+int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
+{
+ int ret = ssl_peek_internal(s, buf, num, readbytes);
+
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED);
+ SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_SENT_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
- SSLerr(SSL_F_SSL_WRITE, SSL_R_PROTOCOL_IS_SHUTDOWN);
- return (-1);
+ SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+ return -1;
}
- if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
+ || s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY)
+ return 0;
+
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ int ret;
struct ssl_async_args args;
args.s = s;
args.type = WRITEFUNC;
args.f.func_write = s->method->ssl_write;
- return ssl_start_async_job(s, &args, ssl_io_intern);
+ ret = ssl_start_async_job(s, &args, ssl_io_intern);
+ *written = s->asyncrw;
+ return ret;
} else {
- return s->method->ssl_write(s, buf, num);
+ return s->method->ssl_write(s, buf, num, written);
}
}
+int SSL_write(SSL *s, const void *buf, int num)
+{
+ int ret;
+ size_t written;
+
+ if (num < 0) {
+ SSLerr(SSL_F_SSL_WRITE, SSL_R_BAD_LENGTH);
+ return -1;
+ }
+
+ ret = ssl_write_internal(s, buf, (size_t)num, &written);
+
+ /*
+ * The cast is safe here because ret should be <= INT_MAX because num is
+ * <= INT_MAX
+ */
+ if (ret > 0)
+ ret = (int)written;
+
+ return ret;
+}
+
+int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written)
+{
+ int ret = ssl_write_internal(s, buf, num, written);
+
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+int SSL_write_early(SSL *s, const void *buf, size_t num, size_t *written)
+{
+ int ret;
+
+ if (s->server) {
+ SSLerr(SSL_F_SSL_WRITE_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ /*
+ * TODO(TLS1.3): Somehow we need to check that we're not sending too much
+ * data
+ */
+
+ switch (s->early_data_state) {
+ case SSL_EARLY_DATA_NONE:
+ if (!SSL_in_before(s)) {
+ SSLerr(SSL_F_SSL_WRITE_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ /* fall through */
+
+ case SSL_EARLY_DATA_CONNECT_RETRY:
+ s->early_data_state = SSL_EARLY_DATA_CONNECTING;
+ ret = SSL_connect(s);
+ if (ret <= 0) {
+ /* NBIO or error */
+ s->early_data_state = SSL_EARLY_DATA_CONNECT_RETRY;
+ return 0;
+ }
+ /* fall through */
+
+ case SSL_EARLY_DATA_WRITE_RETRY:
+ s->early_data_state = SSL_EARLY_DATA_WRITING;
+ ret = SSL_write_ex(s, buf, num, written);
+ s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
+ return ret;
+
+ default:
+ SSLerr(SSL_F_SSL_WRITE_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+}
+
+int SSL_write_early_finish(SSL *s)
+{
+ int ret;
+
+ if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY) {
+ SSLerr(SSL_F_SSL_WRITE_EARLY_FINISH, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ s->early_data_state = SSL_EARLY_DATA_WRITING;
+ ret = ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_END_OF_EARLY_DATA);
+ if (ret <= 0) {
+ s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
+ return 0;
+ }
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ /*
+ * We set the enc_write_ctx back to NULL because we may end up writing
+ * in cleartext again if we get a HelloRetryRequest from the server.
+ */
+ EVP_CIPHER_CTX_free(s->enc_write_ctx);
+ s->enc_write_ctx = NULL;
+ ossl_statem_set_in_init(s, 1);
+ return 1;
+}
+
int SSL_shutdown(SSL *s)
{
/*
}
if (!SSL_in_init(s)) {
- if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
args.s = s;
}
}
+int SSL_key_update(SSL *s, int updatetype)
+{
+ /*
+ * TODO(TLS1.3): How will applications know whether TLSv1.3 has been
+ * negotiated, and that it is appropriate to call SSL_key_update() instead
+ * of SSL_renegotiate().
+ */
+ if (!SSL_IS_TLS13(s)) {
+ SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_WRONG_SSL_VERSION);
+ return 0;
+ }
+
+ if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
+ && updatetype != SSL_KEY_UPDATE_REQUESTED) {
+ SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_INVALID_KEY_UPDATE_TYPE);
+ return 0;
+ }
+
+ if (!SSL_is_init_finished(s)) {
+ SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_STILL_IN_INIT);
+ return 0;
+ }
+
+ ossl_statem_set_in_init(s, 1);
+ s->key_update = updatetype;
+ return 1;
+}
+
+int SSL_get_key_update_type(SSL *s)
+{
+ return s->key_update;
+}
+
int SSL_renegotiate(SSL *s)
{
+ if (SSL_IS_TLS13(s)) {
+ SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_WRONG_SSL_VERSION);
+ return 0;
+ }
+
if (s->renegotiate == 0)
s->renegotiate = 1;
int SSL_renegotiate_abbreviated(SSL *s)
{
+ if (SSL_IS_TLS13(s))
+ return 0;
+
if (s->renegotiate == 0)
s->renegotiate = 1;
case SSL_CTRL_CLEAR_MODE:
return (s->mode &= ~larg);
case SSL_CTRL_GET_MAX_CERT_LIST:
- return (s->max_cert_list);
+ return (long)(s->max_cert_list);
case SSL_CTRL_SET_MAX_CERT_LIST:
- l = s->max_cert_list;
- s->max_cert_list = larg;
- return (l);
+ if (larg < 0)
+ return 0;
+ l = (long)s->max_cert_list;
+ s->max_cert_list = (size_t)larg;
+ return l;
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
s->split_send_fragment = s->max_send_fragment;
return 1;
case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
- if ((unsigned int)larg > s->max_send_fragment || larg == 0)
+ if ((size_t)larg > s->max_send_fragment || larg == 0)
return 0;
s->split_send_fragment = larg;
return 1;
}
case SSL_CTRL_GET_EXTMS_SUPPORT:
if (!s->session || SSL_in_init(s) || ossl_statem_get_in_handshake(s))
- return -1;
+ return -1;
if (s->session->flags & SSL_SESS_FLAG_EXTMS)
return 1;
else
if (ctx == NULL) {
switch (cmd) {
#ifndef OPENSSL_NO_EC
- case SSL_CTRL_SET_CURVES_LIST:
- return tls1_set_curves_list(NULL, NULL, parg);
+ case SSL_CTRL_SET_GROUPS_LIST:
+ return tls1_set_groups_list(NULL, NULL, parg);
#endif
case SSL_CTRL_SET_SIGALGS_LIST:
case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
return 1;
case SSL_CTRL_GET_MAX_CERT_LIST:
- return (ctx->max_cert_list);
+ return (long)(ctx->max_cert_list);
case SSL_CTRL_SET_MAX_CERT_LIST:
- l = ctx->max_cert_list;
- ctx->max_cert_list = larg;
- return (l);
+ if (larg < 0)
+ return 0;
+ l = (long)ctx->max_cert_list;
+ ctx->max_cert_list = (size_t)larg;
+ return l;
case SSL_CTRL_SET_SESS_CACHE_SIZE:
- l = ctx->session_cache_size;
- ctx->session_cache_size = larg;
- return (l);
+ if (larg < 0)
+ return 0;
+ l = (long)ctx->session_cache_size;
+ ctx->session_cache_size = (size_t)larg;
+ return l;
case SSL_CTRL_GET_SESS_CACHE_SIZE:
- return (ctx->session_cache_size);
+ return (long)(ctx->session_cache_size);
case SSL_CTRL_SET_SESS_CACHE_MODE:
l = ctx->session_cache_mode;
ctx->session_cache_mode = larg;
ctx->split_send_fragment = ctx->max_send_fragment;
return 1;
case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
- if ((unsigned int)larg > ctx->max_send_fragment || larg == 0)
+ if ((size_t)larg > ctx->max_send_fragment || larg == 0)
return 0;
ctx->split_send_fragment = larg;
return 1;
if (type != TLSEXT_NAMETYPE_host_name)
return NULL;
- return s->session && !s->tlsext_hostname ?
- s->session->tlsext_hostname : s->tlsext_hostname;
+ return s->session && !s->ext.hostname ?
+ s->session->ext.hostname : s->ext.hostname;
}
int SSL_get_servername_type(const SSL *s)
{
if (s->session
- && (!s->tlsext_hostname ? s->session->
- tlsext_hostname : s->tlsext_hostname))
+ && (!s->ext.hostname ? s->session->
+ ext.hostname : s->ext.hostname))
return TLSEXT_NAMETYPE_host_name;
return -1;
}
* is indicated to the callback. In this case, the client application has to
* abort the connection or have a default application level protocol. 2) If
* the server supports NPN, but advertises an empty list then the client
- * selects the first protcol in its list, but indicates via the API that this
+ * selects the first protocol in its list, but indicates via the API that this
* fallback case was enacted. 3) Otherwise, the client finds the first
* protocol in the server's list that it supports and selects this protocol.
* This is because it's assumed that the server has better information about
int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
const unsigned char *server,
unsigned int server_len,
- const unsigned char *client,
- unsigned int client_len)
+ const unsigned char *client, unsigned int client_len)
{
unsigned int i, j;
const unsigned char *result;
void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len)
{
- *data = s->next_proto_negotiated;
+ *data = s->ext.npn;
if (!*data) {
*len = 0;
} else {
- *len = s->next_proto_negotiated_len;
+ *len = (unsigned int)s->ext.npn_len;
}
}
/*
- * SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when
+ * SSL_CTX_set_npn_advertised_cb sets a callback that is called when
* a TLS server needs a list of supported protocols for Next Protocol
* Negotiation. The returned list must be in wire format. The list is
* returned by setting |out| to point to it and |outlen| to its length. This
* wishes to advertise. Otherwise, no such extension will be included in the
* ServerHello.
*/
-void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx,
- int (*cb) (SSL *ssl,
- const unsigned char
- **out,
- unsigned int *outlen,
- void *arg), void *arg)
+void SSL_CTX_set_npn_advertised_cb(SSL_CTX *ctx,
+ SSL_CTX_npn_advertised_cb_func cb,
+ void *arg)
{
- ctx->next_protos_advertised_cb = cb;
- ctx->next_protos_advertised_cb_arg = arg;
+ ctx->ext.npn_advertised_cb = cb;
+ ctx->ext.npn_advertised_cb_arg = arg;
}
/*
* select a protocol. It is fatal to the connection if this callback returns
* a value other than SSL_TLSEXT_ERR_OK.
*/
-void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx,
- int (*cb) (SSL *s, unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg), void *arg)
+void SSL_CTX_set_npn_select_cb(SSL_CTX *ctx,
+ SSL_CTX_npn_select_cb_func cb,
+ void *arg)
{
- ctx->next_proto_select_cb = cb;
- ctx->next_proto_select_cb_arg = arg;
+ ctx->ext.npn_select_cb = cb;
+ ctx->ext.npn_select_cb_arg = arg;
}
#endif
int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
unsigned int protos_len)
{
- OPENSSL_free(ctx->alpn_client_proto_list);
- ctx->alpn_client_proto_list = OPENSSL_memdup(protos, protos_len);
- if (ctx->alpn_client_proto_list == NULL) {
+ OPENSSL_free(ctx->ext.alpn);
+ ctx->ext.alpn = OPENSSL_memdup(protos, protos_len);
+ if (ctx->ext.alpn == NULL) {
SSLerr(SSL_F_SSL_CTX_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
return 1;
}
- ctx->alpn_client_proto_list_len = protos_len;
+ ctx->ext.alpn_len = protos_len;
return 0;
}
int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
unsigned int protos_len)
{
- OPENSSL_free(ssl->alpn_client_proto_list);
- ssl->alpn_client_proto_list = OPENSSL_memdup(protos, protos_len);
- if (ssl->alpn_client_proto_list == NULL) {
+ OPENSSL_free(ssl->ext.alpn);
+ ssl->ext.alpn = OPENSSL_memdup(protos, protos_len);
+ if (ssl->ext.alpn == NULL) {
SSLerr(SSL_F_SSL_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
return 1;
}
- ssl->alpn_client_proto_list_len = protos_len;
+ ssl->ext.alpn_len = protos_len;
return 0;
}
* from the client's list of offered protocols.
*/
void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
- int (*cb) (SSL *ssl,
- const unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg), void *arg)
+ SSL_CTX_alpn_select_cb_func cb,
+ void *arg)
{
- ctx->alpn_select_cb = cb;
- ctx->alpn_select_cb_arg = arg;
+ ctx->ext.alpn_select_cb = cb;
+ ctx->ext.alpn_select_cb_arg = arg;
}
/*
if (*data == NULL)
*len = 0;
else
- *len = ssl->s3->alpn_selected_len;
+ *len = (unsigned int)ssl->s3->alpn_selected_len;
}
-
int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen,
const unsigned char *p, size_t plen,
int use_context)
{
- if (s->version < TLS1_VERSION)
+ if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER)
return -1;
return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
static unsigned long ssl_session_hash(const SSL_SESSION *a)
{
+ const unsigned char *session_id = a->session_id;
unsigned long l;
+ unsigned char tmp_storage[4];
+
+ if (a->session_id_length < sizeof(tmp_storage)) {
+ memset(tmp_storage, 0, sizeof(tmp_storage));
+ memcpy(tmp_storage, a->session_id, a->session_id_length);
+ session_id = tmp_storage;
+ }
l = (unsigned long)
- ((unsigned int)a->session_id[0]) |
- ((unsigned int)a->session_id[1] << 8L) |
- ((unsigned long)a->session_id[2] << 16L) |
- ((unsigned long)a->session_id[3] << 24L);
+ ((unsigned long)session_id[0]) |
+ ((unsigned long)session_id[1] << 8L) |
+ ((unsigned long)session_id[2] << 16L) |
+ ((unsigned long)session_id[3] << 24L);
return (l);
}
if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL))
return NULL;
- if (FIPS_mode() && (meth->version < TLS1_VERSION)) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE);
- return NULL;
- }
-
if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
goto err;
goto err;
#endif
if (!ssl_create_cipher_list(ret->method,
- &ret->cipher_list, &ret->cipher_list_by_id,
- SSL_DEFAULT_CIPHER_LIST, ret->cert)
- || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
+ &ret->cipher_list, &ret->cipher_list_by_id,
+ SSL_DEFAULT_CIPHER_LIST, ret->cert)
+ || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
goto err2;
}
ret->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
/* Setup RFC5077 ticket keys */
- if ((RAND_bytes(ret->tlsext_tick_key_name, sizeof(ret->tlsext_tick_key_name)) <= 0)
- || (RAND_bytes(ret->tlsext_tick_hmac_key, sizeof(ret->tlsext_tick_hmac_key)) <= 0)
- || (RAND_bytes(ret->tlsext_tick_aes_key, sizeof(ret->tlsext_tick_aes_key)) <= 0))
+ if ((RAND_bytes(ret->ext.tick_key_name,
+ sizeof(ret->ext.tick_key_name)) <= 0)
+ || (RAND_bytes(ret->ext.tick_hmac_key,
+ sizeof(ret->ext.tick_hmac_key)) <= 0)
+ || (RAND_bytes(ret->ext.tick_aes_key,
+ sizeof(ret->ext.tick_aes_key)) <= 0))
ret->options |= SSL_OP_NO_TICKET;
#ifndef OPENSSL_NO_SRP
*/
ret->options |= SSL_OP_NO_COMPRESSION;
- ret->tlsext_status_type = -1;
+ ret->ext.status_type = TLSEXT_STATUSTYPE_nothing;
return ret;
err:
{
int i;
- if (CRYPTO_atomic_add(&ctx->references, 1, &i, ctx->lock) <= 0)
+ if (CRYPTO_UP_REF(&ctx->references, &i, ctx->lock) <= 0)
return 0;
REF_PRINT_COUNT("SSL_CTX", ctx);
if (a == NULL)
return;
- CRYPTO_atomic_add(&a->references, -1, &i, a->lock);
+ CRYPTO_DOWN_REF(&a->references, &i, a->lock);
REF_PRINT_COUNT("SSL_CTX", a);
if (i > 0)
return;
#endif
#ifndef OPENSSL_NO_EC
- OPENSSL_free(a->tlsext_ecpointformatlist);
- OPENSSL_free(a->tlsext_ellipticcurvelist);
+ OPENSSL_free(a->ext.ecpointformats);
+ OPENSSL_free(a->ext.supportedgroups);
#endif
- OPENSSL_free(a->alpn_client_proto_list);
+ OPENSSL_free(a->ext.alpn);
CRYPTO_THREAD_lock_free(a->lock);
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
-void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
- void *arg)
+void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), void *arg)
{
ssl_cert_set_cert_cb(c->cert, cb, arg);
}
void ssl_set_masks(SSL *s)
{
-#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_GOST)
- CERT_PKEY *cpk;
-#endif
CERT *c = s->cert;
uint32_t *pvalid = s->s3->tmp.valid_flags;
int rsa_enc, rsa_sign, dh_tmp, dsa_sign;
unsigned long mask_k, mask_a;
#ifndef OPENSSL_NO_EC
int have_ecc_cert, ecdsa_ok;
- X509 *x = NULL;
#endif
if (c == NULL)
return;
dh_tmp = 0;
#endif
- rsa_enc = pvalid[SSL_PKEY_RSA_ENC] & CERT_PKEY_VALID;
- rsa_sign = pvalid[SSL_PKEY_RSA_SIGN] & CERT_PKEY_SIGN;
- dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_SIGN;
+ rsa_enc = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID;
+ rsa_sign = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID;
+ dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_VALID;
#ifndef OPENSSL_NO_EC
have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID;
#endif
#endif
#ifndef OPENSSL_NO_GOST
- cpk = &(c->pkeys[SSL_PKEY_GOST12_512]);
- if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST12;
}
- cpk = &(c->pkeys[SSL_PKEY_GOST12_256]);
- if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST12;
}
- cpk = &(c->pkeys[SSL_PKEY_GOST01]);
- if (cpk->x509 != NULL && cpk->privatekey != NULL) {
+ if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST01;
}
#ifndef OPENSSL_NO_EC
if (have_ecc_cert) {
uint32_t ex_kusage;
- cpk = &c->pkeys[SSL_PKEY_ECC];
- x = cpk->x509;
- ex_kusage = X509_get_key_usage(x);
+ ex_kusage = X509_get_key_usage(c->pkeys[SSL_PKEY_ECC].x509);
ecdsa_ok = ex_kusage & X509v3_KU_DIGITAL_SIGNATURE;
if (!(pvalid[SSL_PKEY_ECC] & CERT_PKEY_SIGN))
ecdsa_ok = 0;
#endif
-static int ssl_get_server_cert_index(const SSL *s)
-{
- int idx;
- idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
- if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
- idx = SSL_PKEY_RSA_SIGN;
- if (idx == SSL_PKEY_GOST_EC) {
- if (s->cert->pkeys[SSL_PKEY_GOST12_512].x509)
- idx = SSL_PKEY_GOST12_512;
- else if (s->cert->pkeys[SSL_PKEY_GOST12_256].x509)
- idx = SSL_PKEY_GOST12_256;
- else if (s->cert->pkeys[SSL_PKEY_GOST01].x509)
- idx = SSL_PKEY_GOST01;
- else
- idx = -1;
- }
- if (idx == -1)
- SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX, ERR_R_INTERNAL_ERROR);
- return idx;
-}
-
-CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
-{
- CERT *c;
- int i;
-
- c = s->cert;
- if (!s->s3 || !s->s3->tmp.new_cipher)
- return NULL;
- ssl_set_masks(s);
-
- i = ssl_get_server_cert_index(s);
-
- /* This may or may not be an error. */
- if (i < 0)
- return NULL;
-
- /* May be NULL. */
- return &c->pkeys[i];
-}
-
-EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher,
- const EVP_MD **pmd)
-{
- unsigned long alg_a;
- CERT *c;
- int idx = -1;
-
- alg_a = cipher->algorithm_auth;
- c = s->cert;
-
- if ((alg_a & SSL_aDSS) &&
- (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
- idx = SSL_PKEY_DSA_SIGN;
- else if (alg_a & SSL_aRSA) {
- if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
- idx = SSL_PKEY_RSA_SIGN;
- else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
- idx = SSL_PKEY_RSA_ENC;
- } else if ((alg_a & SSL_aECDSA) &&
- (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
- idx = SSL_PKEY_ECC;
- if (idx == -1) {
- SSLerr(SSL_F_SSL_GET_SIGN_PKEY, ERR_R_INTERNAL_ERROR);
- return (NULL);
- }
- if (pmd)
- *pmd = s->s3->tmp.md[idx];
- return c->pkeys[idx].privatekey;
-}
-
int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
size_t *serverinfo_length)
{
- CERT *c = NULL;
- int i = 0;
+ CERT_PKEY *cpk = s->s3->tmp.cert;
*serverinfo_length = 0;
- c = s->cert;
- i = ssl_get_server_cert_index(s);
-
- if (i == -1)
- return 0;
- if (c->pkeys[i].serverinfo == NULL)
+ if (cpk == NULL || cpk->serverinfo == NULL)
return 0;
- *serverinfo = c->pkeys[i].serverinfo;
- *serverinfo_length = c->pkeys[i].serverinfo_length;
+ *serverinfo = cpk->serverinfo;
+ *serverinfo_length = cpk->serverinfo_length;
return 1;
}
if (s->method != meth) {
const SSL_METHOD *sm = s->method;
- int (*hf)(SSL *) = s->handshake_func;
+ int (*hf) (SSL *) = s->handshake_func;
if (sm->version == meth->version)
s->method = meth;
return (SSL_ERROR_SSL);
}
- if (i < 0) {
- if (SSL_want_read(s)) {
- bio = SSL_get_rbio(s);
- if (BIO_should_read(bio))
- return (SSL_ERROR_WANT_READ);
- else if (BIO_should_write(bio))
- /*
- * This one doesn't make too much sense ... We never try to write
- * to the rbio, and an application program where rbio and wbio
- * are separate couldn't even know what it should wait for.
- * However if we ever set s->rwstate incorrectly (so that we have
- * SSL_want_read(s) instead of SSL_want_write(s)) and rbio and
- * wbio *are* the same, this test works around that bug; so it
- * might be safer to keep it.
- */
- return (SSL_ERROR_WANT_WRITE);
- else if (BIO_should_io_special(bio)) {
- reason = BIO_get_retry_reason(bio);
- if (reason == BIO_RR_CONNECT)
- return (SSL_ERROR_WANT_CONNECT);
- else if (reason == BIO_RR_ACCEPT)
- return (SSL_ERROR_WANT_ACCEPT);
- else
- return (SSL_ERROR_SYSCALL); /* unknown */
- }
+ if (SSL_want_read(s)) {
+ bio = SSL_get_rbio(s);
+ if (BIO_should_read(bio))
+ return (SSL_ERROR_WANT_READ);
+ else if (BIO_should_write(bio))
+ /*
+ * This one doesn't make too much sense ... We never try to write
+ * to the rbio, and an application program where rbio and wbio
+ * are separate couldn't even know what it should wait for.
+ * However if we ever set s->rwstate incorrectly (so that we have
+ * SSL_want_read(s) instead of SSL_want_write(s)) and rbio and
+ * wbio *are* the same, this test works around that bug; so it
+ * might be safer to keep it.
+ */
+ return (SSL_ERROR_WANT_WRITE);
+ else if (BIO_should_io_special(bio)) {
+ reason = BIO_get_retry_reason(bio);
+ if (reason == BIO_RR_CONNECT)
+ return (SSL_ERROR_WANT_CONNECT);
+ else if (reason == BIO_RR_ACCEPT)
+ return (SSL_ERROR_WANT_ACCEPT);
+ else
+ return (SSL_ERROR_SYSCALL); /* unknown */
}
+ }
- if (SSL_want_write(s)) {
- bio = SSL_get_wbio(s);
- if (BIO_should_write(bio))
- return (SSL_ERROR_WANT_WRITE);
- else if (BIO_should_read(bio))
- /*
- * See above (SSL_want_read(s) with BIO_should_write(bio))
- */
- return (SSL_ERROR_WANT_READ);
- else if (BIO_should_io_special(bio)) {
- reason = BIO_get_retry_reason(bio);
- if (reason == BIO_RR_CONNECT)
- return (SSL_ERROR_WANT_CONNECT);
- else if (reason == BIO_RR_ACCEPT)
- return (SSL_ERROR_WANT_ACCEPT);
- else
- return (SSL_ERROR_SYSCALL);
- }
- }
- if (SSL_want_x509_lookup(s)) {
- return (SSL_ERROR_WANT_X509_LOOKUP);
- }
- if (SSL_want_async(s)) {
- return SSL_ERROR_WANT_ASYNC;
- }
- if (SSL_want_async_job(s)) {
- return SSL_ERROR_WANT_ASYNC_JOB;
+ if (SSL_want_write(s)) {
+ /*
+ * Access wbio directly - in order to use the buffered bio if
+ * present
+ */
+ bio = s->wbio;
+ if (BIO_should_write(bio))
+ return (SSL_ERROR_WANT_WRITE);
+ else if (BIO_should_read(bio))
+ /*
+ * See above (SSL_want_read(s) with BIO_should_write(bio))
+ */
+ return (SSL_ERROR_WANT_READ);
+ else if (BIO_should_io_special(bio)) {
+ reason = BIO_get_retry_reason(bio);
+ if (reason == BIO_RR_CONNECT)
+ return (SSL_ERROR_WANT_CONNECT);
+ else if (reason == BIO_RR_ACCEPT)
+ return (SSL_ERROR_WANT_ACCEPT);
+ else
+ return (SSL_ERROR_SYSCALL);
}
}
+ if (SSL_want_x509_lookup(s))
+ return (SSL_ERROR_WANT_X509_LOOKUP);
+ if (SSL_want_async(s))
+ return SSL_ERROR_WANT_ASYNC;
+ if (SSL_want_async_job(s))
+ return SSL_ERROR_WANT_ASYNC_JOB;
+ if (SSL_want_early(s))
+ return SSL_ERROR_WANT_EARLY;
+
+ if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
+ (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
+ return (SSL_ERROR_ZERO_RETURN);
- if (i == 0) {
- if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
- (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
- return (SSL_ERROR_ZERO_RETURN);
- }
return (SSL_ERROR_SYSCALL);
}
return -1;
}
- s->method->ssl_renegotiate_check(s);
+ if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
+ || s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY)
+ return -1;
+
+ s->method->ssl_renegotiate_check(s, 0);
if (SSL_in_init(s) || SSL_in_before(s)) {
- if((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
+ if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
args.s = s;
const char *ssl_protocol_to_string(int version)
{
- if (version == TLS1_2_VERSION)
+ switch(version)
+ {
+ case TLS1_3_VERSION:
+ return "TLSv1.3";
+
+ case TLS1_2_VERSION:
return "TLSv1.2";
- else if (version == TLS1_1_VERSION)
+
+ case TLS1_1_VERSION:
return "TLSv1.1";
- else if (version == TLS1_VERSION)
+
+ case TLS1_VERSION:
return "TLSv1";
- else if (version == SSL3_VERSION)
+
+ case SSL3_VERSION:
return "SSLv3";
- else if (version == DTLS1_BAD_VER)
+
+ case DTLS1_BAD_VER:
return "DTLSv0.9";
- else if (version == DTLS1_VERSION)
+
+ case DTLS1_VERSION:
return "DTLSv1";
- else if (version == DTLS1_2_VERSION)
+
+ case DTLS1_2_VERSION:
return "DTLSv1.2";
- else
- return ("unknown");
+
+ default:
+ return "unknown";
+ }
}
const char *SSL_get_version(const SSL *s)
/* If we're not quiescent, just up_ref! */
if (!SSL_in_init(s) || !SSL_in_before(s)) {
- CRYPTO_atomic_add(&s->references, 1, &i, s->lock);
+ CRYPTO_UP_REF(&s->references, &i, s->lock);
return s;
}
goto err;
}
- if (!SSL_set_session_id_context(ret, s->sid_ctx, s->sid_ctx_length))
+ if (!SSL_set_session_id_context(ret, s->sid_ctx,
+ (int)s->sid_ctx_length))
goto err;
}
if (s->wbio != s->rbio) {
if (!BIO_dup_state(s->wbio, (char *)&ret->wbio))
goto err;
- } else
+ } else {
+ BIO_up_ref(ret->rbio);
ret->wbio = ret->rbio;
+ }
}
ret->server = s->server;
#endif
}
-int ssl_init_wbio_buffer(SSL *s, int push)
+int ssl_init_wbio_buffer(SSL *s)
{
BIO *bbio;
- if (s->bbio == NULL) {
- bbio = BIO_new(BIO_f_buffer());
- if (bbio == NULL)
- return (0);
- s->bbio = bbio;
- } else {
- bbio = s->bbio;
- if (s->bbio == s->wbio)
- s->wbio = BIO_pop(s->wbio);
+ if (s->bbio != NULL) {
+ /* Already buffered. */
+ return 1;
}
- (void)BIO_reset(bbio);
-/* if (!BIO_set_write_buffer_size(bbio,16*1024)) */
- if (!BIO_set_read_buffer_size(bbio, 1)) {
+
+ bbio = BIO_new(BIO_f_buffer());
+ if (bbio == NULL || !BIO_set_read_buffer_size(bbio, 1)) {
+ BIO_free(bbio);
SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER, ERR_R_BUF_LIB);
- return (0);
- }
- if (push) {
- if (s->wbio != bbio)
- s->wbio = BIO_push(bbio, s->wbio);
- } else {
- if (s->wbio == bbio)
- s->wbio = BIO_pop(bbio);
+ return 0;
}
- return (1);
+ s->bbio = bbio;
+ s->wbio = BIO_push(bbio, s->wbio);
+
+ return 1;
}
void ssl_free_wbio_buffer(SSL *s)
if (s->bbio == NULL)
return;
- if (s->bbio == s->wbio) {
- /* remove buffering */
- s->wbio = BIO_pop(s->wbio);
- assert(s->wbio != NULL);
- }
+ s->wbio = BIO_pop(s->wbio);
+ assert(s->wbio != NULL);
BIO_free(s->bbio);
s->bbio = NULL;
}
if (ssl->ctx == ctx)
return ssl->ctx;
if (ctx == NULL)
- ctx = ssl->initial_ctx;
+ ctx = ssl->session_ctx;
new_cert = ssl_cert_dup(ctx->cert);
if (new_cert == NULL) {
return NULL;
}
SSL_CTX_up_ref(ctx);
- SSL_CTX_free(ssl->ctx); /* decrement reference count */
+ SSL_CTX_free(ssl->ctx); /* decrement reference count */
ssl->ctx = ctx;
return ssl->ctx;
}
size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
- unsigned char *out, size_t outlen)
+ unsigned char *out, size_t outlen)
{
- if (session->master_key_length < 0) {
- /* Should never happen */
- return 0;
- }
if (outlen == 0)
return session->master_key_length;
- if (outlen > (size_t)session->master_key_length)
+ if (outlen > session->master_key_length)
outlen = session->master_key_length;
memcpy(out, session->master_key, outlen);
return outlen;
return (CRYPTO_get_ex_data(&s->ex_data, idx));
}
-int ssl_ok(SSL *s)
-{
- return (1);
-}
-
X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx)
{
return (ctx->cert_store);
ctx->cert_store = store;
}
+void SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store)
+{
+ if (store != NULL)
+ X509_STORE_up_ref(store);
+ SSL_CTX_set_cert_store(ctx, store);
+}
+
int SSL_want(const SSL *s)
{
return (s->rwstate);
int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
{
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
- SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT,
- SSL_R_DATA_LENGTH_TOO_LONG);
+ SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
OPENSSL_free(ctx->cert->psk_identity_hint);
return (s->session->psk_identity);
}
-void SSL_set_psk_client_callback(SSL *s,
- unsigned int (*cb) (SSL *ssl,
- const char *hint,
- char *identity,
- unsigned int
- max_identity_len,
- unsigned char *psk,
- unsigned int
- max_psk_len))
+void SSL_set_psk_client_callback(SSL *s, SSL_psk_client_cb_func cb)
{
s->psk_client_callback = cb;
}
-void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx,
- unsigned int (*cb) (SSL *ssl,
- const char *hint,
- char *identity,
- unsigned int
- max_identity_len,
- unsigned char *psk,
- unsigned int
- max_psk_len))
+void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb)
{
ctx->psk_client_callback = cb;
}
-void SSL_set_psk_server_callback(SSL *s,
- unsigned int (*cb) (SSL *ssl,
- const char *identity,
- unsigned char *psk,
- unsigned int
- max_psk_len))
+void SSL_set_psk_server_callback(SSL *s, SSL_psk_server_cb_func cb)
{
s->psk_server_callback = cb;
}
-void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx,
- unsigned int (*cb) (SSL *ssl,
- const char *identity,
- unsigned char *psk,
- unsigned int
- max_psk_len))
+void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb)
{
ctx->psk_server_callback = cb;
}
/*
* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
* variable, freeing EVP_MD_CTX previously stored in that variable, if any.
- * If EVP_MD pointer is passed, initializes ctx with this md Returns newly
- * allocated ctx;
+ * If EVP_MD pointer is passed, initializes ctx with this md.
+ * Returns the newly allocated ctx;
*/
EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md)
void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
{
- if (*hash)
- EVP_MD_CTX_free(*hash);
+ EVP_MD_CTX_free(*hash);
*hash = NULL;
}
/* Retrieve handshake hashes */
-int ssl_handshake_hash(SSL *s, unsigned char *out, int outlen)
+int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
+ size_t *hashlen)
{
EVP_MD_CTX *ctx = NULL;
EVP_MD_CTX *hdgst = s->s3->handshake_dgst;
- int ret = EVP_MD_CTX_size(hdgst);
- if (ret < 0 || ret > outlen) {
- ret = 0;
+ int hashleni = EVP_MD_CTX_size(hdgst);
+ int ret = 0;
+
+ if (hashleni < 0 || (size_t)hashleni > outlen)
goto err;
- }
+
ctx = EVP_MD_CTX_new();
- if (ctx == NULL) {
- ret = 0;
+ if (ctx == NULL)
goto err;
- }
+
if (!EVP_MD_CTX_copy_ex(ctx, hdgst)
|| EVP_DigestFinal_ex(ctx, out, NULL) <= 0)
- ret = 0;
+ goto err;
+
+ *hashlen = hashleni;
+
+ ret = 1;
err:
EVP_MD_CTX_free(ctx);
return ret;
}
#endif
-
void SSL_set_security_level(SSL *s, int level)
{
s->cert->sec_level = level;
}
void SSL_set_security_callback(SSL *s,
- int (*cb) (const SSL *s, const SSL_CTX *ctx, int op,
- int bits, int nid, void *other,
- void *ex))
+ int (*cb) (const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex))
{
s->cert->sec_cb = cb;
}
-int (*SSL_get_security_callback(const SSL *s)) (const SSL *s, const SSL_CTX *ctx, int op,
- int bits, int nid,
- void *other, void *ex) {
+int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
+ const SSL_CTX *ctx, int op,
+ int bits, int nid, void *other,
+ void *ex) {
return s->cert->sec_cb;
}
}
void SSL_CTX_set_security_callback(SSL_CTX *ctx,
- int (*cb) (const SSL *s, const SSL_CTX *ctx, int op,
- int bits, int nid, void *other,
- void *ex))
+ int (*cb) (const SSL *s, const SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex))
{
ctx->cert->sec_cb = cb;
}
return ctx->cert->sec_ex;
}
-
/*
* Get/Set/Clear options in SSL_CTX or SSL, formerly macros, now functions that
* can return unsigned long, instead of the generic long return value from the
{
return ctx->options;
}
-unsigned long SSL_get_options(const SSL* s)
+
+unsigned long SSL_get_options(const SSL *s)
{
return s->options;
}
+
unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op)
{
return ctx->options |= op;
}
+
unsigned long SSL_set_options(SSL *s, unsigned long op)
{
return s->options |= op;
}
+
unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op)
{
return ctx->options &= ~op;
}
+
unsigned long SSL_clear_options(SSL *s, unsigned long op)
{
return s->options &= ~op;
* the caller.
* Returns the number of SCTs moved, or a negative integer if an error occurs.
*/
-static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src, sct_source_t origin)
+static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src,
+ sct_source_t origin)
{
int scts_moved = 0;
SCT *sct = NULL;
}
return scts_moved;
-err:
+ err:
if (sct != NULL)
- sk_SCT_push(src, sct); /* Put the SCT back */
- return scts_moved;
+ sk_SCT_push(src, sct); /* Put the SCT back */
+ return -1;
}
/*
-* Look for data collected during ServerHello and parse if found.
-* Return 1 on success, 0 on failure.
-*/
+ * Look for data collected during ServerHello and parse if found.
+ * Returns the number of SCTs extracted.
+ */
static int ct_extract_tls_extension_scts(SSL *s)
{
int scts_extracted = 0;
- if (s->tlsext_scts != NULL) {
- const unsigned char *p = s->tlsext_scts;
- STACK_OF(SCT) *scts = o2i_SCT_LIST(NULL, &p, s->tlsext_scts_len);
+ if (s->ext.scts != NULL) {
+ const unsigned char *p = s->ext.scts;
+ STACK_OF(SCT) *scts = o2i_SCT_LIST(NULL, &p, s->ext.scts_len);
scts_extracted = ct_move_scts(&s->scts, scts, SCT_SOURCE_TLS_EXTENSION);
*/
static int ct_extract_ocsp_response_scts(SSL *s)
{
-#ifndef OPENSSL_NO_OCSP
+# ifndef OPENSSL_NO_OCSP
int scts_extracted = 0;
const unsigned char *p;
OCSP_BASICRESP *br = NULL;
STACK_OF(SCT) *scts = NULL;
int i;
- if (s->tlsext_ocsp_resp == NULL || s->tlsext_ocsp_resplen == 0)
+ if (s->ext.ocsp.resp == NULL || s->ext.ocsp.resp_len == 0)
goto err;
- p = s->tlsext_ocsp_resp;
- rsp = d2i_OCSP_RESPONSE(NULL, &p, s->tlsext_ocsp_resplen);
+ p = s->ext.ocsp.resp;
+ rsp = d2i_OCSP_RESPONSE(NULL, &p, (int)s->ext.ocsp.resp_len);
if (rsp == NULL)
goto err;
if (single == NULL)
continue;
- scts = OCSP_SINGLERESP_get1_ext_d2i(single, NID_ct_cert_scts, NULL, NULL);
- scts_extracted = ct_move_scts(&s->scts, scts,
- SCT_SOURCE_OCSP_STAPLED_RESPONSE);
+ scts =
+ OCSP_SINGLERESP_get1_ext_d2i(single, NID_ct_cert_scts, NULL, NULL);
+ scts_extracted =
+ ct_move_scts(&s->scts, scts, SCT_SOURCE_OCSP_STAPLED_RESPONSE);
if (scts_extracted < 0)
goto err;
}
-err:
+ err:
SCT_LIST_free(scts);
OCSP_BASICRESP_free(br);
OCSP_RESPONSE_free(rsp);
return scts_extracted;
-#else
+# else
/* Behave as if no OCSP response exists */
return 0;
-#endif
+# endif
}
/*
s->scts_parsed = 1;
}
return s->scts;
-err:
+ err:
return NULL;
}
-static int ct_permissive(const CT_POLICY_EVAL_CTX *ctx,
+static int ct_permissive(const CT_POLICY_EVAL_CTX * ctx,
const STACK_OF(SCT) *scts, void *unused_arg)
{
return 1;
}
-static int ct_strict(const CT_POLICY_EVAL_CTX *ctx,
+static int ct_strict(const CT_POLICY_EVAL_CTX * ctx,
const STACK_OF(SCT) *scts, void *unused_arg)
{
int count = scts != NULL ? sk_SCT_num(scts) : 0;
* for this and throw an error if they have already registered to use CT.
*/
if (callback != NULL && SSL_CTX_has_client_custom_ext(s->ctx,
- TLSEXT_TYPE_signed_certificate_timestamp)) {
+ TLSEXT_TYPE_signed_certificate_timestamp))
+ {
SSLerr(SSL_F_SSL_SET_CT_VALIDATION_CALLBACK,
SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
return 0;
}
if (callback != NULL) {
- /* If we are validating CT, then we MUST accept SCTs served via OCSP */
+ /*
+ * If we are validating CT, then we MUST accept SCTs served via OCSP
+ */
if (!SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp))
return 0;
}
}
int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
- ssl_ct_validation_cb callback,
- void *arg)
+ ssl_ct_validation_cb callback, void *arg)
{
/*
* Since code exists that uses the custom extension handler for CT, look for
* this and throw an error if they have already registered to use CT.
*/
if (callback != NULL && SSL_CTX_has_client_custom_ext(ctx,
- TLSEXT_TYPE_signed_certificate_timestamp)) {
+ TLSEXT_TYPE_signed_certificate_timestamp))
+ {
SSLerr(SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK,
SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
return 0;
*/
if (s->ct_validation_callback == NULL || cert == NULL ||
s->verify_result != X509_V_OK ||
- s->verified_chain == NULL ||
- sk_X509_num(s->verified_chain) <= 1)
+ s->verified_chain == NULL || sk_X509_num(s->verified_chain) <= 1)
return 1;
/*
}
issuer = sk_X509_value(s->verified_chain, 1);
- CT_POLICY_EVAL_CTX_set0_cert(ctx, cert);
- CT_POLICY_EVAL_CTX_set0_issuer(ctx, issuer);
- CT_POLICY_EVAL_CTX_set0_log_store(ctx, s->ctx->ctlog_store);
+ CT_POLICY_EVAL_CTX_set1_cert(ctx, cert);
+ CT_POLICY_EVAL_CTX_set1_issuer(ctx, issuer);
+ CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ctx, s->ctx->ctlog_store);
+ CT_POLICY_EVAL_CTX_set_time(ctx, SSL_SESSION_get_time(SSL_get0_session(s)));
scts = SSL_get0_peer_scts(s);
* value is negative.
*
* XXX: One might well argue that the return value of this function is an
- * unforunate design choice. Its job is only to determine the validation
+ * unfortunate design choice. Its job is only to determine the validation
* status of each of the provided SCTs. So long as it correctly separates
* the wheat from the chaff it should return success. Failure in this case
* ought to correspond to an inability to carry out its duties.
ret = s->ct_validation_callback(ctx, scts, s->ct_validation_callback_arg);
if (ret < 0)
- ret = 0; /* This function returns 0 on failure */
+ ret = 0; /* This function returns 0 on failure */
-end:
+ end:
CT_POLICY_EVAL_CTX_free(ctx);
/*
* With SSL_VERIFY_NONE the session may be cached and re-used despite a
return CTLOG_STORE_load_file(ctx->ctlog_store, path);
}
-void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs)
+void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE * logs)
{
CTLOG_STORE_free(ctx->ctlog_store);
ctx->ctlog_store = logs;
return ctx->ctlog_store;
}
-#endif
+#endif /* OPENSSL_NO_CT */
+
+void SSL_CTX_set_early_cb(SSL_CTX *c, SSL_early_cb_fn cb, void *arg)
+{
+ c->early_cb = cb;
+ c->early_cb_arg = arg;
+}
+
+int SSL_early_isv2(SSL *s)
+{
+ if (s->clienthello == NULL)
+ return 0;
+ return s->clienthello->isv2;
+}
+
+unsigned int SSL_early_get0_legacy_version(SSL *s)
+{
+ if (s->clienthello == NULL)
+ return 0;
+ return s->clienthello->legacy_version;
+}
+
+size_t SSL_early_get0_random(SSL *s, const unsigned char **out)
+{
+ if (s->clienthello == NULL)
+ return 0;
+ if (out != NULL)
+ *out = s->clienthello->random;
+ return SSL3_RANDOM_SIZE;
+}
+
+size_t SSL_early_get0_session_id(SSL *s, const unsigned char **out)
+{
+ if (s->clienthello == NULL)
+ return 0;
+ if (out != NULL)
+ *out = s->clienthello->session_id;
+ return s->clienthello->session_id_len;
+}
+
+size_t SSL_early_get0_ciphers(SSL *s, const unsigned char **out)
+{
+ if (s->clienthello == NULL)
+ return 0;
+ if (out != NULL)
+ *out = PACKET_data(&s->clienthello->ciphersuites);
+ return PACKET_remaining(&s->clienthello->ciphersuites);
+}
+
+size_t SSL_early_get0_compression_methods(SSL *s, const unsigned char **out)
+{
+ if (s->clienthello == NULL)
+ return 0;
+ if (out != NULL)
+ *out = s->clienthello->compressions;
+ return s->clienthello->compressions_len;
+}
+
+int SSL_early_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
+ size_t *outlen)
+{
+ size_t i;
+ RAW_EXTENSION *r;
+
+ if (s->clienthello == NULL)
+ return 0;
+ for (i = 0; i < s->clienthello->pre_proc_exts_len; ++i) {
+ r = s->clienthello->pre_proc_exts + i;
+ if (r->present && r->type == type) {
+ if (out != NULL)
+ *out = PACKET_data(&r->data);
+ if (outlen != NULL)
+ *outlen = PACKET_remaining(&r->data);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb)
+{
+ ctx->keylog_callback = cb;
+}
+
+SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx)
+{
+ return ctx->keylog_callback;
+}
+
+static int nss_keylog_int(const char *prefix,
+ SSL *ssl,
+ const uint8_t *parameter_1,
+ size_t parameter_1_len,
+ const uint8_t *parameter_2,
+ size_t parameter_2_len)
+{
+ char *out = NULL;
+ char *cursor = NULL;
+ size_t out_len = 0;
+ size_t i;
+ size_t prefix_len;
+
+ if (ssl->ctx->keylog_callback == NULL) return 1;
+
+ /*
+ * Our output buffer will contain the following strings, rendered with
+ * space characters in between, terminated by a NULL character: first the
+ * prefix, then the first parameter, then the second parameter. The
+ * meaning of each parameter depends on the specific key material being
+ * logged. Note that the first and second parameters are encoded in
+ * hexadecimal, so we need a buffer that is twice their lengths.
+ */
+ prefix_len = strlen(prefix);
+ out_len = prefix_len + (2*parameter_1_len) + (2*parameter_2_len) + 3;
+ if ((out = cursor = OPENSSL_malloc(out_len)) == NULL) {
+ SSLerr(SSL_F_NSS_KEYLOG_INT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ strcpy(cursor, prefix);
+ cursor += prefix_len;
+ *cursor++ = ' ';
+
+ for (i = 0; i < parameter_1_len; i++) {
+ sprintf(cursor, "%02x", parameter_1[i]);
+ cursor += 2;
+ }
+ *cursor++ = ' ';
+
+ for (i = 0; i < parameter_2_len; i++) {
+ sprintf(cursor, "%02x", parameter_2[i]);
+ cursor += 2;
+ }
+ *cursor = '\0';
+
+ ssl->ctx->keylog_callback(ssl, (const char *)out);
+ OPENSSL_free(out);
+ return 1;
+
+}
+
+int ssl_log_rsa_client_key_exchange(SSL *ssl,
+ const uint8_t *encrypted_premaster,
+ size_t encrypted_premaster_len,
+ const uint8_t *premaster,
+ size_t premaster_len)
+{
+ if (encrypted_premaster_len < 8) {
+ SSLerr(SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ /* We only want the first 8 bytes of the encrypted premaster as a tag. */
+ return nss_keylog_int("RSA",
+ ssl,
+ encrypted_premaster,
+ 8,
+ premaster,
+ premaster_len);
+}
+
+int ssl_log_secret(SSL *ssl,
+ const char *label,
+ const uint8_t *secret,
+ size_t secret_len)
+{
+ return nss_keylog_int(label,
+ ssl,
+ ssl->s3->client_random,
+ SSL3_RANDOM_SIZE,
+ secret,
+ secret_len);
+}
+
+#define SSLV2_CIPHER_LEN 3
+
+int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format,
+ int *al)
+{
+ int n;
+
+ n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
+
+ if (PACKET_remaining(cipher_suites) == 0) {
+ SSLerr(SSL_F_SSL_CACHE_CIPHERLIST, SSL_R_NO_CIPHERS_SPECIFIED);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ if (PACKET_remaining(cipher_suites) % n != 0) {
+ SSLerr(SSL_F_SSL_CACHE_CIPHERLIST,
+ SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ OPENSSL_free(s->s3->tmp.ciphers_raw);
+ s->s3->tmp.ciphers_raw = NULL;
+ s->s3->tmp.ciphers_rawlen = 0;
+
+ if (sslv2format) {
+ size_t numciphers = PACKET_remaining(cipher_suites) / n;
+ PACKET sslv2ciphers = *cipher_suites;
+ unsigned int leadbyte;
+ unsigned char *raw;
+
+ /*
+ * We store the raw ciphers list in SSLv3+ format so we need to do some
+ * preprocessing to convert the list first. If there are any SSLv2 only
+ * ciphersuites with a non-zero leading byte then we are going to
+ * slightly over allocate because we won't store those. But that isn't a
+ * problem.
+ */
+ raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN);
+ s->s3->tmp.ciphers_raw = raw;
+ if (raw == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ for (s->s3->tmp.ciphers_rawlen = 0;
+ PACKET_remaining(&sslv2ciphers) > 0;
+ raw += TLS_CIPHER_LEN) {
+ if (!PACKET_get_1(&sslv2ciphers, &leadbyte)
+ || (leadbyte == 0
+ && !PACKET_copy_bytes(&sslv2ciphers, raw,
+ TLS_CIPHER_LEN))
+ || (leadbyte != 0
+ && !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_free(s->s3->tmp.ciphers_raw);
+ s->s3->tmp.ciphers_raw = NULL;
+ s->s3->tmp.ciphers_rawlen = 0;
+ goto err;
+ }
+ if (leadbyte == 0)
+ s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN;
+ }
+ } else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw,
+ &s->s3->tmp.ciphers_rawlen)) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ return 1;
+ err:
+ return 0;
+}
+
+int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
+ int isv2format, STACK_OF(SSL_CIPHER) **sk,
+ STACK_OF(SSL_CIPHER) **scsvs)
+{
+ int alert;
+ PACKET pkt;
+
+ if (!PACKET_buf_init(&pkt, bytes, len))
+ return 0;
+ return bytes_to_cipher_list(s, &pkt, sk, scsvs, isv2format, &alert);
+}
+
+int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
+ STACK_OF(SSL_CIPHER) **skp,
+ STACK_OF(SSL_CIPHER) **scsvs_out,
+ int sslv2format, int *al)
+{
+ const SSL_CIPHER *c;
+ STACK_OF(SSL_CIPHER) *sk = NULL;
+ STACK_OF(SSL_CIPHER) *scsvs = NULL;
+ int n;
+ /* 3 = SSLV2_CIPHER_LEN > TLS_CIPHER_LEN = 2. */
+ unsigned char cipher[SSLV2_CIPHER_LEN];
+
+ n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
+
+ if (PACKET_remaining(cipher_suites) == 0) {
+ SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ if (PACKET_remaining(cipher_suites) % n != 0) {
+ SSLerr(SSL_F_BYTES_TO_CIPHER_LIST,
+ SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ sk = sk_SSL_CIPHER_new_null();
+ scsvs = sk_SSL_CIPHER_new_null();
+ if (sk == NULL || scsvs == NULL) {
+ SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+
+ while (PACKET_copy_bytes(cipher_suites, cipher, n)) {
+ /*
+ * SSLv3 ciphers wrapped in an SSLv2-compatible ClientHello have the
+ * first byte set to zero, while true SSLv2 ciphers have a non-zero
+ * first byte. We don't support any true SSLv2 ciphers, so skip them.
+ */
+ if (sslv2format && cipher[0] != '\0')
+ continue;
+
+ /* For SSLv2-compat, ignore leading 0-byte. */
+ c = ssl_get_cipher_by_char(s, sslv2format ? &cipher[1] : cipher, 1);
+ if (c != NULL) {
+ if ((c->valid && !sk_SSL_CIPHER_push(sk, c)) ||
+ (!c->valid && !sk_SSL_CIPHER_push(scsvs, c))) {
+ SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ *al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ }
+ }
+ if (PACKET_remaining(cipher_suites) > 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (skp != NULL)
+ *skp = sk;
+ else
+ sk_SSL_CIPHER_free(sk);
+ if (scsvs_out != NULL)
+ *scsvs_out = scsvs;
+ else
+ sk_SSL_CIPHER_free(scsvs);
+ return 1;
+ err:
+ sk_SSL_CIPHER_free(sk);
+ sk_SSL_CIPHER_free(scsvs);
+ return 0;
+}
+
+int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data)
+{
+ ctx->max_early_data = max_early_data;
+
+ return 1;
+}
+
+uint32_t SSL_CTX_get_max_early_data(SSL_CTX *ctx)
+{
+ return ctx->max_early_data;
+}
+
+int SSL_set_max_early_data(SSL *s, uint32_t max_early_data)
+{
+ s->max_early_data = max_early_data;
+
+ return 1;
+}
+
+uint32_t SSL_get_max_early_data(SSL_CTX *s)
+{
+ return s->max_early_data;
+}