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;
s->ext.ocsp.resp = NULL;
s->ext.ocsp.resp_len = 0;
SSL_CTX_up_ref(ctx);
- s->initial_ctx = ctx;
+ s->session_ctx = ctx;
#ifndef OPENSSL_NO_EC
if (ctx->ext.ecpointformats) {
s->ext.ecpointformats =
s->method = ctx->method;
+ s->key_update = SSL_KEY_UPDATE_NONE;
+
if (!s->method->ssl_new(s))
goto err;
/* Free up if allocated */
OPENSSL_free(s->ext.hostname);
- SSL_CTX_free(s->initial_ctx);
+ SSL_CTX_free(s->session_ctx);
#ifndef OPENSSL_NO_EC
OPENSSL_free(s->ext.ecpointformats);
OPENSSL_free(s->ext.supportedgroups);
#endif
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);
return -1;
}
-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_ex(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 ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
- SSLerr(SSL_F_SSL_READ_EX, 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) {
}
}
-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_PEEK, SSL_R_BAD_LENGTH);
+ SSLerr(SSL_F_SSL_READ, SSL_R_BAD_LENGTH);
return -1;
}
- ret = SSL_peek_ex(s, buf, (size_t)num, &readbytes);
+ ret = ssl_read_internal(s, buf, (size_t)num, &readbytes);
/*
* The cast is safe here because ret should be <= INT_MAX because num is
return ret;
}
-int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
+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_EX, 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) {
struct ssl_async_args args;
}
}
-int SSL_write(SSL *s, const void *buf, int num)
+int SSL_peek(SSL *s, void *buf, int num)
{
int ret;
- size_t written;
+ size_t readbytes;
if (num < 0) {
- SSLerr(SSL_F_SSL_WRITE, SSL_R_BAD_LENGTH);
+ SSLerr(SSL_F_SSL_PEEK, SSL_R_BAD_LENGTH);
return -1;
}
- ret = SSL_write_ex(s, buf, (size_t)num, &written);
+ 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)written;
+ ret = (int)readbytes;
return ret;
}
-int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written)
+
+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_EX, 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_EX, 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) {
}
}
+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_shutdown(SSL *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;
* ServerHello.
*/
void SSL_CTX_set_npn_advertised_cb(SSL_CTX *ctx,
- int (*cb) (SSL *ssl,
- const unsigned char **out,
- unsigned int *outlen,
- void *arg),
+ SSL_CTX_npn_advertised_cb_func cb,
void *arg)
{
ctx->ext.npn_advertised_cb = cb;
* a value other than SSL_TLSEXT_ERR_OK.
*/
void SSL_CTX_set_npn_select_cb(SSL_CTX *ctx,
- int (*cb) (SSL *s, unsigned char **out,
- unsigned char *outlen,
- const unsigned char *in,
- unsigned int inlen,
- void *arg),
+ SSL_CTX_npn_select_cb_func cb,
void *arg)
{
ctx->ext.npn_select_cb = cb;
* 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->ext.alpn_select_cb = cb;
ctx->ext.alpn_select_cb_arg = arg;
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);
}
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;
}
return (SSL_ERROR_SYSCALL);
}
}
- if (SSL_want_x509_lookup(s)) {
+ if (SSL_want_x509_lookup(s))
return (SSL_ERROR_WANT_X509_LOOKUP);
- }
- if (SSL_want_async(s)) {
+ if (SSL_want_async(s))
return SSL_ERROR_WANT_ASYNC;
- }
- if (SSL_want_async_job(s)) {
+ 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 -1;
}
- s->method->ssl_renegotiate_check(s);
+ 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 (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;
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);
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)
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;
+}