Line data Source code
1 : /*
2 : * Copyright (C) 2009-2013 Free Software Foundation, Inc.
3 : * Copyright (C) 2013 Nikos Mavrogiannopoulos
4 : *
5 : * Author: Nikos Mavrogiannopoulos
6 : *
7 : * This file is part of GnuTLS.
8 : *
9 : * The GnuTLS is free software; you can redistribute it and/or
10 : * modify it under the terms of the GNU Lesser General Public License
11 : * as published by the Free Software Foundation; either version 2.1 of
12 : * the License, or (at your option) any later version.
13 : *
14 : * This library is distributed in the hope that it will be useful, but
15 : * WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : * Lesser General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU Lesser General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>
21 : *
22 : */
23 :
24 : #include "gnutls_int.h"
25 : #include "errors.h"
26 : #include <cipher_int.h>
27 : #include <datum.h>
28 : #include <gnutls/crypto.h>
29 : #include <crypto.h>
30 : #include <fips.h>
31 : #include <algorithms.h>
32 :
33 : #define SR_FB(x, cleanup) ret=(x); if ( ret<0 ) { \
34 : if (ret == GNUTLS_E_NEED_FALLBACK) { \
35 : if (handle->handle) \
36 : handle->deinit(handle->handle); \
37 : goto fallback; \
38 : } \
39 : gnutls_assert(); \
40 : ret = GNUTLS_E_INTERNAL_ERROR; \
41 : goto cleanup; \
42 : }
43 :
44 : #define SR(x, cleanup) if ( (x)<0 ) { \
45 : gnutls_assert(); \
46 : ret = GNUTLS_E_INTERNAL_ERROR; \
47 : goto cleanup; \
48 : }
49 :
50 : /* Returns true(non-zero) or false(0) if the
51 : * provided cipher exists
52 : */
53 39442 : int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher)
54 : {
55 39442 : const gnutls_crypto_cipher_st *cc;
56 39442 : int ret;
57 :
58 39442 : if (is_cipher_algo_forbidden(cipher))
59 : return 0;
60 :
61 : /* All the other ciphers are disabled on the back-end library.
62 : * The NULL needs to be detected here as it is not a cipher
63 : * that is provided by the back-end.
64 : */
65 39442 : if (cipher == GNUTLS_CIPHER_NULL)
66 : return 1;
67 :
68 39393 : cc = _gnutls_get_crypto_cipher(cipher);
69 39393 : if (cc != NULL)
70 : return 1;
71 :
72 12673 : ret = _gnutls_cipher_ops.exists(cipher);
73 12673 : return ret;
74 : }
75 :
76 : int
77 52662 : _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e,
78 : const gnutls_datum_t *key, const gnutls_datum_t *iv,
79 : int enc)
80 : {
81 52662 : int ret = GNUTLS_E_INTERNAL_ERROR;
82 52662 : const gnutls_crypto_cipher_st *cc = NULL;
83 :
84 52662 : if (unlikely(e == NULL || e->id == GNUTLS_CIPHER_NULL))
85 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
86 :
87 52662 : FAIL_IF_LIB_ERROR;
88 :
89 52662 : handle->e = e;
90 52662 : handle->handle = NULL;
91 :
92 : /* check if a cipher has been registered
93 : */
94 52662 : cc = _gnutls_get_crypto_cipher(e->id);
95 52662 : if (cc != NULL) {
96 45571 : handle->encrypt = cc->encrypt;
97 45571 : handle->decrypt = cc->decrypt;
98 45571 : handle->aead_encrypt = cc->aead_encrypt;
99 45571 : handle->aead_decrypt = cc->aead_decrypt;
100 45571 : handle->deinit = cc->deinit;
101 45571 : handle->auth = cc->auth;
102 45571 : handle->tag = cc->tag;
103 45571 : handle->setiv = cc->setiv;
104 45571 : handle->getiv = cc->getiv;
105 45571 : handle->setkey = cc->setkey;
106 :
107 : /* if cc->init() returns GNUTLS_E_NEED_FALLBACK we
108 : * use the default ciphers */
109 45571 : SR_FB(cc->init(e->id, &handle->handle, enc), cc_cleanup);
110 45571 : SR_FB(cc->setkey(handle->handle, key->data, key->size),
111 45570 : cc_cleanup);
112 45570 : if (iv) {
113 10177 : if (unlikely(cc->setiv == NULL)) /* the API doesn't accept IV */
114 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
115 10177 : SR(cc->setiv(handle->handle, iv->data, iv->size),
116 45570 : cc_cleanup);
117 : }
118 :
119 45570 : return 0;
120 : }
121 :
122 7091 : fallback:
123 7091 : handle->encrypt = _gnutls_cipher_ops.encrypt;
124 7091 : handle->decrypt = _gnutls_cipher_ops.decrypt;
125 7091 : handle->aead_encrypt = _gnutls_cipher_ops.aead_encrypt;
126 7091 : handle->aead_decrypt = _gnutls_cipher_ops.aead_decrypt;
127 7091 : handle->deinit = _gnutls_cipher_ops.deinit;
128 7091 : handle->auth = _gnutls_cipher_ops.auth;
129 7091 : handle->tag = _gnutls_cipher_ops.tag;
130 7091 : handle->setiv = _gnutls_cipher_ops.setiv;
131 7091 : handle->getiv = _gnutls_cipher_ops.getiv;
132 7091 : handle->setkey = _gnutls_cipher_ops.setkey;
133 :
134 : /* otherwise use generic cipher interface
135 : */
136 7091 : ret = _gnutls_cipher_ops.init(e->id, &handle->handle, enc);
137 7091 : if (ret < 0) {
138 0 : gnutls_assert();
139 0 : return ret;
140 : }
141 :
142 7091 : ret =
143 14182 : _gnutls_cipher_ops.setkey(handle->handle, key->data,
144 7091 : key->size);
145 7091 : if (ret < 0) {
146 0 : gnutls_assert();
147 0 : goto cc_cleanup;
148 : }
149 :
150 7091 : if (iv) {
151 1689 : ret =
152 3378 : _gnutls_cipher_ops.setiv(handle->handle, iv->data,
153 1689 : iv->size);
154 1689 : if (ret < 0) {
155 0 : gnutls_assert();
156 0 : goto cc_cleanup;
157 : }
158 : }
159 :
160 : return 0;
161 :
162 1 : cc_cleanup:
163 :
164 1 : if (handle->handle)
165 1 : handle->deinit(handle->handle);
166 :
167 : return ret;
168 : }
169 :
170 : /* Auth_cipher API
171 : */
172 18824 : int _gnutls_auth_cipher_init(auth_cipher_hd_st * handle,
173 : const cipher_entry_st * e,
174 : const gnutls_datum_t * cipher_key,
175 : const gnutls_datum_t * iv,
176 : const mac_entry_st * me,
177 : const gnutls_datum_t * mac_key,
178 : unsigned etm,
179 : #ifdef ENABLE_SSL3
180 : unsigned ssl_hmac,
181 : #endif
182 : int enc)
183 : {
184 18824 : int ret;
185 :
186 18824 : if (unlikely(e == NULL))
187 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
188 :
189 18824 : FAIL_IF_LIB_ERROR;
190 :
191 18824 : memset(handle, 0, sizeof(*handle));
192 18824 : handle->etm = etm;
193 :
194 18824 : if (e->id != GNUTLS_CIPHER_NULL) {
195 18744 : handle->non_null = 1;
196 18744 : ret =
197 18744 : _gnutls_cipher_init(&handle->cipher, e, cipher_key, iv,
198 : enc);
199 18744 : if (ret < 0)
200 0 : return gnutls_assert_val(ret);
201 : } else
202 80 : handle->non_null = 0;
203 :
204 18824 : if (me->id != GNUTLS_MAC_AEAD) {
205 9150 : handle->is_mac = 1;
206 : #ifdef ENABLE_SSL3
207 : handle->ssl_hmac = ssl_hmac;
208 :
209 : if (ssl_hmac)
210 : ret =
211 : _gnutls_mac_init_ssl3(&handle->mac.dig, me,
212 : mac_key->data,
213 : mac_key->size);
214 : else
215 : #endif
216 9150 : ret =
217 18300 : _gnutls_mac_init(&handle->mac.mac, me,
218 9150 : mac_key->data, mac_key->size);
219 9150 : if (ret < 0) {
220 0 : gnutls_assert();
221 0 : goto cleanup;
222 : }
223 : #ifdef ENABLE_GOST
224 9150 : handle->continuous_mac = !!(me->flags & GNUTLS_MAC_FLAG_CONTINUOUS_MAC);
225 : #endif
226 :
227 18300 : handle->tag_size = _gnutls_mac_get_algo_len(me);
228 9674 : } else if (_gnutls_cipher_algo_is_aead(e)) {
229 9674 : handle->tag_size = _gnutls_cipher_get_tag_size(e);
230 : } else {
231 0 : gnutls_assert();
232 0 : ret = GNUTLS_E_INVALID_REQUEST;
233 0 : goto cleanup;
234 : }
235 :
236 : return 0;
237 0 : cleanup:
238 0 : if (handle->non_null != 0)
239 0 : _gnutls_cipher_deinit(&handle->cipher);
240 : return ret;
241 :
242 : }
243 :
244 : #ifdef ENABLE_SSL3
245 : # define MAC(handle, text, textlen) \
246 : if (handle->ssl_hmac) { \
247 : ret = \
248 : _gnutls_hash(&handle->mac.dig, text, textlen); \
249 : } else { \
250 : ret = _gnutls_mac(&handle->mac.mac, text, textlen); \
251 : } \
252 : if (unlikely(ret < 0)) \
253 : return gnutls_assert_val(ret)
254 : #else
255 : # define MAC(handle, text, textlen) \
256 : ret = _gnutls_mac(&handle->mac.mac, text, textlen); \
257 : if (unlikely(ret < 0)) \
258 : return gnutls_assert_val(ret)
259 : #endif
260 :
261 4173110 : int _gnutls_auth_cipher_add_auth(auth_cipher_hd_st * handle,
262 : const void *text, int textlen)
263 : {
264 4173110 : int ret;
265 :
266 4173110 : if (handle->is_mac) {
267 6876590 : MAC(handle, text, textlen);
268 734753 : } else if (_gnutls_cipher_is_aead(&handle->cipher))
269 0 : return _gnutls_cipher_auth(&handle->cipher, text, textlen);
270 : return 0;
271 : }
272 :
273 :
274 : /* The caller must make sure that textlen+pad_size+tag_size is divided by the block size of the cipher */
275 1287180 : int _gnutls_auth_cipher_encrypt2_tag(auth_cipher_hd_st * handle,
276 : const uint8_t * text, int textlen,
277 : void *_ciphertext, int ciphertextlen,
278 : int pad_size)
279 : {
280 1287180 : int ret;
281 1287180 : uint8_t *ciphertext = _ciphertext;
282 2574370 : unsigned blocksize =
283 1287180 : _gnutls_cipher_get_block_size(handle->cipher.e);
284 1287180 : unsigned l;
285 :
286 1287180 : assert(ciphertext != NULL);
287 :
288 1287180 : if (handle->is_mac) { /* cipher + mac */
289 1231140 : if (handle->non_null == 0) { /* NULL cipher + MAC */
290 393328 : MAC(handle, text, textlen);
291 :
292 196664 : if (unlikely(textlen + pad_size + handle->tag_size) >
293 : ciphertextlen)
294 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
295 :
296 196664 : if (text != ciphertext)
297 196664 : memcpy(ciphertext, text, textlen);
298 196664 : ret =
299 393328 : _gnutls_auth_cipher_tag(handle,
300 196664 : ciphertext + textlen,
301 196664 : handle->tag_size);
302 196664 : if (ret < 0)
303 0 : return gnutls_assert_val(ret);
304 :
305 : } else {
306 1034480 : uint8_t *orig_ciphertext = ciphertext;
307 :
308 1034480 : if (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK) {
309 754270 : MAC(handle, text, textlen);
310 : }
311 :
312 1034480 : if (unlikely(textlen + pad_size + handle->tag_size) >
313 : ciphertextlen)
314 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
315 :
316 1034480 : assert(blocksize != 0);
317 1034480 : l = (textlen / blocksize) * blocksize;
318 1034480 : if (l > 0) {
319 1028750 : ret =
320 1028750 : _gnutls_cipher_encrypt2(&handle->cipher, text,
321 : l, ciphertext,
322 : ciphertextlen);
323 1028750 : if (ret < 0)
324 0 : return gnutls_assert_val(ret);
325 :
326 1028750 : textlen -= l;
327 1028750 : text += l;
328 1028750 : ciphertext += l;
329 1028750 : ciphertextlen -= l;
330 : }
331 :
332 1034480 : if (ciphertext != text && textlen > 0)
333 620961 : memcpy(ciphertext, text, textlen);
334 :
335 1034480 : if (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK) {
336 377190 : ret =
337 754380 : _gnutls_auth_cipher_tag(handle,
338 377190 : ciphertext + textlen,
339 377190 : handle->tag_size);
340 377190 : if (ret < 0)
341 0 : return gnutls_assert_val(ret);
342 377190 : textlen += handle->tag_size;
343 : }
344 :
345 : /* TLS 1.0 style padding */
346 1034480 : if (pad_size > 0) {
347 668577 : memset(ciphertext + textlen, pad_size - 1,
348 : pad_size);
349 668577 : textlen += pad_size;
350 : }
351 :
352 1034480 : ret =
353 1034480 : _gnutls_cipher_encrypt2(&handle->cipher,
354 : ciphertext, textlen,
355 : ciphertext,
356 : ciphertextlen);
357 1034480 : if (ret < 0)
358 0 : return gnutls_assert_val(ret);
359 :
360 1034480 : if (handle->etm != 0 && handle->cipher.e->type == CIPHER_BLOCK) {
361 1313190 : MAC(handle, orig_ciphertext, l);
362 1314580 : MAC(handle, ciphertext, textlen);
363 :
364 657288 : ret =
365 1314580 : _gnutls_auth_cipher_tag(handle,
366 657288 : ciphertext + textlen,
367 657288 : handle->tag_size);
368 657288 : if (ret < 0)
369 0 : return gnutls_assert_val(ret);
370 : }
371 : }
372 56041 : } else if (_gnutls_cipher_is_aead(&handle->cipher)) {
373 0 : ret =
374 0 : _gnutls_cipher_encrypt2(&handle->cipher, text, textlen,
375 : ciphertext, ciphertextlen);
376 0 : if (unlikely(ret < 0))
377 0 : return gnutls_assert_val(ret);
378 :
379 0 : ret =
380 0 : _gnutls_auth_cipher_tag(handle, ciphertext + textlen,
381 0 : handle->tag_size);
382 0 : if (unlikely(ret < 0))
383 0 : return gnutls_assert_val(ret);
384 56041 : } else if (handle->non_null == 0 && text != ciphertext) /* NULL cipher - no MAC */
385 56041 : memcpy(ciphertext, text, textlen);
386 :
387 : return 0;
388 : }
389 :
390 1241280 : int _gnutls_auth_cipher_decrypt2(auth_cipher_hd_st * handle,
391 : const void *ciphertext, int ciphertextlen,
392 : void *text, int textlen)
393 : {
394 1241280 : int ret;
395 :
396 1241280 : if (unlikely(ciphertextlen > textlen))
397 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
398 :
399 1241280 : if (handle->is_mac && (handle->etm != 0 && handle->cipher.e->type == CIPHER_BLOCK)) {
400 : /* The MAC is not to be hashed */
401 0 : ciphertextlen -= handle->tag_size;
402 :
403 0 : MAC(handle, ciphertext, ciphertextlen);
404 : }
405 :
406 1241280 : if (handle->non_null != 0) {
407 365894 : ret =
408 365894 : _gnutls_cipher_decrypt2(&handle->cipher, ciphertext,
409 : ciphertextlen, text, textlen);
410 365894 : if (ret < 0)
411 0 : return gnutls_assert_val(ret);
412 875390 : } else if (handle->non_null == 0 && text != ciphertext)
413 875390 : memcpy(text, ciphertext, ciphertextlen);
414 :
415 1241280 : if (handle->is_mac && (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK)) {
416 : /* The MAC is not to be hashed */
417 562572 : ciphertextlen -= handle->tag_size;
418 :
419 1125140 : MAC(handle, text, ciphertextlen);
420 : }
421 :
422 : return 0;
423 : }
424 :
425 3138310 : int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void *tag,
426 : int tag_size)
427 : {
428 3138310 : if (handle->is_mac) {
429 : #ifdef ENABLE_SSL3
430 : if (handle->ssl_hmac) {
431 : int ret =
432 : _gnutls_mac_output_ssl3(&handle->mac.dig, tag);
433 : if (ret < 0)
434 : return gnutls_assert_val(ret);
435 : } else
436 : #endif
437 : #ifdef ENABLE_GOST
438 : /* draft-smyshlyaev-tls12-gost-suites section 4.1.2 */
439 2459600 : if (handle->continuous_mac) {
440 216 : mac_hd_st temp_mac;
441 216 : int ret = _gnutls_mac_copy(&handle->mac.mac, &temp_mac);
442 216 : if (ret < 0)
443 0 : return gnutls_assert_val(ret);
444 216 : _gnutls_mac_deinit(&temp_mac, tag);
445 : } else
446 : #endif
447 2459380 : _gnutls_mac_output(&handle->mac.mac, tag);
448 678712 : } else if (_gnutls_cipher_is_aead(&handle->cipher)) {
449 0 : _gnutls_cipher_tag(&handle->cipher, tag, tag_size);
450 : } else
451 678712 : memset(tag, 0, tag_size);
452 :
453 : return 0;
454 : }
455 :
456 81098 : void _gnutls_auth_cipher_deinit(auth_cipher_hd_st * handle)
457 : {
458 81098 : if (handle->is_mac) {
459 : #ifdef ENABLE_SSL3
460 : if (handle->ssl_hmac) /* failure here doesn't matter */
461 : _gnutls_mac_deinit_ssl3(&handle->mac.dig, NULL);
462 : else
463 : #endif
464 9068 : _gnutls_mac_deinit(&handle->mac.mac, NULL);
465 : }
466 81098 : if (handle->non_null != 0)
467 18638 : _gnutls_cipher_deinit(&handle->cipher);
468 81098 : }
|