Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2014-12-19 04:42:32 +0300
committerAdam Langley <agl@google.com>2014-12-19 04:43:03 +0300
commitfcf25833bc4d057377da1ea755f57b2f5126e555 (patch)
treef9c9c70afa73cc9935c836debb23f6f897266f1b /ssl/t1_enc.c
parent4685e87746bbb6a47772feda773ce9f098948479 (diff)
Reformat the rest of ssl/.
Change-Id: I7dc264f7e29b3ba8be4c717583467edf71bf8dd9
Diffstat (limited to 'ssl/t1_enc.c')
-rw-r--r--ssl/t1_enc.c2311
1 files changed, 1133 insertions, 1178 deletions
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 28405b70..669f736c 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -146,276 +146,259 @@
#include "ssl_locl.h"
-/* seed1 through seed5 are virtually concatenated */
-static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
- int sec_len,
- const void *seed1, int seed1_len,
- const void *seed2, int seed2_len,
- const void *seed3, int seed3_len,
- unsigned char *out, int olen)
- {
- int chunk;
- size_t j;
- EVP_MD_CTX ctx, ctx_tmp, ctx_init;
- EVP_PKEY *mac_key;
- unsigned char A1[EVP_MAX_MD_SIZE];
- size_t A1_len;
- int ret = 0;
-
- chunk=EVP_MD_size(md);
-
- EVP_MD_CTX_init(&ctx);
- EVP_MD_CTX_init(&ctx_tmp);
- EVP_MD_CTX_init(&ctx_init);
- mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
- if (!mac_key)
- goto err;
- if (!EVP_DigestSignInit(&ctx_init,NULL,md, NULL, mac_key))
- goto err;
- if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init))
- goto err;
- if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
- goto err;
- if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
- goto err;
- if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
- goto err;
- A1_len = EVP_MAX_MD_SIZE;
- if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
- goto err;
-
- for (;;)
- {
- /* Reinit mac contexts */
- if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init))
- goto err;
- if (!EVP_DigestSignUpdate(&ctx,A1,A1_len))
- goto err;
- if (olen>chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp,&ctx))
- goto err;
- if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
- goto err;
- if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
- goto err;
- if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
- goto err;
-
- if (olen > chunk)
- {
- j = olen;
- if (!EVP_DigestSignFinal(&ctx,out,&j))
- goto err;
- out+=j;
- olen-=j;
- /* calc the next A1 value */
- A1_len = EVP_MAX_MD_SIZE;
- if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len))
- goto err;
- }
- else /* last one */
- {
- A1_len = EVP_MAX_MD_SIZE;
- if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
- goto err;
- memcpy(out,A1,olen);
- break;
- }
- }
- ret = 1;
+
+/* seed1 through seed3 are virtually concatenated */
+static int tls1_P_hash(const EVP_MD *md, const uint8_t *sec, int sec_len,
+ const void *seed1, int seed1_len,
+ const void *seed2, int seed2_len,
+ const void *seed3, int seed3_len,
+ uint8_t *out, int olen) {
+ int chunk;
+ size_t j;
+ EVP_MD_CTX ctx, ctx_tmp, ctx_init;
+ EVP_PKEY *mac_key;
+ uint8_t A1[EVP_MAX_MD_SIZE];
+ size_t A1_len;
+ int ret = 0;
+
+ chunk = EVP_MD_size(md);
+
+ EVP_MD_CTX_init(&ctx);
+ EVP_MD_CTX_init(&ctx_tmp);
+ EVP_MD_CTX_init(&ctx_init);
+ mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
+ A1_len = EVP_MAX_MD_SIZE;
+ if (!mac_key ||
+ !EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key) ||
+ !EVP_MD_CTX_copy_ex(&ctx, &ctx_init) ||
+ (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) ||
+ (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) ||
+ (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len)) ||
+ !EVP_DigestSignFinal(&ctx, A1, &A1_len)) {
+ goto err;
+ }
+
+ for (;;) {
+ /* Reinit mac contexts */
+ if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init) ||
+ !EVP_DigestSignUpdate(&ctx, A1, A1_len) ||
+ (olen > chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx)) ||
+ (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) ||
+ (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) ||
+ (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len))) {
+ goto err;
+ }
+
+ if (olen > chunk) {
+ j = olen;
+ if (!EVP_DigestSignFinal(&ctx, out, &j)) {
+ goto err;
+ }
+ out += j;
+ olen -= j;
+ /* calc the next A1 value */
+ A1_len = EVP_MAX_MD_SIZE;
+ if (!EVP_DigestSignFinal(&ctx_tmp, A1, &A1_len)) {
+ goto err;
+ }
+ } else {
+ /* last one */
+ A1_len = EVP_MAX_MD_SIZE;
+ if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) {
+ goto err;
+ }
+ memcpy(out, A1, olen);
+ break;
+ }
+ }
+
+ ret = 1;
+
err:
- EVP_PKEY_free(mac_key);
- EVP_MD_CTX_cleanup(&ctx);
- EVP_MD_CTX_cleanup(&ctx_tmp);
- EVP_MD_CTX_cleanup(&ctx_init);
- OPENSSL_cleanse(A1,sizeof(A1));
- return ret;
- }
-
-/* seed1 through seed5 are virtually concatenated */
+ EVP_PKEY_free(mac_key);
+ EVP_MD_CTX_cleanup(&ctx);
+ EVP_MD_CTX_cleanup(&ctx_tmp);
+ EVP_MD_CTX_cleanup(&ctx_init);
+ OPENSSL_cleanse(A1, sizeof(A1));
+ return ret;
+}
+
+/* seed1 through seed3 are virtually concatenated */
static int tls1_PRF(long digest_mask,
- const void *seed1, int seed1_len,
- const void *seed2, int seed2_len,
- const void *seed3, int seed3_len,
- const unsigned char *sec, int slen,
- unsigned char *out1,
- unsigned char *out2, int olen)
- {
- int len,i,idx,count;
- const unsigned char *S1;
- long m;
- const EVP_MD *md;
- int ret = 0;
-
- /* Count number of digests and partition sec evenly */
- count=0;
- for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
- if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++;
- }
- len=slen/count;
- if (count == 1)
- slen = 0;
- S1=sec;
- memset(out1,0,olen);
- for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) {
- if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) {
- if (!md) {
- OPENSSL_PUT_ERROR(SSL, tls1_PRF, SSL_R_UNSUPPORTED_DIGEST_TYPE);
- goto err;
- }
- if (!tls1_P_hash(md ,S1,len+(slen&1),
- seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,
- out2,olen))
- goto err;
- S1+=len;
- for (i=0; i<olen; i++)
- {
- out1[i]^=out2[i];
- }
- }
- }
- ret = 1;
+ const void *seed1, int seed1_len,
+ const void *seed2, int seed2_len,
+ const void *seed3, int seed3_len,
+ const uint8_t *sec, int slen,
+ uint8_t *out1, uint8_t *out2, int olen) {
+ int len, i, idx, count;
+ const uint8_t *S1;
+ long m;
+ const EVP_MD *md;
+ int ret = 0;
+
+ /* Count number of digests and partition sec evenly */
+ count = 0;
+ for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) {
+ if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) {
+ count++;
+ }
+ }
+ len = slen / count;
+ if (count == 1) {
+ slen = 0;
+ }
+ S1 = sec;
+ memset(out1, 0, olen);
+ for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) {
+ if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) {
+ if (!md) {
+ OPENSSL_PUT_ERROR(SSL, tls1_PRF, SSL_R_UNSUPPORTED_DIGEST_TYPE);
+ goto err;
+ }
+ if (!tls1_P_hash(md, S1, len + (slen & 1), seed1, seed1_len, seed2,
+ seed2_len, seed3, seed3_len, out2, olen)) {
+ goto err;
+ }
+ S1 += len;
+ for (i = 0; i < olen; i++) {
+ out1[i] ^= out2[i];
+ }
+ }
+ }
+ ret = 1;
+
err:
- return ret;
+ return ret;
}
-static int tls1_generate_key_block(SSL *s, unsigned char *km,
- unsigned char *tmp, int num)
- {
- int ret;
- ret = tls1_PRF(ssl_get_algorithm2(s),
- TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
- s->s3->server_random,SSL3_RANDOM_SIZE,
- s->s3->client_random,SSL3_RANDOM_SIZE,
- s->session->master_key,s->session->master_key_length,
- km,tmp,num);
- return ret;
- }
+static int tls1_generate_key_block(SSL *s, uint8_t *km, uint8_t *tmp, int num) {
+ return tls1_PRF(ssl_get_algorithm2(s), TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,
+ SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->session->master_key, s->session->master_key_length, km,
+ tmp, num);
+}
/* tls1_aead_ctx_init allocates |*aead_ctx|, if needed and returns 1. It
* returns 0 on malloc error. */
-static int tls1_aead_ctx_init(SSL_AEAD_CTX **aead_ctx)
- {
- if (*aead_ctx != NULL)
- EVP_AEAD_CTX_cleanup(&(*aead_ctx)->ctx);
- else
- {
- *aead_ctx = (SSL_AEAD_CTX*) OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
- if (*aead_ctx == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, tls1_aead_ctx_init, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- }
-
- return 1;
- }
-
-static void tls1_cleanup_enc_ctx(EVP_CIPHER_CTX **ctx)
- {
- if (*ctx != NULL)
- EVP_CIPHER_CTX_free(*ctx);
- *ctx = NULL;
- }
-
-static void tls1_cleanup_hash_ctx(EVP_MD_CTX **ctx)
- {
- if (*ctx != NULL)
- EVP_MD_CTX_destroy(*ctx);
- *ctx = NULL;
- }
+static int tls1_aead_ctx_init(SSL_AEAD_CTX **aead_ctx) {
+ if (*aead_ctx != NULL) {
+ EVP_AEAD_CTX_cleanup(&(*aead_ctx)->ctx);
+ } else {
+ *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
+ if (*aead_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_aead_ctx_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void tls1_cleanup_enc_ctx(EVP_CIPHER_CTX **ctx) {
+ if (*ctx != NULL) {
+ EVP_CIPHER_CTX_free(*ctx);
+ }
+ *ctx = NULL;
+}
+
+static void tls1_cleanup_hash_ctx(EVP_MD_CTX **ctx) {
+ if (*ctx != NULL) {
+ EVP_MD_CTX_destroy(*ctx);
+ }
+ *ctx = NULL;
+}
static int tls1_change_cipher_state_aead(SSL *s, char is_read,
- const unsigned char *key, unsigned key_len,
- const unsigned char *iv, unsigned iv_len,
- const unsigned char *mac_secret, unsigned mac_secret_len)
- {
- const EVP_AEAD *aead = s->s3->tmp.new_aead;
- SSL_AEAD_CTX *aead_ctx;
- /* mac_key_and_key is used to merge the MAC and cipher keys for an AEAD
- * which simulates pre-AEAD cipher suites. It needs to be large enough
- * to cope with the largest pair of keys. */
- uint8_t mac_key_and_key[32 /* HMAC(SHA256) */ + 32 /* AES-256 */];
-
- if (is_read)
- {
- tls1_cleanup_enc_ctx(&s->enc_read_ctx);
- tls1_cleanup_hash_ctx(&s->read_hash);
- }
- else
- {
- tls1_cleanup_enc_ctx(&s->enc_write_ctx);
- tls1_cleanup_hash_ctx(&s->write_hash);
- }
-
- if (mac_secret_len > 0)
- {
- /* This is a "stateful" AEAD (for compatibility with pre-AEAD
- * cipher suites). */
- if (mac_secret_len + key_len > sizeof(mac_key_and_key))
- {
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- memcpy(mac_key_and_key, mac_secret, mac_secret_len);
- memcpy(mac_key_and_key + mac_secret_len, key, key_len);
- key = mac_key_and_key;
- key_len += mac_secret_len;
- }
-
- if (is_read)
- {
- if (!tls1_aead_ctx_init(&s->aead_read_ctx))
- return 0;
- aead_ctx = s->aead_read_ctx;
- }
- else
- {
- if (!tls1_aead_ctx_init(&s->aead_write_ctx))
- return 0;
- aead_ctx = s->aead_write_ctx;
- }
-
- if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len,
- EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */))
- {
- OPENSSL_free(aead_ctx);
- if (is_read)
- s->aead_read_ctx = NULL;
- else
- s->aead_write_ctx = NULL;
- return 0;
- }
- if (iv_len > sizeof(aead_ctx->fixed_nonce))
- {
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- memcpy(aead_ctx->fixed_nonce, iv, iv_len);
- aead_ctx->fixed_nonce_len = iv_len;
- aead_ctx->variable_nonce_len = 8; /* correct for all true AEADs so far. */
- if (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD)
- aead_ctx->variable_nonce_len = 0;
- aead_ctx->variable_nonce_included_in_record =
- (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
- if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len != EVP_AEAD_nonce_length(aead))
- {
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- aead_ctx->tag_len = EVP_AEAD_max_overhead(aead);
-
- return 1;
- }
-
-static void tls1_cleanup_aead_ctx(SSL_AEAD_CTX **ctx)
- {
- if (*ctx != NULL)
- {
- EVP_AEAD_CTX_cleanup(&(*ctx)->ctx);
- OPENSSL_free(*ctx);
- }
- *ctx = NULL;
- }
+ const uint8_t *key, unsigned key_len,
+ const uint8_t *iv, unsigned iv_len,
+ const uint8_t *mac_secret,
+ unsigned mac_secret_len) {
+ const EVP_AEAD *aead = s->s3->tmp.new_aead;
+ SSL_AEAD_CTX *aead_ctx;
+ /* mac_key_and_key is used to merge the MAC and cipher keys for an AEAD which
+ * simulates pre-AEAD cipher suites. It needs to be large enough to cope with
+ * the largest pair of keys. */
+ uint8_t mac_key_and_key[32 /* HMAC(SHA256) */ + 32 /* AES-256 */];
+
+ if (is_read) {
+ tls1_cleanup_enc_ctx(&s->enc_read_ctx);
+ tls1_cleanup_hash_ctx(&s->read_hash);
+ } else {
+ tls1_cleanup_enc_ctx(&s->enc_write_ctx);
+ tls1_cleanup_hash_ctx(&s->write_hash);
+ }
+
+ if (mac_secret_len > 0) {
+ /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
+ * suites). */
+ if (mac_secret_len + key_len > sizeof(mac_key_and_key)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ memcpy(mac_key_and_key, mac_secret, mac_secret_len);
+ memcpy(mac_key_and_key + mac_secret_len, key, key_len);
+ key = mac_key_and_key;
+ key_len += mac_secret_len;
+ }
+
+ if (is_read) {
+ if (!tls1_aead_ctx_init(&s->aead_read_ctx)) {
+ return 0;
+ }
+ aead_ctx = s->aead_read_ctx;
+ } else {
+ if (!tls1_aead_ctx_init(&s->aead_write_ctx)) {
+ return 0;
+ }
+ aead_ctx = s->aead_write_ctx;
+ }
+
+ if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */)) {
+ OPENSSL_free(aead_ctx);
+ if (is_read) {
+ s->aead_read_ctx = NULL;
+ } else {
+ s->aead_write_ctx = NULL;
+ }
+
+ return 0;
+ }
+
+ if (iv_len > sizeof(aead_ctx->fixed_nonce)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ memcpy(aead_ctx->fixed_nonce, iv, iv_len);
+ aead_ctx->fixed_nonce_len = iv_len;
+ aead_ctx->variable_nonce_len = 8; /* correct for all true AEADs so far. */
+ if (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) {
+ aead_ctx->variable_nonce_len = 0;
+ }
+
+ aead_ctx->variable_nonce_included_in_record =
+ (s->s3->tmp.new_cipher->algorithm2 &
+ SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
+ if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len !=
+ EVP_AEAD_nonce_length(aead)) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ aead_ctx->tag_len = EVP_AEAD_max_overhead(aead);
+
+ return 1;
+}
+
+static void tls1_cleanup_aead_ctx(SSL_AEAD_CTX **ctx) {
+ if (*ctx != NULL) {
+ EVP_AEAD_CTX_cleanup(&(*ctx)->ctx);
+ OPENSSL_free(*ctx);
+ }
+ *ctx = NULL;
+}
/* tls1_change_cipher_state_cipher performs the work needed to switch cipher
* states when using EVP_CIPHER. The argument |is_read| is true iff this
@@ -423,941 +406,913 @@ static void tls1_cleanup_aead_ctx(SSL_AEAD_CTX **ctx)
* ChangeCipherSpec message. In order to support export ciphersuites,
* use_client_keys indicates whether the key material provided is in the
* "client write" direction. */
-static int tls1_change_cipher_state_cipher(
- SSL *s, char is_read, char use_client_keys,
- const unsigned char *mac_secret, unsigned mac_secret_len,
- const unsigned char *key, unsigned key_len,
- const unsigned char *iv, unsigned iv_len)
- {
- const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
- EVP_CIPHER_CTX *cipher_ctx;
- EVP_MD_CTX *mac_ctx;
-
- if (is_read)
- tls1_cleanup_aead_ctx(&s->aead_read_ctx);
- else
- tls1_cleanup_aead_ctx(&s->aead_write_ctx);
-
- if (is_read)
- {
- if (s->enc_read_ctx != NULL && !SSL_IS_DTLS(s))
- EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
- else if ((s->enc_read_ctx=EVP_CIPHER_CTX_new()) == NULL)
- goto err;
-
- cipher_ctx = s->enc_read_ctx;
- mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
- if (mac_ctx == NULL)
- goto err;
-
- memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len);
- s->s3->read_mac_secret_size = mac_secret_len;
- }
- else
- {
- /* When updating the write contexts for DTLS, we do not wish to
- * free the old ones because DTLS stores pointers to them in
- * order to implement retransmission. */
-
- if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s))
- EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
- else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
- goto err;
- else
- /* make sure it's intialized in case we exit later with an error */
- EVP_CIPHER_CTX_init(s->enc_write_ctx);
-
- cipher_ctx = s->enc_write_ctx;
- if (SSL_IS_DTLS(s))
- {
- /* This is the same as ssl_replace_hash, but doesn't
- * free the old |s->write_hash|. */
- mac_ctx = EVP_MD_CTX_create();
- if (!mac_ctx)
- goto err;
- s->write_hash = mac_ctx;
- }
- else
- {
- mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
- if (mac_ctx == NULL)
- goto err;
- }
-
- memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len);
- s->s3->write_mac_secret_size = mac_secret_len;
- }
-
- EVP_PKEY *mac_key =
- EVP_PKEY_new_mac_key(s->s3->tmp.new_mac_pkey_type,
- NULL, mac_secret, mac_secret_len);
- if (!mac_key)
- return 0;
- if (!EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key))
- {
- EVP_PKEY_free(mac_key);
- goto err;
- }
- EVP_PKEY_free(mac_key);
-
- if (!EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read))
- goto err;
-
- return 1;
+static int tls1_change_cipher_state_cipher(SSL *s, char is_read,
+ char use_client_keys,
+ const uint8_t *mac_secret,
+ unsigned mac_secret_len,
+ const uint8_t *key, unsigned key_len,
+ const uint8_t *iv, unsigned iv_len) {
+ const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
+ EVP_CIPHER_CTX *cipher_ctx;
+ EVP_MD_CTX *mac_ctx;
+
+ if (is_read) {
+ tls1_cleanup_aead_ctx(&s->aead_read_ctx);
+ } else {
+ tls1_cleanup_aead_ctx(&s->aead_write_ctx);
+ }
+
+ if (is_read) {
+ if (s->enc_read_ctx != NULL && !SSL_IS_DTLS(s)) {
+ EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
+ } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+ goto err;
+ }
+
+ cipher_ctx = s->enc_read_ctx;
+ mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
+ if (mac_ctx == NULL) {
+ goto err;
+ }
+
+ memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len);
+ s->s3->read_mac_secret_size = mac_secret_len;
+ } else {
+ /* When updating the write contexts for DTLS, we do not wish to free the
+ * old ones because DTLS stores pointers to them in order to implement
+ * retransmission. */
+
+ if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) {
+ EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
+ } else {
+ s->enc_write_ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX));
+ if (s->enc_write_ctx == NULL) {
+ goto err;
+ }
+ }
+ EVP_CIPHER_CTX_init(s->enc_write_ctx);
+
+ cipher_ctx = s->enc_write_ctx;
+ if (SSL_IS_DTLS(s)) {
+ /* This is the same as ssl_replace_hash, but doesn't
+ * free the old |s->write_hash|. */
+ mac_ctx = EVP_MD_CTX_create();
+ if (!mac_ctx) {
+ goto err;
+ }
+ s->write_hash = mac_ctx;
+ } else {
+ mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
+ if (mac_ctx == NULL) {
+ goto err;
+ }
+ }
+
+ memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len);
+ s->s3->write_mac_secret_size = mac_secret_len;
+ }
+
+ EVP_PKEY *mac_key = EVP_PKEY_new_mac_key(s->s3->tmp.new_mac_pkey_type, NULL,
+ mac_secret, mac_secret_len);
+ if (!mac_key) {
+ return 0;
+ }
+
+ if (!EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key)) {
+ EVP_PKEY_free(mac_key);
+ goto err;
+ }
+ EVP_PKEY_free(mac_key);
+
+ if (!EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv,
+ !is_read)) {
+ goto err;
+ }
+
+ return 1;
err:
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_cipher, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
-int tls1_change_cipher_state(SSL *s, int which)
- {
- /* is_read is true if we have just read a ChangeCipherSpec message -
- * i.e. we need to update the read cipherspec. Otherwise we have just
- * written one. */
- const char is_read = (which & SSL3_CC_READ) != 0;
- /* use_client_keys is true if we wish to use the keys for the "client
- * write" direction. This is the case if we're a client sending a
- * ChangeCipherSpec, or a server reading a client's ChangeCipherSpec. */
- const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE ||
- which == SSL3_CHANGE_CIPHER_SERVER_READ;
- const unsigned char *client_write_mac_secret, *server_write_mac_secret, *mac_secret;
- const unsigned char *client_write_key, *server_write_key, *key;
- const unsigned char *client_write_iv, *server_write_iv, *iv;
- const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
- const EVP_AEAD *aead = s->s3->tmp.new_aead;
- unsigned key_len, iv_len, mac_secret_len;
- const unsigned char *key_data;
-
- /* Reset sequence number to zero. */
- if (!SSL_IS_DTLS(s))
- memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8);
-
- mac_secret_len = s->s3->tmp.new_mac_secret_size;
-
- if (aead != NULL)
- {
- key_len = EVP_AEAD_key_length(aead);
- /* For "stateful" AEADs (i.e. compatibility with pre-AEAD
- * cipher suites) the key length reported by
- * |EVP_AEAD_key_length| will include the MAC key bytes. */
- if (key_len < mac_secret_len)
- {
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- key_len -= mac_secret_len;
- iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->s3->tmp.new_cipher);
- }
- else
- {
- key_len = EVP_CIPHER_key_length(cipher);
- iv_len = EVP_CIPHER_iv_length(cipher);
- }
-
- key_data = s->s3->tmp.key_block;
- client_write_mac_secret = key_data; key_data += mac_secret_len;
- server_write_mac_secret = key_data; key_data += mac_secret_len;
- client_write_key = key_data; key_data += key_len;
- server_write_key = key_data; key_data += key_len;
- client_write_iv = key_data; key_data += iv_len;
- server_write_iv = key_data; key_data += iv_len;
-
- if (use_client_keys)
- {
- mac_secret = client_write_mac_secret;
- key = client_write_key;
- iv = client_write_iv;
- }
- else
- {
- mac_secret = server_write_mac_secret;
- key = server_write_key;
- iv = server_write_iv;
- }
-
- if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length)
- {
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (aead != NULL)
- {
- if (!tls1_change_cipher_state_aead(s, is_read,
- key, key_len, iv, iv_len,
- mac_secret, mac_secret_len))
- return 0;
- }
- else
- {
- if (!tls1_change_cipher_state_cipher(s, is_read, use_client_keys,
- mac_secret, mac_secret_len,
- key, key_len,
- iv, iv_len))
- return 0;
- }
-
- return 1;
- }
-
-int tls1_setup_key_block(SSL *s)
- {
- unsigned char *p1,*p2=NULL;
- const EVP_CIPHER *c = NULL;
- const EVP_MD *hash = NULL;
- const EVP_AEAD *aead = NULL;
- int num;
- int mac_type= NID_undef,mac_secret_size=0;
- int ret=0;
- unsigned key_len, iv_len;
-
-
- if (s->s3->tmp.key_block_length != 0)
- return(1);
-
- if (s->session->cipher &&
- ((s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) ||
- (s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD)))
- {
- if (!ssl_cipher_get_evp_aead(s->session, &aead))
- goto cipher_unavailable_err;
- key_len = EVP_AEAD_key_length(aead);
- iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
- if ((s->session->cipher->algorithm2 &
- SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) &&
- !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size))
- goto cipher_unavailable_err;
- /* For "stateful" AEADs (i.e. compatibility with pre-AEAD
- * cipher suites) the key length reported by
- * |EVP_AEAD_key_length| will include the MAC key bytes. */
- if (key_len < (size_t)mac_secret_size)
- {
- OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- key_len -= mac_secret_size;
- }
- else
- {
- if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size))
- goto cipher_unavailable_err;
- key_len = EVP_CIPHER_key_length(c);
- iv_len = EVP_CIPHER_iv_length(c);
- }
-
- s->s3->tmp.new_aead=aead;
- s->s3->tmp.new_sym_enc=c;
- s->s3->tmp.new_hash=hash;
- s->s3->tmp.new_mac_pkey_type = mac_type;
- s->s3->tmp.new_mac_secret_size = mac_secret_size;
-
- num=key_len+mac_secret_size+iv_len;
- num*=2;
-
- ssl3_cleanup_key_block(s);
-
- if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- s->s3->tmp.key_block_length=num;
- s->s3->tmp.key_block=p1;
-
- if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
-#ifdef TLS_DEBUG
-printf("client random\n");
-{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); }
-printf("server random\n");
-{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); }
-printf("pre-master\n");
-{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
-#endif
- if (!tls1_generate_key_block(s,p1,p2,num))
- goto err;
-#ifdef TLS_DEBUG
-printf("\nkey block\n");
-{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
-#endif
-
- if (!SSL_USE_EXPLICIT_IV(s) &&
- (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0)
- {
- /* enable vulnerability countermeasure for CBC ciphers with
- * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt)
- */
- s->s3->need_record_splitting = 1;
-
- if (s->session->cipher != NULL)
- {
- if (s->session->cipher->algorithm_enc == SSL_RC4)
- s->s3->need_record_splitting = 0;
- }
- }
-
- ret = 1;
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_cipher, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int tls1_change_cipher_state(SSL *s, int which) {
+ /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we
+ * need to update the read cipherspec. Otherwise we have just written one. */
+ const char is_read = (which & SSL3_CC_READ) != 0;
+ /* use_client_keys is true if we wish to use the keys for the "client write"
+ * direction. This is the case if we're a client sending a ChangeCipherSpec,
+ * or a server reading a client's ChangeCipherSpec. */
+ const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE ||
+ which == SSL3_CHANGE_CIPHER_SERVER_READ;
+ const uint8_t *client_write_mac_secret, *server_write_mac_secret, *mac_secret;
+ const uint8_t *client_write_key, *server_write_key, *key;
+ const uint8_t *client_write_iv, *server_write_iv, *iv;
+ const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
+ const EVP_AEAD *aead = s->s3->tmp.new_aead;
+ unsigned key_len, iv_len, mac_secret_len;
+ const uint8_t *key_data;
+
+ /* Reset sequence number to zero. */
+ if (!SSL_IS_DTLS(s)) {
+ memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8);
+ }
+
+ mac_secret_len = s->s3->tmp.new_mac_secret_size;
+
+ if (aead != NULL) {
+ key_len = EVP_AEAD_key_length(aead);
+ /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites)
+ * the key length reported by |EVP_AEAD_key_length| will include the MAC
+ * key bytes. */
+ if (key_len < mac_secret_len) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ key_len -= mac_secret_len;
+ iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->s3->tmp.new_cipher);
+ } else {
+ key_len = EVP_CIPHER_key_length(cipher);
+ iv_len = EVP_CIPHER_iv_length(cipher);
+ }
+
+ key_data = s->s3->tmp.key_block;
+ client_write_mac_secret = key_data;
+ key_data += mac_secret_len;
+ server_write_mac_secret = key_data;
+ key_data += mac_secret_len;
+ client_write_key = key_data;
+ key_data += key_len;
+ server_write_key = key_data;
+ key_data += key_len;
+ client_write_iv = key_data;
+ key_data += iv_len;
+ server_write_iv = key_data;
+ key_data += iv_len;
+
+ if (use_client_keys) {
+ mac_secret = client_write_mac_secret;
+ key = client_write_key;
+ iv = client_write_iv;
+ } else {
+ mac_secret = server_write_mac_secret;
+ key = server_write_key;
+ iv = server_write_iv;
+ }
+
+ if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (aead != NULL) {
+ if (!tls1_change_cipher_state_aead(s, is_read, key, key_len, iv, iv_len,
+ mac_secret, mac_secret_len)) {
+ return 0;
+ }
+ } else {
+ if (!tls1_change_cipher_state_cipher(s, is_read, use_client_keys,
+ mac_secret, mac_secret_len, key,
+ key_len, iv, iv_len)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int tls1_setup_key_block(SSL *s) {
+ uint8_t *p1, *p2 = NULL;
+ const EVP_CIPHER *c = NULL;
+ const EVP_MD *hash = NULL;
+ const EVP_AEAD *aead = NULL;
+ int num;
+ int mac_type = NID_undef, mac_secret_size = 0;
+ int ret = 0;
+ unsigned key_len, iv_len;
+
+
+ if (s->s3->tmp.key_block_length != 0) {
+ return 1;
+ }
+
+ if (s->session->cipher &&
+ ((s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) ||
+ (s->session->cipher->algorithm2 &
+ SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD))) {
+ if (!ssl_cipher_get_evp_aead(s->session, &aead)) {
+ goto cipher_unavailable_err;
+ }
+ key_len = EVP_AEAD_key_length(aead);
+ iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
+ if ((s->session->cipher->algorithm2 &
+ SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) &&
+ !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size)) {
+ goto cipher_unavailable_err;
+ }
+ /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites)
+ * the key length reported by |EVP_AEAD_key_length| will include the MAC
+ * key bytes. */
+ if (key_len < (size_t)mac_secret_size) {
+ OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ key_len -= mac_secret_size;
+ } else {
+ if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type,
+ &mac_secret_size)) {
+ goto cipher_unavailable_err;
+ }
+ key_len = EVP_CIPHER_key_length(c);
+ iv_len = EVP_CIPHER_iv_length(c);
+ }
+
+ s->s3->tmp.new_aead = aead;
+ s->s3->tmp.new_sym_enc = c;
+ s->s3->tmp.new_hash = hash;
+ s->s3->tmp.new_mac_pkey_type = mac_type;
+ s->s3->tmp.new_mac_secret_size = mac_secret_size;
+
+ num = key_len + mac_secret_size + iv_len;
+ num *= 2;
+
+ ssl3_cleanup_key_block(s);
+
+ p1 = (uint8_t *)OPENSSL_malloc(num);
+ if (p1 == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ s->s3->tmp.key_block_length = num;
+ s->s3->tmp.key_block = p1;
+
+ p2 = (uint8_t *)OPENSSL_malloc(num);
+ if (p2 == NULL) {
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!tls1_generate_key_block(s, p1, p2, num)) {
+ goto err;
+ }
+
+ if (!SSL_USE_EXPLICIT_IV(s) &&
+ (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0) {
+ /* enable vulnerability countermeasure for CBC ciphers with known-IV
+ * problem (http://www.openssl.org/~bodo/tls-cbc.txt). */
+ s->s3->need_record_splitting = 1;
+
+ if (s->session->cipher != NULL &&
+ s->session->cipher->algorithm_enc == SSL_RC4) {
+ s->s3->need_record_splitting = 0;
+ }
+ }
+
+ ret = 1;
+
err:
- if (p2)
- {
- OPENSSL_cleanse(p2,num);
- OPENSSL_free(p2);
- }
- return(ret);
+ if (p2) {
+ OPENSSL_cleanse(p2, num);
+ OPENSSL_free(p2);
+ }
+ return ret;
cipher_unavailable_err:
- OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
- return 0;
- }
+ OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block,
+ SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ return 0;
+}
-/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
+/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|,
+ * respectively.
*
* Returns:
* 0: (in non-constant time) if the record is publically invalid (i.e. too
* short etc).
* 1: if the record's padding is valid / the encryption was successful.
* -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
- * an internal error occured.
- */
-int tls1_enc(SSL *s, int send)
- {
- SSL3_RECORD *rec;
- EVP_CIPHER_CTX *ds;
- unsigned long l;
- int bs,i,j,k,pad=0,ret,mac_size=0;
- const EVP_CIPHER *enc;
- const SSL_AEAD_CTX *aead;
-
- if (send)
- rec = &s->s3->wrec;
- else
- rec = &s->s3->rrec;
-
- if (send)
- aead = s->aead_write_ctx;
- else
- aead = s->aead_read_ctx;
-
- if (aead)
- {
- unsigned char ad[13], *seq, *in, *out, nonce[16];
- unsigned nonce_used;
- size_t n;
-
- seq = send ? s->s3->write_sequence : s->s3->read_sequence;
-
- if (SSL_IS_DTLS(s))
- {
- unsigned char dtlsseq[9], *p = dtlsseq;
-
- s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p);
- memcpy(p, &seq[2], 6);
- memcpy(ad, dtlsseq, 8);
- }
- else
- {
- memcpy(ad, seq, 8);
- for (i=7; i>=0; i--) /* increment */
- {
- ++seq[i];
- if (seq[i] != 0)
- break;
- }
- }
-
- ad[8] = rec->type;
- ad[9] = (unsigned char)(s->version>>8);
- ad[10] = (unsigned char)(s->version);
-
- if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce) ||
- aead->variable_nonce_len > 8)
- return -1; /* internal error - should never happen. */
-
- memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
- nonce_used = aead->fixed_nonce_len;
-
- if (send)
- {
- size_t len = rec->length;
- size_t eivlen = 0;
- in = rec->input;
- out = rec->data;
-
- /* When sending we use the sequence number as the
- * variable part of the nonce. */
- if (aead->variable_nonce_len > 8)
- return -1;
- memcpy(nonce + nonce_used, ad, aead->variable_nonce_len);
- nonce_used += aead->variable_nonce_len;
-
- /* in do_ssl3_write, rec->input is moved forward by
- * variable_nonce_len in order to leave space for the
- * variable nonce. Thus we can copy the sequence number
- * bytes into place without overwriting any of the
- * plaintext. */
- if (aead->variable_nonce_included_in_record)
- {
- memcpy(out, ad, aead->variable_nonce_len);
- len -= aead->variable_nonce_len;
- eivlen = aead->variable_nonce_len;
- }
-
- ad[11] = len >> 8;
- ad[12] = len & 0xff;
-
- if (!EVP_AEAD_CTX_seal(
- &aead->ctx,
- out + eivlen, &n, len + aead->tag_len,
- nonce, nonce_used,
- in + eivlen, len,
- ad, sizeof(ad)))
- {
- return -1;
- }
- if (aead->variable_nonce_included_in_record)
- n += aead->variable_nonce_len;
- }
- else
- {
- /* receive */
- size_t len = rec->length;
-
- if (rec->data != rec->input)
- return -1; /* internal error - should never happen. */
- out = in = rec->input;
-
- if (len < aead->variable_nonce_len)
- return 0;
- memcpy(nonce + nonce_used,
- aead->variable_nonce_included_in_record ? in : ad,
- aead->variable_nonce_len);
- nonce_used += aead->variable_nonce_len;
-
- if (aead->variable_nonce_included_in_record)
- {
- in += aead->variable_nonce_len;
- len -= aead->variable_nonce_len;
- out += aead->variable_nonce_len;
- }
-
- if (len < aead->tag_len)
- return 0;
- len -= aead->tag_len;
-
- ad[11] = len >> 8;
- ad[12] = len & 0xff;
-
- if (!EVP_AEAD_CTX_open(
- &aead->ctx,
- out, &n, len,
- nonce, nonce_used,
- in, len + aead->tag_len,
- ad, sizeof(ad)))
- {
- return -1;
- }
-
- rec->data = rec->input = out;
- }
-
- rec->length = n;
- return 1;
- }
-
- if (send)
- {
- ds=s->enc_write_ctx;
- rec= &(s->s3->wrec);
- if (s->enc_write_ctx == NULL)
- enc=NULL;
- else
- {
- int ivlen;
- enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
- /* For TLSv1.1 and later explicit IV */
- if (SSL_USE_EXPLICIT_IV(s)
- && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
- ivlen = EVP_CIPHER_iv_length(enc);
- else
- ivlen = 0;
- if (ivlen > 1)
- {
- if ( rec->data != rec->input)
- /* we can't write into the input stream:
- * Can this ever happen?? (steve)
- */
- fprintf(stderr,
- "%s:%d: rec->data != rec->input\n",
- __FILE__, __LINE__);
- else if (!RAND_bytes(rec->input, ivlen))
- return -1;
- }
- }
- }
- else
- {
- ds=s->enc_read_ctx;
- rec= &(s->s3->rrec);
- if (s->enc_read_ctx == NULL)
- enc=NULL;
- else
- enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
- }
-
- if ((s->session == NULL) || (ds == NULL) || (enc == NULL))
- {
- memmove(rec->data,rec->input,rec->length);
- rec->input=rec->data;
- ret = 1;
- }
- else
- {
- l=rec->length;
- bs=EVP_CIPHER_block_size(ds->cipher);
-
- if ((bs != 1) && send)
- {
- i=bs-((int)l%bs);
-
- /* Add weird padding of upto 256 bytes */
-
- /* we need to add 'i' padding bytes of value j */
- j=i-1;
- for (k=(int)l; k<(int)(l+i); k++)
- rec->input[k]=j;
- l+=i;
- rec->length+=i;
- }
-
- if (!send)
- {
- if (l == 0 || l%bs != 0)
- return 0;
- }
-
- if (!EVP_Cipher(ds, rec->data, rec->input, l))
- return -1;
-
- ret = 1;
- if (EVP_MD_CTX_md(s->read_hash) != NULL)
- mac_size = EVP_MD_CTX_size(s->read_hash);
- if ((bs != 1) && !send)
- ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
- if (pad && !send)
- rec->length -= pad;
- }
- return ret;
- }
-
-int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
- {
- unsigned int ret;
- EVP_MD_CTX ctx, *d=NULL;
- int i;
-
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s, free_handshake_buffer))
- return 0;
-
- for (i=0;i<SSL_MAX_DIGEST;i++)
- {
- if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid)
- {
- d=s->s3->handshake_dgst[i];
- break;
- }
- }
- if (!d) {
- OPENSSL_PUT_ERROR(SSL, tls1_cert_verify_mac, SSL_R_NO_REQUIRED_DIGEST);
- return 0;
- }
-
- EVP_MD_CTX_init(&ctx);
- EVP_MD_CTX_copy_ex(&ctx,d);
- EVP_DigestFinal_ex(&ctx,out,&ret);
- EVP_MD_CTX_cleanup(&ctx);
- return((int)ret);
- }
+ * an internal error occured. */
+int tls1_enc(SSL *s, int send) {
+ SSL3_RECORD *rec;
+ EVP_CIPHER_CTX *ds;
+ unsigned long l;
+ int bs, i, j, k, pad = 0, ret, mac_size = 0;
+ const EVP_CIPHER *enc;
+ const SSL_AEAD_CTX *aead;
+
+ if (send) {
+ rec = &s->s3->wrec;
+ aead = s->aead_write_ctx;
+ } else {
+ rec = &s->s3->rrec;
+ aead = s->aead_read_ctx;
+ }
+
+ if (aead) {
+ uint8_t ad[13], *seq, *in, *out, nonce[16];
+ unsigned nonce_used;
+ size_t n;
+
+ seq = send ? s->s3->write_sequence : s->s3->read_sequence;
+
+ if (SSL_IS_DTLS(s)) {
+ uint8_t dtlsseq[9], *p = dtlsseq;
+
+ s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p);
+ memcpy(p, &seq[2], 6);
+ memcpy(ad, dtlsseq, 8);
+ } else {
+ memcpy(ad, seq, 8);
+ for (i = 7; i >= 0; i--) {
+ ++seq[i];
+ if (seq[i] != 0) {
+ break;
+ }
+ }
+ }
+
+ ad[8] = rec->type;
+ ad[9] = (uint8_t)(s->version >> 8);
+ ad[10] = (uint8_t)(s->version);
+
+ if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce) ||
+ aead->variable_nonce_len > 8) {
+ return -1; /* internal error - should never happen. */
+ }
+
+ memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+ nonce_used = aead->fixed_nonce_len;
+
+ if (send) {
+ size_t len = rec->length;
+ size_t eivlen = 0;
+ in = rec->input;
+ out = rec->data;
+
+ /* When sending we use the sequence number as the variable part of the
+ * nonce. */
+ if (aead->variable_nonce_len > 8) {
+ return -1;
+ }
+ memcpy(nonce + nonce_used, ad, aead->variable_nonce_len);
+ nonce_used += aead->variable_nonce_len;
+
+ /* in do_ssl3_write, rec->input is moved forward by variable_nonce_len in
+ * order to leave space for the variable nonce. Thus we can copy the
+ * sequence number bytes into place without overwriting any of the
+ * plaintext. */
+ if (aead->variable_nonce_included_in_record) {
+ memcpy(out, ad, aead->variable_nonce_len);
+ len -= aead->variable_nonce_len;
+ eivlen = aead->variable_nonce_len;
+ }
+
+ ad[11] = len >> 8;
+ ad[12] = len & 0xff;
+
+ if (!EVP_AEAD_CTX_seal(&aead->ctx, out + eivlen, &n, len + aead->tag_len,
+ nonce, nonce_used, in + eivlen, len, ad,
+ sizeof(ad))) {
+ return -1;
+ }
+
+ if (aead->variable_nonce_included_in_record) {
+ n += aead->variable_nonce_len;
+ }
+ } else {
+ /* receive */
+ size_t len = rec->length;
+
+ if (rec->data != rec->input) {
+ return -1; /* internal error - should never happen. */
+ }
+ out = in = rec->input;
+
+ if (len < aead->variable_nonce_len) {
+ return 0;
+ }
+ memcpy(nonce + nonce_used,
+ aead->variable_nonce_included_in_record ? in : ad,
+ aead->variable_nonce_len);
+ nonce_used += aead->variable_nonce_len;
+
+ if (aead->variable_nonce_included_in_record) {
+ in += aead->variable_nonce_len;
+ len -= aead->variable_nonce_len;
+ out += aead->variable_nonce_len;
+ }
+
+ if (len < aead->tag_len) {
+ return 0;
+ }
+ len -= aead->tag_len;
+
+ ad[11] = len >> 8;
+ ad[12] = len & 0xff;
+
+ if (!EVP_AEAD_CTX_open(&aead->ctx, out, &n, len, nonce, nonce_used, in,
+ len + aead->tag_len, ad, sizeof(ad))) {
+ return -1;
+ }
+
+ rec->data = rec->input = out;
+ }
+
+ rec->length = n;
+ return 1;
+ }
+
+ if (send) {
+ ds = s->enc_write_ctx;
+ rec = &(s->s3->wrec);
+ if (s->enc_write_ctx == NULL) {
+ enc = NULL;
+ } else {
+ int ivlen;
+ enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+ /* For TLSv1.1 and later explicit IV */
+ if (SSL_USE_EXPLICIT_IV(s) && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) {
+ ivlen = EVP_CIPHER_iv_length(enc);
+ } else {
+ ivlen = 0;
+ }
+
+ if (ivlen > 1) {
+ if (rec->data != rec->input) {
+ /* we can't write into the input stream:
+ * Can this ever happen?? (steve)
+ */
+ fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__,
+ __LINE__);
+ } else if (!RAND_bytes(rec->input, ivlen)) {
+ return -1;
+ }
+ }
+ }
+ } else {
+ ds = s->enc_read_ctx;
+ rec = &(s->s3->rrec);
+ if (s->enc_read_ctx == NULL) {
+ enc = NULL;
+ } else {
+ enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ }
+ }
+
+ if (s->session == NULL || ds == NULL || enc == NULL) {
+ memmove(rec->data, rec->input, rec->length);
+ rec->input = rec->data;
+ ret = 1;
+ } else {
+ l = rec->length;
+ bs = EVP_CIPHER_block_size(ds->cipher);
+
+ if (bs != 1 && send) {
+ i = bs - ((int)l % bs);
+
+ /* Add weird padding of upto 256 bytes */
+ /* we need to add 'i' padding bytes of value j */
+ j = i - 1;
+ for (k = (int)l; k < (int)(l + i); k++) {
+ rec->input[k] = j;
+ }
+ l += i;
+ rec->length += i;
+ }
+
+ if (!send && (l == 0 || l % bs != 0)) {
+ return 0;
+ }
+
+ if (!EVP_Cipher(ds, rec->data, rec->input, l)) {
+ return -1;
+ }
+
+ ret = 1;
+ if (EVP_MD_CTX_md(s->read_hash) != NULL) {
+ mac_size = EVP_MD_CTX_size(s->read_hash);
+ }
+
+ if (bs != 1 && !send) {
+ ret = tls1_cbc_remove_padding(s, rec, bs, mac_size);
+ }
+ if (pad && !send) {
+ rec->length -= pad;
+ }
+ }
+ return ret;
+}
+
+int tls1_cert_verify_mac(SSL *s, int md_nid, uint8_t *out) {
+ unsigned int ret;
+ EVP_MD_CTX ctx, *d = NULL;
+ int i;
+
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return 0;
+ }
+
+ for (i = 0; i < SSL_MAX_DIGEST; i++) {
+ if (s->s3->handshake_dgst[i] &&
+ EVP_MD_CTX_type(s->s3->handshake_dgst[i]) == md_nid) {
+ d = s->s3->handshake_dgst[i];
+ break;
+ }
+ }
+
+ if (!d) {
+ OPENSSL_PUT_ERROR(SSL, tls1_cert_verify_mac, SSL_R_NO_REQUIRED_DIGEST);
+ return 0;
+ }
+
+ EVP_MD_CTX_init(&ctx);
+ EVP_MD_CTX_copy_ex(&ctx, d);
+ EVP_DigestFinal_ex(&ctx, out, &ret);
+ EVP_MD_CTX_cleanup(&ctx);
+
+ return ret;
+}
/* tls1_handshake_digest calculates the current handshake hash and writes it to
* |out|, which has space for |out_len| bytes. It returns the number of bytes
* written or -1 in the event of an error. This function works on a copy of the
* underlying digests so can be called multiple times and prior to the final
* update etc. */
-int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len)
- {
- const EVP_MD *md;
- EVP_MD_CTX ctx;
- int i, err = 0, len = 0;
- long mask;
-
- EVP_MD_CTX_init(&ctx);
-
- for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++)
- {
- int hash_size;
- unsigned int digest_len;
- EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
-
- if ((mask & ssl_get_algorithm2(s)) == 0)
- continue;
-
- hash_size = EVP_MD_size(md);
- if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len)
- {
- err = 1;
- break;
- }
-
- if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
- !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
- digest_len != (unsigned int)hash_size) /* internal error */
- {
- err = 1;
- break;
- }
- out += digest_len;
- out_len -= digest_len;
- len += digest_len;
- }
-
- EVP_MD_CTX_cleanup(&ctx);
-
- if (err != 0)
- return -1;
- return len;
- }
-
-int tls1_final_finish_mac(SSL *s,
- const char *str, int slen, unsigned char *out)
- {
- unsigned char buf[2*EVP_MAX_MD_SIZE];
- unsigned char buf2[12];
- int err=0;
- int digests_len;
-
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s, free_handshake_buffer))
- return 0;
-
- digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
- if (digests_len < 0)
- {
- err = 1;
- digests_len = 0;
- }
-
- if (!tls1_PRF(ssl_get_algorithm2(s),
- str,slen, buf, digests_len, NULL,0,
- s->session->master_key,s->session->master_key_length,
- out,buf2,sizeof buf2))
- err = 1;
-
- if (err)
- return 0;
- else
- return sizeof buf2;
- }
-
-int tls1_mac(SSL *ssl, unsigned char *md, int send)
- {
- SSL3_RECORD *rec;
- unsigned char *seq;
- EVP_MD_CTX *hash;
- size_t md_size, orig_len;
- int i, ok;
- EVP_MD_CTX hmac, *mac_ctx;
- unsigned char header[13];
- int t;
-
- if (send)
- {
- rec= &(ssl->s3->wrec);
- seq= &(ssl->s3->write_sequence[0]);
- hash=ssl->write_hash;
- }
- else
- {
- rec= &(ssl->s3->rrec);
- seq= &(ssl->s3->read_sequence[0]);
- hash=ssl->read_hash;
- }
-
- t=EVP_MD_CTX_size(hash);
- assert(t >= 0);
- md_size=t;
-
- mac_ctx = &hmac;
- if (!EVP_MD_CTX_copy(mac_ctx, hash))
- return -1;
-
- if (SSL_IS_DTLS(ssl))
- {
- unsigned char dtlsseq[8],*p=dtlsseq;
-
- s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
- memcpy (p,&seq[2],6);
-
- memcpy(header, dtlsseq, 8);
- }
- else
- memcpy(header, seq, 8);
-
- /* kludge: tls1_cbc_remove_padding passes padding length in rec->type */
- orig_len = rec->length+md_size+((unsigned int)rec->type>>8);
- rec->type &= 0xff;
-
- header[8]=rec->type;
- header[9]=(unsigned char)(ssl->version>>8);
- header[10]=(unsigned char)(ssl->version);
- header[11]=(rec->length)>>8;
- header[12]=(rec->length)&0xff;
-
- if (!send &&
- EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- ssl3_cbc_record_digest_supported(mac_ctx))
- {
- /* This is a CBC-encrypted record. We must avoid leaking any
- * timing-side channel information about how many blocks of
- * data we are hashing because that gives an attacker a
- * timing-oracle. */
- ok = ssl3_cbc_digest_record(
- mac_ctx,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, orig_len,
- ssl->s3->read_mac_secret,
- ssl->s3->read_mac_secret_size,
- 0 /* not SSLv3 */);
- }
- else
- {
- EVP_DigestSignUpdate(mac_ctx,header,sizeof(header));
- EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
- ok = EVP_DigestSignFinal(mac_ctx,md,&md_size);
- }
-
- EVP_MD_CTX_cleanup(mac_ctx);
-
- if (!ok)
- return -1;
-
- if (!SSL_IS_DTLS(ssl))
- {
- for (i=7; i>=0; i--)
- {
- ++seq[i];
- if (seq[i] != 0) break;
- }
- }
-
- return md_size;
- }
-
-int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
- int len)
- {
- unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
-
- if (s->s3->tmp.extended_master_secret)
- {
- uint8_t digests[2*EVP_MAX_MD_SIZE];
- int digests_len;
-
- if (s->s3->handshake_buffer)
- {
- /* The master secret is based on the handshake hash
- * just after sending the ClientKeyExchange. However,
- * we might have a client certificate to send, in which
- * case we might need different hashes for the
- * verification and thus still need the handshake
- * buffer around. Keeping both a handshake buffer *and*
- * running hashes isn't yet supported so, when it comes
- * to calculating the Finished hash, we'll have to hash
- * the handshake buffer again. */
- if (!ssl3_digest_cached_records(s, dont_free_handshake_buffer))
- return 0;
- }
-
- digests_len = tls1_handshake_digest(s, digests, sizeof(digests));
-
- if (digests_len == -1)
- {
- return 0;
- }
-
- tls1_PRF(ssl_get_algorithm2(s),
- TLS_MD_EXTENDED_MASTER_SECRET_CONST,
- TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
- digests, digests_len,
- NULL, 0,
- p, len,
- s->session->master_key,
- buff, sizeof(buff));
- }
- else
- {
- tls1_PRF(ssl_get_algorithm2(s),
- TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
- s->s3->client_random,SSL3_RANDOM_SIZE,
- s->s3->server_random,SSL3_RANDOM_SIZE,
- p, len,
- s->session->master_key,buff,sizeof buff);
- }
-
-#ifdef SSL_DEBUG
- fprintf(stderr, "Premaster Secret:\n");
- BIO_dump_fp(stderr, (char *)p, len);
- fprintf(stderr, "Client Random:\n");
- BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
- fprintf(stderr, "Server Random:\n");
- BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
- fprintf(stderr, "Master Secret:\n");
- BIO_dump_fp(stderr, (char *)s->session->master_key, SSL3_MASTER_SECRET_SIZE);
-#endif
-
-#ifdef OPENSSL_SSL_TRACE_CRYPTO
- if (s->msg_callback)
- {
- s->msg_callback(2, s->version, TLS1_RT_CRYPTO_PREMASTER,
- p, len, s, s->msg_callback_arg);
- s->msg_callback(2, s->version, TLS1_RT_CRYPTO_CLIENT_RANDOM,
- s->s3->client_random, SSL3_RANDOM_SIZE,
- s, s->msg_callback_arg);
- s->msg_callback(2, s->version, TLS1_RT_CRYPTO_SERVER_RANDOM,
- s->s3->server_random, SSL3_RANDOM_SIZE,
- s, s->msg_callback_arg);
- s->msg_callback(2, s->version, TLS1_RT_CRYPTO_MASTER,
- s->session->master_key,
- SSL3_MASTER_SECRET_SIZE,
- s, s->msg_callback_arg);
- }
-#endif
-
- return(SSL3_MASTER_SECRET_SIZE);
- }
-
-int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
- const char *label, size_t llen, const unsigned char *context,
- size_t contextlen, int use_context)
- {
- unsigned char *buff;
- unsigned char *val = NULL;
- size_t vallen, currentvalpos;
- int rv;
-
- buff = OPENSSL_malloc(olen);
- if (buff == NULL) goto err2;
-
- /* construct PRF arguments
- * we construct the PRF argument ourself rather than passing separate
- * values into the TLS PRF to ensure that the concatenation of values
- * does not create a prohibited label.
- */
- vallen = llen + SSL3_RANDOM_SIZE * 2;
- if (use_context)
- {
- vallen += 2 + contextlen;
- }
-
- val = OPENSSL_malloc(vallen);
- if (val == NULL) goto err2;
- currentvalpos = 0;
- memcpy(val + currentvalpos, (unsigned char *) label, llen);
- currentvalpos += llen;
- memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
- currentvalpos += SSL3_RANDOM_SIZE;
- memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
- currentvalpos += SSL3_RANDOM_SIZE;
-
- if (use_context)
- {
- val[currentvalpos] = (contextlen >> 8) & 0xff;
- currentvalpos++;
- val[currentvalpos] = contextlen & 0xff;
- currentvalpos++;
- if ((contextlen > 0) || (context != NULL))
- {
- memcpy(val + currentvalpos, context, contextlen);
- }
- }
-
- /* disallow prohibited labels
- * note that SSL3_RANDOM_SIZE > max(prohibited label len) =
- * 15, so size of val > max(prohibited label len) = 15 and the
- * comparisons won't have buffer overflow
- */
- if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
- TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1;
- if (memcmp(val, TLS_MD_SERVER_FINISH_CONST,
- TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1;
- if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
- TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1;
- if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
- TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1;
-
- rv = tls1_PRF(ssl_get_algorithm2(s),
- val, vallen,
- NULL, 0,
- NULL, 0,
- s->session->master_key,s->session->master_key_length,
- out,buff,olen);
-
- goto ret;
+int tls1_handshake_digest(SSL *s, uint8_t *out, size_t out_len) {
+ const EVP_MD *md;
+ EVP_MD_CTX ctx;
+ int i, err = 0, len = 0;
+ long mask;
+
+ EVP_MD_CTX_init(&ctx);
+
+ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) {
+ int hash_size;
+ unsigned int digest_len;
+ EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
+
+ if ((mask & ssl_get_algorithm2(s)) == 0) {
+ continue;
+ }
+
+ hash_size = EVP_MD_size(md);
+ if (!hdgst ||
+ hash_size < 0 ||
+ (size_t)hash_size > out_len ||
+ !EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
+ !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
+ digest_len != (unsigned int)hash_size /* internal error */) {
+ err = 1;
+ break;
+ }
+
+ out += digest_len;
+ out_len -= digest_len;
+ len += digest_len;
+ }
+
+ EVP_MD_CTX_cleanup(&ctx);
+
+ if (err != 0) {
+ return -1;
+ }
+ return len;
+}
+
+int tls1_final_finish_mac(SSL *s, const char *str, int slen, uint8_t *out) {
+ uint8_t buf[2 * EVP_MAX_MD_SIZE];
+ uint8_t buf2[12];
+ int err = 0;
+ int digests_len;
+
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ return 0;
+ }
+
+ digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
+ if (digests_len < 0) {
+ err = 1;
+ digests_len = 0;
+ }
+
+ if (!tls1_PRF(ssl_get_algorithm2(s), str, slen, buf, digests_len, NULL, 0,
+ s->session->master_key, s->session->master_key_length, out,
+ buf2, sizeof buf2)) {
+ err = 1;
+ }
+
+ if (err) {
+ return 0;
+ } else {
+ return sizeof(buf2);
+ }
+}
+
+int tls1_mac(SSL *ssl, uint8_t *md, int send) {
+ SSL3_RECORD *rec;
+ uint8_t *seq;
+ EVP_MD_CTX *hash;
+ size_t md_size, orig_len;
+ int i, ok;
+ EVP_MD_CTX hmac, *mac_ctx;
+ uint8_t header[13];
+ int t;
+
+ if (send) {
+ rec = &ssl->s3->wrec;
+ seq = &ssl->s3->write_sequence[0];
+ hash = ssl->write_hash;
+ } else {
+ rec = &ssl->s3->rrec;
+ seq = &ssl->s3->read_sequence[0];
+ hash = ssl->read_hash;
+ }
+
+ t = EVP_MD_CTX_size(hash);
+ assert(t >= 0);
+ md_size = t;
+
+ mac_ctx = &hmac;
+ if (!EVP_MD_CTX_copy(mac_ctx, hash)) {
+ return -1;
+ }
+
+ if (SSL_IS_DTLS(ssl)) {
+ uint8_t dtlsseq[8], *p = dtlsseq;
+
+ s2n(send ? ssl->d1->w_epoch : ssl->d1->r_epoch, p);
+ memcpy(p, &seq[2], 6);
+
+ memcpy(header, dtlsseq, 8);
+ } else {
+ memcpy(header, seq, 8);
+ }
+
+ /* kludge: tls1_cbc_remove_padding passes padding length in rec->type */
+ orig_len = rec->length + md_size + ((unsigned int)rec->type >> 8);
+ rec->type &= 0xff;
+
+ header[8] = rec->type;
+ header[9] = (uint8_t)(ssl->version >> 8);
+ header[10] = (uint8_t)(ssl->version);
+ header[11] = (rec->length) >> 8;
+ header[12] = (rec->length) & 0xff;
+
+ if (!send && EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
+ ssl3_cbc_record_digest_supported(mac_ctx)) {
+ /* This is a CBC-encrypted record. We must avoid leaking any timing-side
+ * channel information about how many blocks of data we are hashing because
+ * that gives an attacker a timing-oracle. */
+ ok = ssl3_cbc_digest_record(
+ mac_ctx, md, &md_size, header, rec->input, rec->length + md_size,
+ orig_len, ssl->s3->read_mac_secret, ssl->s3->read_mac_secret_size,
+ 0 /* not SSLv3 */);
+ } else {
+ EVP_DigestSignUpdate(mac_ctx, header, sizeof(header));
+ EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length);
+ ok = EVP_DigestSignFinal(mac_ctx, md, &md_size);
+ }
+
+ EVP_MD_CTX_cleanup(mac_ctx);
+
+ if (!ok) {
+ return -1;
+ }
+
+ if (!SSL_IS_DTLS(ssl)) {
+ for (i = 7; i >= 0; i--) {
+ ++seq[i];
+ if (seq[i] != 0) {
+ break;
+ }
+ }
+ }
+
+ return md_size;
+}
+
+int tls1_generate_master_secret(SSL *s, uint8_t *out, uint8_t *p, int len) {
+ uint8_t buff[SSL_MAX_MASTER_KEY_LENGTH];
+
+ if (s->s3->tmp.extended_master_secret) {
+ uint8_t digests[2 * EVP_MAX_MD_SIZE];
+ int digests_len;
+
+ /* The master secret is based on the handshake hash just after sending the
+ * ClientKeyExchange. However, we might have a client certificate to send,
+ * in which case we might need different hashes for the verification and
+ * thus still need the handshake buffer around. Keeping both a handshake
+ * buffer *and* running hashes isn't yet supported so, when it comes to
+ * calculating the Finished hash, we'll have to hash the handshake buffer
+ * again. */
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, dont_free_handshake_buffer)) {
+ return 0;
+ }
+
+ digests_len = tls1_handshake_digest(s, digests, sizeof(digests));
+
+ if (digests_len == -1) {
+ return 0;
+ }
+
+ tls1_PRF(ssl_get_algorithm2(s), TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests, digests_len,
+ NULL, 0, p, len, s->session->master_key, buff, sizeof(buff));
+ } else {
+ tls1_PRF(ssl_get_algorithm2(s), TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE, s->s3->client_random,
+ SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE, p, len,
+ s->session->master_key, buff, sizeof buff);
+ }
+
+ return SSL3_MASTER_SECRET_SIZE;
+}
+
+int tls1_export_keying_material(SSL *s, uint8_t *out, size_t olen,
+ const char *label, size_t llen,
+ const uint8_t *context, size_t contextlen,
+ int use_context) {
+ uint8_t *buff;
+ uint8_t *val = NULL;
+ size_t vallen, currentvalpos;
+ int ret;
+
+ buff = OPENSSL_malloc(olen);
+ if (buff == NULL) {
+ goto err2;
+ }
+
+ /* construct PRF arguments we construct the PRF argument ourself rather than
+ * passing separate values into the TLS PRF to ensure that the concatenation
+ * of values does not create a prohibited label. */
+ vallen = llen + SSL3_RANDOM_SIZE * 2;
+ if (use_context) {
+ vallen += 2 + contextlen;
+ }
+
+ val = OPENSSL_malloc(vallen);
+ if (val == NULL) {
+ goto err2;
+ }
+
+ currentvalpos = 0;
+ memcpy(val + currentvalpos, (uint8_t *)label, llen);
+ currentvalpos += llen;
+ memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+ memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
+ currentvalpos += SSL3_RANDOM_SIZE;
+
+ if (use_context) {
+ val[currentvalpos] = (contextlen >> 8) & 0xff;
+ currentvalpos++;
+ val[currentvalpos] = contextlen & 0xff;
+ currentvalpos++;
+ if (contextlen > 0 || context != NULL) {
+ memcpy(val + currentvalpos, context, contextlen);
+ }
+ }
+
+ /* disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited
+ * label len) = 15, so size of val > max(prohibited label len) = 15 and the
+ * comparisons won't have buffer overflow. */
+ if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
+ TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0 ||
+ memcmp(val, TLS_MD_SERVER_FINISH_CONST,
+ TLS_MD_SERVER_FINISH_CONST_SIZE) == 0 ||
+ memcmp(val, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE) == 0 ||
+ memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) {
+ goto err1;
+ }
+
+ ret = tls1_PRF(ssl_get_algorithm2(s), val, vallen, NULL, 0, NULL, 0,
+ s->session->master_key, s->session->master_key_length, out,
+ buff, olen);
+
+ goto out;
+
err1:
- OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
- rv = 0;
- goto ret;
+ OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material,
+ SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ ret = 0;
+ goto out;
+
err2:
- OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, ERR_R_MALLOC_FAILURE);
- rv = 0;
-ret:
- if (buff != NULL) OPENSSL_free(buff);
- if (val != NULL) OPENSSL_free(val);
- return(rv);
- }
-
-int tls1_alert_code(int code)
- {
- switch (code)
- {
- case SSL_AD_CLOSE_NOTIFY: return(SSL3_AD_CLOSE_NOTIFY);
- case SSL_AD_UNEXPECTED_MESSAGE: return(SSL3_AD_UNEXPECTED_MESSAGE);
- case SSL_AD_BAD_RECORD_MAC: return(SSL3_AD_BAD_RECORD_MAC);
- case SSL_AD_DECRYPTION_FAILED: return(TLS1_AD_DECRYPTION_FAILED);
- case SSL_AD_RECORD_OVERFLOW: return(TLS1_AD_RECORD_OVERFLOW);
- case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE);
- case SSL_AD_HANDSHAKE_FAILURE: return(SSL3_AD_HANDSHAKE_FAILURE);
- case SSL_AD_NO_CERTIFICATE: return(-1);
- case SSL_AD_BAD_CERTIFICATE: return(SSL3_AD_BAD_CERTIFICATE);
- case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE);
- case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED);
- case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED);
- case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN);
- case SSL_AD_ILLEGAL_PARAMETER: return(SSL3_AD_ILLEGAL_PARAMETER);
- case SSL_AD_UNKNOWN_CA: return(TLS1_AD_UNKNOWN_CA);
- case SSL_AD_ACCESS_DENIED: return(TLS1_AD_ACCESS_DENIED);
- case SSL_AD_DECODE_ERROR: return(TLS1_AD_DECODE_ERROR);
- case SSL_AD_DECRYPT_ERROR: return(TLS1_AD_DECRYPT_ERROR);
- case SSL_AD_EXPORT_RESTRICTION: return(TLS1_AD_EXPORT_RESTRICTION);
- case SSL_AD_PROTOCOL_VERSION: return(TLS1_AD_PROTOCOL_VERSION);
- case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY);
- case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR);
- case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED);
- case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION);
- case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION);
- case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE);
- case SSL_AD_UNRECOGNIZED_NAME: return(TLS1_AD_UNRECOGNIZED_NAME);
- case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
- case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
- case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
- case SSL_AD_INAPPROPRIATE_FALLBACK:return(SSL3_AD_INAPPROPRIATE_FALLBACK);
- default: return(-1);
- }
- }
+ OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, ERR_R_MALLOC_FAILURE);
+ ret = 0;
+
+out:
+ if (buff != NULL) {
+ OPENSSL_free(buff);
+ }
+ if (val != NULL) {
+ OPENSSL_free(val);
+ }
+
+ return ret;
+}
+
+int tls1_alert_code(int code) {
+ switch (code) {
+ case SSL_AD_CLOSE_NOTIFY:
+ return SSL3_AD_CLOSE_NOTIFY;
+
+ case SSL_AD_UNEXPECTED_MESSAGE:
+ return SSL3_AD_UNEXPECTED_MESSAGE;
+
+ case SSL_AD_BAD_RECORD_MAC:
+ return SSL3_AD_BAD_RECORD_MAC;
+
+ case SSL_AD_DECRYPTION_FAILED:
+ return TLS1_AD_DECRYPTION_FAILED;
+
+ case SSL_AD_RECORD_OVERFLOW:
+ return TLS1_AD_RECORD_OVERFLOW;
+
+ case SSL_AD_DECOMPRESSION_FAILURE:
+ return SSL3_AD_DECOMPRESSION_FAILURE;
+
+ case SSL_AD_HANDSHAKE_FAILURE:
+ return SSL3_AD_HANDSHAKE_FAILURE;
+
+ case SSL_AD_NO_CERTIFICATE:
+ return -1;
+
+ case SSL_AD_BAD_CERTIFICATE:
+ return SSL3_AD_BAD_CERTIFICATE;
+
+ case SSL_AD_UNSUPPORTED_CERTIFICATE:
+ return SSL3_AD_UNSUPPORTED_CERTIFICATE;
+
+ case SSL_AD_CERTIFICATE_REVOKED:
+ return SSL3_AD_CERTIFICATE_REVOKED;
+
+ case SSL_AD_CERTIFICATE_EXPIRED:
+ return SSL3_AD_CERTIFICATE_EXPIRED;
+
+ case SSL_AD_CERTIFICATE_UNKNOWN:
+ return SSL3_AD_CERTIFICATE_UNKNOWN;
+
+ case SSL_AD_ILLEGAL_PARAMETER:
+ return SSL3_AD_ILLEGAL_PARAMETER;
+
+ case SSL_AD_UNKNOWN_CA:
+ return TLS1_AD_UNKNOWN_CA;
+
+ case SSL_AD_ACCESS_DENIED:
+ return TLS1_AD_ACCESS_DENIED;
+
+ case SSL_AD_DECODE_ERROR:
+ return TLS1_AD_DECODE_ERROR;
+
+ case SSL_AD_DECRYPT_ERROR:
+ return TLS1_AD_DECRYPT_ERROR;
+ case SSL_AD_EXPORT_RESTRICTION:
+ return TLS1_AD_EXPORT_RESTRICTION;
+
+ case SSL_AD_PROTOCOL_VERSION:
+ return TLS1_AD_PROTOCOL_VERSION;
+
+ case SSL_AD_INSUFFICIENT_SECURITY:
+ return TLS1_AD_INSUFFICIENT_SECURITY;
+
+ case SSL_AD_INTERNAL_ERROR:
+ return TLS1_AD_INTERNAL_ERROR;
+
+ case SSL_AD_USER_CANCELLED:
+ return TLS1_AD_USER_CANCELLED;
+
+ case SSL_AD_NO_RENEGOTIATION:
+ return TLS1_AD_NO_RENEGOTIATION;
+
+ case SSL_AD_UNSUPPORTED_EXTENSION:
+ return TLS1_AD_UNSUPPORTED_EXTENSION;
+
+ case SSL_AD_CERTIFICATE_UNOBTAINABLE:
+ return TLS1_AD_CERTIFICATE_UNOBTAINABLE;
+
+ case SSL_AD_UNRECOGNIZED_NAME:
+ return TLS1_AD_UNRECOGNIZED_NAME;
+
+ case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
+ return TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+
+ case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
+ return TLS1_AD_BAD_CERTIFICATE_HASH_VALUE;
+
+ case SSL_AD_UNKNOWN_PSK_IDENTITY:
+ return TLS1_AD_UNKNOWN_PSK_IDENTITY;
+
+ case SSL_AD_INAPPROPRIATE_FALLBACK:
+ return SSL3_AD_INAPPROPRIATE_FALLBACK;
+
+ default:
+ return -1;
+ }
+}