]>
Commit | Line | Data |
---|---|---|
bebc0c7d | 1 | /* |
e39e295e | 2 | * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. |
bebc0c7d | 3 | * |
2c18d164 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
bebc0c7d MC |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
706457b7 DMSP |
10 | #include "../ssl_local.h" |
11 | #include "record_local.h" | |
67dc995e | 12 | #include "internal/cryptlib.h" |
bebc0c7d MC |
13 | |
14 | /*- | |
ec27e619 MC |
15 | * tls13_enc encrypts/decrypts |n_recs| in |recs|. Calls SSLfatal on internal |
16 | * error, but not otherwise. It is the responsibility of the caller to report | |
17 | * a bad_record_mac. | |
bebc0c7d MC |
18 | * |
19 | * Returns: | |
ec27e619 MC |
20 | * 0: On failure |
21 | * 1: if the record encryption/decryption was successful. | |
bebc0c7d | 22 | */ |
ec27e619 | 23 | int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending, |
a7e6a3d8 | 24 | ossl_unused SSL_MAC_BUF *mac, ossl_unused size_t macsize) |
bebc0c7d MC |
25 | { |
26 | EVP_CIPHER_CTX *ctx; | |
3295d242 MC |
27 | unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; |
28 | size_t ivlen, taglen, offset, loop, hdrlen; | |
bebc0c7d MC |
29 | unsigned char *staticiv; |
30 | unsigned char *seq; | |
31 | int lenu, lenf; | |
32 | SSL3_RECORD *rec = &recs[0]; | |
18b3a80a | 33 | uint32_t alg_enc; |
3295d242 | 34 | WPACKET wpkt; |
bebc0c7d MC |
35 | |
36 | if (n_recs != 1) { | |
37 | /* Should not happen */ | |
c48ffbcc | 38 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 39 | return 0; |
bebc0c7d MC |
40 | } |
41 | ||
d1186c30 | 42 | if (sending) { |
bebc0c7d MC |
43 | ctx = s->enc_write_ctx; |
44 | staticiv = s->write_iv; | |
45 | seq = RECORD_LAYER_get_write_sequence(&s->rlayer); | |
46 | } else { | |
47 | ctx = s->enc_read_ctx; | |
48 | staticiv = s->read_iv; | |
49 | seq = RECORD_LAYER_get_read_sequence(&s->rlayer); | |
50 | } | |
51 | ||
de9e884b MC |
52 | /* |
53 | * If we're sending an alert and ctx != NULL then we must be forcing | |
54 | * plaintext alerts. If we're reading and ctx != NULL then we allow | |
55 | * plaintext alerts at certain points in the handshake. If we've got this | |
56 | * far then we have already validated that a plaintext alert is ok here. | |
57 | */ | |
58 | if (ctx == NULL || rec->type == SSL3_RT_ALERT) { | |
bebc0c7d MC |
59 | memmove(rec->data, rec->input, rec->length); |
60 | rec->input = rec->data; | |
61 | return 1; | |
62 | } | |
18b3a80a | 63 | |
ed576acd | 64 | ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); |
bebc0c7d | 65 | |
ef6c191b MC |
66 | if (s->early_data_state == SSL_EARLY_DATA_WRITING |
67 | || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) { | |
0ef28021 | 68 | if (s->session != NULL && s->session->ext.max_early_data > 0) { |
add8d0e9 | 69 | alg_enc = s->session->cipher->algorithm_enc; |
0ef28021 MC |
70 | } else { |
71 | if (!ossl_assert(s->psksession != NULL | |
921d84a0 | 72 | && s->psksession->ext.max_early_data > 0)) { |
c48ffbcc | 73 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 74 | return 0; |
921d84a0 | 75 | } |
add8d0e9 | 76 | alg_enc = s->psksession->cipher->algorithm_enc; |
0ef28021 | 77 | } |
49e7fe12 MC |
78 | } else { |
79 | /* | |
80 | * To get here we must have selected a ciphersuite - otherwise ctx would | |
81 | * be NULL | |
82 | */ | |
555cbb32 | 83 | if (!ossl_assert(s->s3.tmp.new_cipher != NULL)) { |
c48ffbcc | 84 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 85 | return 0; |
921d84a0 | 86 | } |
555cbb32 | 87 | alg_enc = s->s3.tmp.new_cipher->algorithm_enc; |
49e7fe12 | 88 | } |
18b3a80a | 89 | |
20fc2051 DSH |
90 | if (alg_enc & SSL_AESCCM) { |
91 | if (alg_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) | |
ec07b1d8 DSH |
92 | taglen = EVP_CCM8_TLS_TAG_LEN; |
93 | else | |
94 | taglen = EVP_CCM_TLS_TAG_LEN; | |
d1186c30 | 95 | if (sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, |
921d84a0 | 96 | NULL) <= 0) { |
c48ffbcc | 97 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 98 | return 0; |
921d84a0 | 99 | } |
20fc2051 | 100 | } else if (alg_enc & SSL_AESGCM) { |
ec07b1d8 | 101 | taglen = EVP_GCM_TLS_TAG_LEN; |
20fc2051 DSH |
102 | } else if (alg_enc & SSL_CHACHA20) { |
103 | taglen = EVP_CHACHAPOLY_TLS_TAG_LEN; | |
104 | } else { | |
c48ffbcc | 105 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 106 | return 0; |
ec07b1d8 DSH |
107 | } |
108 | ||
d1186c30 | 109 | if (!sending) { |
bebc0c7d MC |
110 | /* |
111 | * Take off tag. There must be at least one byte of content type as | |
112 | * well as the tag | |
113 | */ | |
ec07b1d8 | 114 | if (rec->length < taglen + 1) |
bebc0c7d | 115 | return 0; |
ec07b1d8 | 116 | rec->length -= taglen; |
bebc0c7d MC |
117 | } |
118 | ||
119 | /* Set up IV */ | |
120 | if (ivlen < SEQ_NUM_SIZE) { | |
121 | /* Should not happen */ | |
c48ffbcc | 122 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 123 | return 0; |
bebc0c7d MC |
124 | } |
125 | offset = ivlen - SEQ_NUM_SIZE; | |
126 | memcpy(iv, staticiv, offset); | |
127 | for (loop = 0; loop < SEQ_NUM_SIZE; loop++) | |
128 | iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; | |
129 | ||
ac77aa9a MC |
130 | /* Increment the sequence counter */ |
131 | for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { | |
132 | ++seq[loop - 1]; | |
133 | if (seq[loop - 1] != 0) | |
134 | break; | |
135 | } | |
136 | if (loop == 0) { | |
137 | /* Sequence has wrapped */ | |
ec27e619 | 138 | return 0; |
ac77aa9a MC |
139 | } |
140 | ||
d1186c30 TS |
141 | if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 |
142 | || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, | |
ec07b1d8 | 143 | taglen, |
3295d242 | 144 | rec->data + rec->length) <= 0)) { |
c48ffbcc | 145 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 146 | return 0; |
3295d242 MC |
147 | } |
148 | ||
149 | /* Set up the AAD */ | |
150 | if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) | |
151 | || !WPACKET_put_bytes_u8(&wpkt, rec->type) | |
152 | || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version) | |
153 | || !WPACKET_put_bytes_u16(&wpkt, rec->length + taglen) | |
154 | || !WPACKET_get_total_written(&wpkt, &hdrlen) | |
155 | || hdrlen != SSL3_RT_HEADER_LENGTH | |
156 | || !WPACKET_finish(&wpkt)) { | |
c48ffbcc | 157 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
3295d242 | 158 | WPACKET_cleanup(&wpkt); |
ec27e619 | 159 | return 0; |
3295d242 MC |
160 | } |
161 | ||
162 | /* | |
163 | * For CCM we must explicitly set the total plaintext length before we add | |
164 | * any AAD. | |
165 | */ | |
166 | if (((alg_enc & SSL_AESCCM) != 0 | |
167 | && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, | |
168 | (unsigned int)rec->length) <= 0) | |
169 | || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, | |
170 | sizeof(recheader)) <= 0 | |
ec07b1d8 DSH |
171 | || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, |
172 | (unsigned int)rec->length) <= 0 | |
bebc0c7d MC |
173 | || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 |
174 | || (size_t)(lenu + lenf) != rec->length) { | |
ec27e619 | 175 | return 0; |
bebc0c7d | 176 | } |
d1186c30 | 177 | if (sending) { |
bebc0c7d | 178 | /* Add the tag */ |
ec07b1d8 | 179 | if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, |
921d84a0 | 180 | rec->data + rec->length) <= 0) { |
c48ffbcc | 181 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
ec27e619 | 182 | return 0; |
921d84a0 | 183 | } |
ec07b1d8 | 184 | rec->length += taglen; |
bebc0c7d MC |
185 | } |
186 | ||
187 | return 1; | |
188 | } |