1 /* Copyright (c) 2015, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <assert.h>
16 #include <string.h>
17
18 #include <openssl/aead.h>
19 #include <openssl/err.h>
20 #include <openssl/rand.h>
21 #include <openssl/type_check.h>
22
23 #include "internal.h"
24
25
26 OPENSSL_COMPILE_ASSERT(EVP_AEAD_MAX_NONCE_LENGTH < 256,
27 variable_nonce_len_doesnt_fit_in_uint8_t);
28
SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,uint16_t version,const SSL_CIPHER * cipher,const uint8_t * enc_key,size_t enc_key_len,const uint8_t * mac_key,size_t mac_key_len,const uint8_t * fixed_iv,size_t fixed_iv_len)29 SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
30 uint16_t version, const SSL_CIPHER *cipher,
31 const uint8_t *enc_key, size_t enc_key_len,
32 const uint8_t *mac_key, size_t mac_key_len,
33 const uint8_t *fixed_iv, size_t fixed_iv_len) {
34 const EVP_AEAD *aead;
35 size_t discard;
36 if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, cipher, version)) {
37 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_new, ERR_R_INTERNAL_ERROR);
38 return 0;
39 }
40
41 uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
42 if (mac_key_len > 0) {
43 /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
44 * suites). */
45 if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) {
46 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_new, ERR_R_INTERNAL_ERROR);
47 return 0;
48 }
49 memcpy(merged_key, mac_key, mac_key_len);
50 memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
51 memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len);
52 enc_key = merged_key;
53 enc_key_len += mac_key_len;
54 enc_key_len += fixed_iv_len;
55 }
56
57 SSL_AEAD_CTX *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
58 if (aead_ctx == NULL) {
59 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_new, ERR_R_MALLOC_FAILURE);
60 return NULL;
61 }
62 memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
63 aead_ctx->cipher = cipher;
64
65 if (!EVP_AEAD_CTX_init_with_direction(
66 &aead_ctx->ctx, aead, enc_key, enc_key_len,
67 EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) {
68 OPENSSL_free(aead_ctx);
69 return NULL;
70 }
71
72 assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
73 aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead);
74 if (mac_key_len == 0) {
75 /* For a real AEAD, the IV is the fixed part of the nonce. */
76 if (fixed_iv_len > sizeof(aead_ctx->fixed_nonce) ||
77 fixed_iv_len > aead_ctx->variable_nonce_len) {
78 SSL_AEAD_CTX_free(aead_ctx);
79 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_new, ERR_R_INTERNAL_ERROR);
80 return 0;
81 }
82 aead_ctx->variable_nonce_len -= fixed_iv_len;
83
84 memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
85 aead_ctx->fixed_nonce_len = fixed_iv_len;
86 aead_ctx->variable_nonce_included_in_record =
87 (cipher->algorithm2 &
88 SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
89 } else {
90 aead_ctx->variable_nonce_included_in_record = 1;
91 aead_ctx->random_variable_nonce = 1;
92 aead_ctx->omit_length_in_ad = 1;
93 aead_ctx->omit_version_in_ad = (version == SSL3_VERSION);
94 }
95
96 return aead_ctx;
97 }
98
SSL_AEAD_CTX_free(SSL_AEAD_CTX * aead)99 void SSL_AEAD_CTX_free(SSL_AEAD_CTX *aead) {
100 if (aead == NULL) {
101 return;
102 }
103 EVP_AEAD_CTX_cleanup(&aead->ctx);
104 OPENSSL_free(aead);
105 }
106
SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX * aead)107 size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *aead) {
108 if (aead != NULL && aead->variable_nonce_included_in_record) {
109 return aead->variable_nonce_len;
110 }
111 return 0;
112 }
113
SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX * aead)114 size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *aead) {
115 if (aead == NULL) {
116 return 0;
117 }
118 return EVP_AEAD_max_overhead(aead->ctx.aead) +
119 SSL_AEAD_CTX_explicit_nonce_len(aead);
120 }
121
122 /* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and
123 * returns the number of bytes written. */
ssl_aead_ctx_get_ad(SSL_AEAD_CTX * aead,uint8_t out[13],uint8_t type,uint16_t wire_version,const uint8_t seqnum[8],size_t plaintext_len)124 static size_t ssl_aead_ctx_get_ad(SSL_AEAD_CTX *aead, uint8_t out[13],
125 uint8_t type, uint16_t wire_version,
126 const uint8_t seqnum[8],
127 size_t plaintext_len) {
128 memcpy(out, seqnum, 8);
129 size_t len = 8;
130 out[len++] = type;
131 if (!aead->omit_version_in_ad) {
132 out[len++] = (uint8_t)(wire_version >> 8);
133 out[len++] = (uint8_t)wire_version;
134 }
135 if (!aead->omit_length_in_ad) {
136 out[len++] = (uint8_t)(plaintext_len >> 8);
137 out[len++] = (uint8_t)plaintext_len;
138 }
139 return len;
140 }
141
SSL_AEAD_CTX_open(SSL_AEAD_CTX * aead,uint8_t * out,size_t * out_len,size_t max_out,uint8_t type,uint16_t wire_version,const uint8_t seqnum[8],const uint8_t * in,size_t in_len)142 int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
143 size_t max_out, uint8_t type, uint16_t wire_version,
144 const uint8_t seqnum[8], const uint8_t *in,
145 size_t in_len) {
146 if (aead == NULL) {
147 /* Handle the initial NULL cipher. */
148 if (in_len > max_out) {
149 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_open, SSL_R_BUFFER_TOO_SMALL);
150 return 0;
151 }
152 memmove(out, in, in_len);
153 *out_len = in_len;
154 return 1;
155 }
156
157 /* TLS 1.2 AEADs include the length in the AD and are assumed to have fixed
158 * overhead. Otherwise the parameter is unused. */
159 size_t plaintext_len = 0;
160 if (!aead->omit_length_in_ad) {
161 size_t overhead = SSL_AEAD_CTX_max_overhead(aead);
162 if (in_len < overhead) {
163 /* Publicly invalid. */
164 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_open, SSL_R_BAD_PACKET_LENGTH);
165 return 0;
166 }
167 plaintext_len = in_len - overhead;
168 }
169 uint8_t ad[13];
170 size_t ad_len = ssl_aead_ctx_get_ad(aead, ad, type, wire_version, seqnum,
171 plaintext_len);
172
173 /* Assemble the nonce. */
174 uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
175 size_t nonce_len = 0;
176 memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
177 nonce_len += aead->fixed_nonce_len;
178 if (aead->variable_nonce_included_in_record) {
179 if (in_len < aead->variable_nonce_len) {
180 /* Publicly invalid. */
181 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_open, SSL_R_BAD_PACKET_LENGTH);
182 return 0;
183 }
184 memcpy(nonce + nonce_len, in, aead->variable_nonce_len);
185 in += aead->variable_nonce_len;
186 in_len -= aead->variable_nonce_len;
187 } else {
188 assert(aead->variable_nonce_len == 8);
189 memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
190 }
191 nonce_len += aead->variable_nonce_len;
192
193 return EVP_AEAD_CTX_open(&aead->ctx, out, out_len, max_out, nonce, nonce_len,
194 in, in_len, ad, ad_len);
195 }
196
SSL_AEAD_CTX_seal(SSL_AEAD_CTX * aead,uint8_t * out,size_t * out_len,size_t max_out,uint8_t type,uint16_t wire_version,const uint8_t seqnum[8],const uint8_t * in,size_t in_len)197 int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
198 size_t max_out, uint8_t type, uint16_t wire_version,
199 const uint8_t seqnum[8], const uint8_t *in,
200 size_t in_len) {
201 if (aead == NULL) {
202 /* Handle the initial NULL cipher. */
203 if (in_len > max_out) {
204 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_seal, SSL_R_BUFFER_TOO_SMALL);
205 return 0;
206 }
207 memmove(out, in, in_len);
208 *out_len = in_len;
209 return 1;
210 }
211
212 uint8_t ad[13];
213 size_t ad_len = ssl_aead_ctx_get_ad(aead, ad, type, wire_version, seqnum,
214 in_len);
215
216 /* Assemble the nonce. */
217 uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
218 size_t nonce_len = 0;
219 memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
220 nonce_len += aead->fixed_nonce_len;
221 if (aead->random_variable_nonce) {
222 assert(aead->variable_nonce_included_in_record);
223 if (!RAND_bytes(nonce + nonce_len, aead->variable_nonce_len)) {
224 return 0;
225 }
226 } else {
227 /* When sending we use the sequence number as the variable part of the
228 * nonce. */
229 assert(aead->variable_nonce_len == 8);
230 memcpy(nonce + nonce_len, ad, aead->variable_nonce_len);
231 }
232 nonce_len += aead->variable_nonce_len;
233
234 /* Emit the variable nonce if included in the record. */
235 size_t extra_len = 0;
236 if (aead->variable_nonce_included_in_record) {
237 if (max_out < aead->variable_nonce_len) {
238 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_seal, SSL_R_BUFFER_TOO_SMALL);
239 return 0;
240 }
241 if (out < in + in_len && in < out + aead->variable_nonce_len) {
242 OPENSSL_PUT_ERROR(SSL, SSL_AEAD_CTX_seal, SSL_R_OUTPUT_ALIASES_INPUT);
243 return 0;
244 }
245 memcpy(out, nonce + aead->fixed_nonce_len, aead->variable_nonce_len);
246 extra_len = aead->variable_nonce_len;
247 out += aead->variable_nonce_len;
248 max_out -= aead->variable_nonce_len;
249 }
250
251 if (!EVP_AEAD_CTX_seal(&aead->ctx, out, out_len, max_out, nonce, nonce_len,
252 in, in_len, ad, ad_len)) {
253 return 0;
254 }
255 *out_len += extra_len;
256 return 1;
257 }
258