X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_enc.c;h=b801d0541bfd330ecc2d0a12b234430ccec1ff0a;hp=83a576ad1a9f319893f8ebc4980d317719d43873;hb=6938c954b072c1ddddeb0ec9f6a151df0d2cd925;hpb=c9dd49a751d4e73e6d891c006bb1d835ebfb8493 diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 83a576ad1a..b801d0541b 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -206,7 +206,7 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) km += MD5_DIGEST_LENGTH; } - OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH); + OPENSSL_cleanse(smd, sizeof(smd)); EVP_MD_CTX_cleanup(&m5); EVP_MD_CTX_cleanup(&s1); return 1; @@ -244,7 +244,7 @@ int ssl3_change_cipher_state(SSL *s, int which) if (s->enc_read_ctx != NULL) reuse_dd = 1; else if ((s->enc_read_ctx = - OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) + OPENSSL_malloc(sizeof(*s->enc_read_ctx))) == NULL) goto err; else /* @@ -253,13 +253,14 @@ int ssl3_change_cipher_state(SSL *s, int which) EVP_CIPHER_CTX_init(s->enc_read_ctx); dd = s->enc_read_ctx; - ssl_replace_hash(&s->read_hash, m); + if (ssl_replace_hash(&s->read_hash, m) == NULL) { + SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); + goto err2; + } #ifndef OPENSSL_NO_COMP /* COMPRESS */ - if (s->expand != NULL) { - COMP_CTX_free(s->expand); - s->expand = NULL; - } + COMP_CTX_free(s->expand); + s->expand = NULL; if (comp != NULL) { s->expand = COMP_CTX_new(comp); if (s->expand == NULL) { @@ -267,20 +268,17 @@ int ssl3_change_cipher_state(SSL *s, int which) SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } - if (s->s3->rrec.comp == NULL) - s->s3->rrec.comp = (unsigned char *) - OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH); - if (s->s3->rrec.comp == NULL) + if (!RECORD_LAYER_setup_comp_buffer(&s->rlayer)) goto err; } #endif - memset(&(s->s3->read_sequence[0]), 0, 8); + RECORD_LAYER_reset_read_sequence(&s->rlayer); mac_secret = &(s->s3->read_mac_secret[0]); } else { if (s->enc_write_ctx != NULL) reuse_dd = 1; else if ((s->enc_write_ctx = - OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) + OPENSSL_malloc(sizeof(*s->enc_write_ctx))) == NULL) goto err; else /* @@ -288,13 +286,14 @@ int ssl3_change_cipher_state(SSL *s, int which) */ EVP_CIPHER_CTX_init(s->enc_write_ctx); dd = s->enc_write_ctx; - ssl_replace_hash(&s->write_hash, m); + if (ssl_replace_hash(&s->write_hash, m) == NULL) { + SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); + goto err2; + } #ifndef OPENSSL_NO_COMP /* COMPRESS */ - if (s->compress != NULL) { - COMP_CTX_free(s->compress); - s->compress = NULL; - } + COMP_CTX_free(s->compress); + s->compress = NULL; if (comp != NULL) { s->compress = COMP_CTX_new(comp); if (s->compress == NULL) { @@ -304,7 +303,7 @@ int ssl3_change_cipher_state(SSL *s, int which) } } #endif - memset(&(s->s3->write_sequence[0]), 0, 8); + RECORD_LAYER_reset_write_sequence(&s->rlayer); mac_secret = &(s->s3->write_mac_secret[0]); } @@ -389,13 +388,15 @@ int ssl3_change_cipher_state(SSL *s, int which) } #endif - OPENSSL_cleanse(&(exp_key[0]), sizeof(exp_key)); - OPENSSL_cleanse(&(exp_iv[0]), sizeof(exp_iv)); + OPENSSL_cleanse(exp_key, sizeof(exp_key)); + OPENSSL_cleanse(exp_iv, sizeof(exp_iv)); EVP_MD_CTX_cleanup(&md); return (1); err: SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); err2: + OPENSSL_cleanse(exp_key, sizeof(exp_key)); + OPENSSL_cleanse(exp_iv, sizeof(exp_iv)); return (0); } @@ -468,101 +469,28 @@ int ssl3_setup_key_block(SSL *s) void ssl3_cleanup_key_block(SSL *s) { - if (s->s3->tmp.key_block != NULL) { - OPENSSL_cleanse(s->s3->tmp.key_block, s->s3->tmp.key_block_length); - OPENSSL_free(s->s3->tmp.key_block); - s->s3->tmp.key_block = NULL; - } + OPENSSL_clear_free(s->s3->tmp.key_block, s->s3->tmp.key_block_length); + s->s3->tmp.key_block = NULL; s->s3->tmp.key_block_length = 0; } -/*- - * ssl3_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 is invalid or, if sending, an internal error - * occurred. - */ -int ssl3_enc(SSL *s, int send) -{ - SSL3_RECORD *rec; - EVP_CIPHER_CTX *ds; - unsigned long l; - int bs, i, mac_size = 0; - const EVP_CIPHER *enc; - - if (send) { - ds = s->enc_write_ctx; - rec = &(s->s3->wrec); - if (s->enc_write_ctx == NULL) - enc = NULL; - else - enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); - } 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; - } else { - l = rec->length; - bs = EVP_CIPHER_block_size(ds->cipher); - - /* COMPRESS */ - - if ((bs != 1) && send) { - i = bs - ((int)l % bs); - - /* we need to add 'i-1' padding bytes */ - l += i; - /* - * the last of these zero bytes will be overwritten with the - * padding length. - */ - memset(&rec->input[rec->length], 0, i); - rec->length += i; - rec->input[l - 1] = (i - 1); - } - - if (!send) { - if (l == 0 || l % bs != 0) - return 0; - /* otherwise, rec->length >= bs */ - } - - if (EVP_Cipher(ds, rec->data, rec->input, l) < 1) - return -1; - - if (EVP_MD_CTX_md(s->read_hash) != NULL) - mac_size = EVP_MD_CTX_size(s->read_hash); - if ((bs != 1) && !send) - return ssl3_cbc_remove_padding(s, rec, bs, mac_size); - } - return (1); -} - void ssl3_init_finished_mac(SSL *s) { - if (s->s3->handshake_buffer) - BIO_free(s->s3->handshake_buffer); - if (s->s3->handshake_dgst) - ssl3_free_digest_list(s); + ssl3_free_digest_list(s); s->s3->handshake_buffer = BIO_new(BIO_s_mem()); (void)BIO_set_close(s->s3->handshake_buffer, BIO_CLOSE); } +/* + * Free digest list. Also frees handshake buffer since they are always freed + * together. + */ + void ssl3_free_digest_list(SSL *s) { int i; + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; if (!s->s3->handshake_dgst) return; for (i = 0; i < SSL_MAX_DIGEST; i++) { @@ -575,8 +503,7 @@ void ssl3_free_digest_list(SSL *s) void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len) { - if (s->s3->handshake_buffer - && !(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { + if (s->s3->handshake_dgst == NULL) { BIO_write(s->s3->handshake_buffer, (void *)buf, len); } else { int i; @@ -587,7 +514,7 @@ void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len) } } -int ssl3_digest_cached_records(SSL *s) +int ssl3_digest_cached_records(SSL *s, int keep) { int i; long mask; @@ -595,37 +522,37 @@ int ssl3_digest_cached_records(SSL *s) long hdatalen; void *hdata; - /* Allocate handshake_dgst array */ - ssl3_free_digest_list(s); - s->s3->handshake_dgst = - OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); if (s->s3->handshake_dgst == NULL) { - SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE); - return 0; - } - memset(s->s3->handshake_dgst, 0, SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); - hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); - if (hdatalen <= 0) { - SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); - return 0; - } + /* Allocate handshake_dgst array */ + s->s3->handshake_dgst = + OPENSSL_malloc(sizeof(*s->s3->handshake_dgst) * SSL_MAX_DIGEST); + if (s->s3->handshake_dgst == NULL) { + SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE); + return 0; + } + hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); + if (hdatalen <= 0) { + SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); + return 0; + } - /* Loop through bitso of algorithm2 field and create MD_CTX-es */ - for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) { - if ((mask & ssl_get_algorithm2(s)) && md) { - s->s3->handshake_dgst[i] = EVP_MD_CTX_create(); - if (EVP_MD_nid(md) == NID_md5) { - EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i], - EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + /* Loop through bits of algorithm2 field and create MD_CTX-es */ + for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) { + if ((mask & ssl_get_algorithm2(s)) && md) { + s->s3->handshake_dgst[i] = EVP_MD_CTX_create(); + if (EVP_MD_nid(md) == NID_md5) { + EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i], + EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + } + EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL); + EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen); + } else { + s->s3->handshake_dgst[i] = NULL; } - EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL); - EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen); - } else { - s->s3->handshake_dgst[i] = NULL; } + } - if (!(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { - /* Free handshake_buffer BIO */ + if (keep == 0) { BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; } @@ -633,11 +560,6 @@ int ssl3_digest_cached_records(SSL *s) return 1; } -int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p) -{ - return (ssl3_handshake_mac(s, md_nid, NULL, 0, p)); -} - int ssl3_final_finish_mac(SSL *s, const char *sender, int len, unsigned char *p) { @@ -665,9 +587,8 @@ static int ssl3_handshake_mac(SSL *s, int md_nid, unsigned char md_buf[EVP_MAX_MD_SIZE]; EVP_MD_CTX ctx, *d = NULL; - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s)) - return 0; + if (!ssl3_digest_cached_records(s, 0)) + return 0; /* * Search for digest of specified type in the handshake_dgst array @@ -691,131 +612,27 @@ static int ssl3_handshake_mac(SSL *s, int md_nid, return 0; npad = (48 / n) * n; - if (sender != NULL) - EVP_DigestUpdate(&ctx, sender, len); - EVP_DigestUpdate(&ctx, s->session->master_key, - s->session->master_key_length); - EVP_DigestUpdate(&ctx, ssl3_pad_1, npad); - EVP_DigestFinal_ex(&ctx, md_buf, &i); - - EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL); - EVP_DigestUpdate(&ctx, s->session->master_key, - s->session->master_key_length); - EVP_DigestUpdate(&ctx, ssl3_pad_2, npad); - EVP_DigestUpdate(&ctx, md_buf, i); - EVP_DigestFinal_ex(&ctx, p, &ret); + if ((sender != NULL && EVP_DigestUpdate(&ctx, sender, len) <= 0) + || EVP_DigestUpdate(&ctx, s->session->master_key, + s->session->master_key_length) <= 0 + || EVP_DigestUpdate(&ctx, ssl3_pad_1, npad) <= 0 + || EVP_DigestFinal_ex(&ctx, md_buf, &i) <= 0 + + || EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL) <= 0 + || EVP_DigestUpdate(&ctx, s->session->master_key, + s->session->master_key_length) <= 0 + || EVP_DigestUpdate(&ctx, ssl3_pad_2, npad) <= 0 + || EVP_DigestUpdate(&ctx, md_buf, i) <= 0 + || EVP_DigestFinal_ex(&ctx, p, &ret) <= 0) { + SSLerr(SSL_F_SSL3_HANDSHAKE_MAC, ERR_R_INTERNAL_ERROR); + ret = 0; + } EVP_MD_CTX_cleanup(&ctx); return ((int)ret); } -int n_ssl3_mac(SSL *ssl, unsigned char *md, int send) -{ - SSL3_RECORD *rec; - unsigned char *mac_sec, *seq; - EVP_MD_CTX md_ctx; - const EVP_MD_CTX *hash; - unsigned char *p, rec_char; - size_t md_size; - int npad; - int t; - - if (send) { - rec = &(ssl->s3->wrec); - mac_sec = &(ssl->s3->write_mac_secret[0]); - seq = &(ssl->s3->write_sequence[0]); - hash = ssl->write_hash; - } else { - rec = &(ssl->s3->rrec); - mac_sec = &(ssl->s3->read_mac_secret[0]); - seq = &(ssl->s3->read_sequence[0]); - hash = ssl->read_hash; - } - - t = EVP_MD_CTX_size(hash); - if (t < 0) - return -1; - md_size = t; - npad = (48 / md_size) * md_size; - - if (!send && - EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && - ssl3_cbc_record_digest_supported(hash)) { - /* - * 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. - */ - - /*- - * npad is, at most, 48 bytes and that's with MD5: - * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. - * - * With SHA-1 (the largest hash speced for SSLv3) the hash size - * goes up 4, but npad goes down by 8, resulting in a smaller - * total size. - */ - unsigned char header[75]; - unsigned j = 0; - memcpy(header + j, mac_sec, md_size); - j += md_size; - memcpy(header + j, ssl3_pad_1, npad); - j += npad; - memcpy(header + j, seq, 8); - j += 8; - header[j++] = rec->type; - header[j++] = rec->length >> 8; - header[j++] = rec->length & 0xff; - - /* Final param == is SSLv3 */ - ssl3_cbc_digest_record(hash, - md, &md_size, - header, rec->input, - rec->length + md_size, rec->orig_len, - mac_sec, md_size, 1); - } else { - unsigned int md_size_u; - /* Chop the digest off the end :-) */ - EVP_MD_CTX_init(&md_ctx); - - EVP_MD_CTX_copy_ex(&md_ctx, hash); - EVP_DigestUpdate(&md_ctx, mac_sec, md_size); - EVP_DigestUpdate(&md_ctx, ssl3_pad_1, npad); - EVP_DigestUpdate(&md_ctx, seq, 8); - rec_char = rec->type; - EVP_DigestUpdate(&md_ctx, &rec_char, 1); - p = md; - s2n(rec->length, p); - EVP_DigestUpdate(&md_ctx, md, 2); - EVP_DigestUpdate(&md_ctx, rec->input, rec->length); - EVP_DigestFinal_ex(&md_ctx, md, NULL); - - EVP_MD_CTX_copy_ex(&md_ctx, hash); - EVP_DigestUpdate(&md_ctx, mac_sec, md_size); - EVP_DigestUpdate(&md_ctx, ssl3_pad_2, npad); - EVP_DigestUpdate(&md_ctx, md, md_size); - EVP_DigestFinal_ex(&md_ctx, md, &md_size_u); - md_size = md_size_u; - - EVP_MD_CTX_cleanup(&md_ctx); - } - - ssl3_record_sequence_update(seq); - return (md_size); -} - -void ssl3_record_sequence_update(unsigned char *seq) -{ - int i; - - for (i = 7; i >= 0; i--) { - ++seq[i]; - if (seq[i] != 0) - break; - } -} - int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, int len) { @@ -840,24 +657,31 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, EVP_MD_CTX_init(&ctx); for (i = 0; i < 3; i++) { - EVP_DigestInit_ex(&ctx, s->ctx->sha1, NULL); - EVP_DigestUpdate(&ctx, salt[i], strlen((const char *)salt[i])); - EVP_DigestUpdate(&ctx, p, len); - EVP_DigestUpdate(&ctx, &(s->s3->client_random[0]), SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&ctx, &(s->s3->server_random[0]), SSL3_RANDOM_SIZE); - EVP_DigestFinal_ex(&ctx, buf, &n); - - EVP_DigestInit_ex(&ctx, s->ctx->md5, NULL); - EVP_DigestUpdate(&ctx, p, len); - EVP_DigestUpdate(&ctx, buf, n); - EVP_DigestFinal_ex(&ctx, out, &n); + if (EVP_DigestInit_ex(&ctx, s->ctx->sha1, NULL) <= 0 + || EVP_DigestUpdate(&ctx, salt[i], + strlen((const char *)salt[i])) <= 0 + || EVP_DigestUpdate(&ctx, p, len) <= 0 + || EVP_DigestUpdate(&ctx, &(s->s3->client_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestUpdate(&ctx, &(s->s3->server_random[0]), + SSL3_RANDOM_SIZE) <= 0 + || EVP_DigestFinal_ex(&ctx, buf, &n) <= 0 + + || EVP_DigestInit_ex(&ctx, s->ctx->md5, NULL) <= 0 + || EVP_DigestUpdate(&ctx, p, len) <= 0 + || EVP_DigestUpdate(&ctx, buf, n) <= 0 + || EVP_DigestFinal_ex(&ctx, out, &n) <= 0) { + SSLerr(SSL_F_SSL3_GENERATE_MASTER_SECRET, ERR_R_INTERNAL_ERROR); + ret = 0; + break; + } out += n; ret += n; } EVP_MD_CTX_cleanup(&ctx); #ifdef OPENSSL_SSL_TRACE_CRYPTO - if (s->msg_callback) { + if (ret > 0 && 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, @@ -871,7 +695,7 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, s, s->msg_callback_arg); } #endif - OPENSSL_cleanse(buf, sizeof buf); + OPENSSL_cleanse(buf, sizeof(buf)); return (ret); }