2 * Copyright (C) 2009-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_cipher_int.h>
26 #include <gnutls_datum.h>
27 #include <gnutls/crypto.h>
29 #include <algorithms.h>
31 #define SR(x, cleanup) if ( (x)<0 ) { \
33 ret = GNUTLS_E_INTERNAL_ERROR; \
37 /* Returns true(non-zero) or false(0) if the
38 * provided cipher exists
40 int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher
)
42 const gnutls_crypto_cipher_st
*cc
;
45 cc
= _gnutls_get_crypto_cipher (cipher
);
46 if (cc
!= NULL
) return 1;
48 ret
= _gnutls_cipher_ops
.exists(cipher
);
53 _gnutls_cipher_init (cipher_hd_st
* handle
, gnutls_cipher_algorithm_t cipher
,
54 const gnutls_datum_t
* key
, const gnutls_datum_t
* iv
, int enc
)
56 int ret
= GNUTLS_E_INTERNAL_ERROR
;
57 const gnutls_crypto_cipher_st
*cc
= NULL
;
59 if (cipher
== GNUTLS_CIPHER_NULL
)
60 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
62 handle
->is_aead
= _gnutls_cipher_algo_is_aead(cipher
);
64 handle
->tag_size
= gnutls_cipher_get_block_size(cipher
);
66 /* check if a cipher has been registered
68 cc
= _gnutls_get_crypto_cipher (cipher
);
71 handle
->encrypt
= cc
->encrypt
;
72 handle
->decrypt
= cc
->decrypt
;
73 handle
->deinit
= cc
->deinit
;
74 handle
->auth
= cc
->auth
;
75 handle
->tag
= cc
->tag
;
76 handle
->setiv
= cc
->setiv
;
78 SR (cc
->init (cipher
, &handle
->handle
, enc
), cc_cleanup
);
79 SR (cc
->setkey( handle
->handle
, key
->data
, key
->size
), cc_cleanup
);
82 SR (cc
->setiv( handle
->handle
, iv
->data
, iv
->size
), cc_cleanup
);
88 handle
->encrypt
= _gnutls_cipher_ops
.encrypt
;
89 handle
->decrypt
= _gnutls_cipher_ops
.decrypt
;
90 handle
->deinit
= _gnutls_cipher_ops
.deinit
;
91 handle
->auth
= _gnutls_cipher_ops
.auth
;
92 handle
->tag
= _gnutls_cipher_ops
.tag
;
93 handle
->setiv
= _gnutls_cipher_ops
.setiv
;
95 /* otherwise use generic cipher interface
97 ret
= _gnutls_cipher_ops
.init (cipher
, &handle
->handle
, enc
);
104 ret
= _gnutls_cipher_ops
.setkey(handle
->handle
, key
->data
, key
->size
);
113 ret
= _gnutls_cipher_ops
.setiv(handle
->handle
, iv
->data
, iv
->size
);
126 handle
->deinit (handle
->handle
);
133 int _gnutls_auth_cipher_init (auth_cipher_hd_st
* handle
,
134 gnutls_cipher_algorithm_t cipher
,
135 const gnutls_datum_t
* cipher_key
,
136 const gnutls_datum_t
* iv
,
137 gnutls_mac_algorithm_t mac
,
138 const gnutls_datum_t
* mac_key
,
139 int ssl_hmac
, int enc
)
143 memset(handle
, 0, sizeof(*handle
));
145 if (cipher
!= GNUTLS_CIPHER_NULL
)
147 ret
= _gnutls_cipher_init(&handle
->cipher
, cipher
, cipher_key
, iv
, enc
);
149 return gnutls_assert_val(ret
);
154 if (mac
!= GNUTLS_MAC_AEAD
)
157 handle
->ssl_hmac
= ssl_hmac
;
160 ret
= _gnutls_mac_init_ssl3(&handle
->mac
, mac
, mac_key
->data
, mac_key
->size
);
162 ret
= _gnutls_hmac_init(&handle
->mac
, mac
, mac_key
->data
, mac_key
->size
);
169 handle
->tag_size
= _gnutls_hmac_get_algo_len(mac
);
171 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
172 handle
->tag_size
= _gnutls_cipher_tag_len(&handle
->cipher
);
176 if (handle
->is_null
== 0)
177 _gnutls_cipher_deinit(&handle
->cipher
);
182 int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st
* handle
, const void *text
,
187 if (handle
->ssl_hmac
)
188 return _gnutls_hash(&handle
->mac
, text
, textlen
);
190 return _gnutls_hmac(&handle
->mac
, text
, textlen
);
192 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
193 return _gnutls_cipher_auth(&handle
->cipher
, text
, textlen
);
198 int _gnutls_auth_cipher_encrypt2_tag (auth_cipher_hd_st
* handle
, const uint8_t *text
,
199 int textlen
, void *ciphertext
, int ciphertextlen
,
200 void* tag_ptr
, int tag_size
,
207 if (handle
->ssl_hmac
)
208 ret
= _gnutls_hash(&handle
->mac
, text
, auth_size
);
210 ret
= _gnutls_hmac(&handle
->mac
, text
, auth_size
);
216 ret
= _gnutls_auth_cipher_tag(handle
, tag_ptr
, tag_size
);
218 return gnutls_assert_val(ret
);
220 if (handle
->is_null
==0)
222 ret
= _gnutls_cipher_encrypt2(&handle
->cipher
, text
, textlen
, ciphertext
, ciphertextlen
);
224 return gnutls_assert_val(ret
);
227 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
229 ret
= _gnutls_cipher_encrypt2(&handle
->cipher
, text
, textlen
, ciphertext
, ciphertextlen
);
231 return gnutls_assert_val(ret
);
233 ret
= _gnutls_auth_cipher_tag(handle
, tag_ptr
, tag_size
);
235 return gnutls_assert_val(ret
);
241 int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st
* handle
,
242 const void *ciphertext
, int ciphertextlen
,
243 void *text
, int textlen
)
247 if (handle
->is_null
==0)
249 ret
= _gnutls_cipher_decrypt2(&handle
->cipher
, ciphertext
, ciphertextlen
,
252 return gnutls_assert_val(ret
);
257 /* The MAC is not to be hashed */
258 textlen
-= handle
->tag_size
;
260 if (handle
->ssl_hmac
)
261 return _gnutls_hash(&handle
->mac
, text
, textlen
);
263 return _gnutls_hmac(&handle
->mac
, text
, textlen
);
269 int _gnutls_auth_cipher_tag(auth_cipher_hd_st
* handle
, void* tag
, int tag_size
)
274 if (handle
->ssl_hmac
)
276 ret
= _gnutls_mac_output_ssl3 (&handle
->mac
, tag
);
278 return gnutls_assert_val(ret
);
280 _gnutls_mac_reset_ssl3 (&handle
->mac
);
284 _gnutls_hmac_output (&handle
->mac
, tag
);
285 _gnutls_hmac_reset (&handle
->mac
);
288 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
290 _gnutls_cipher_tag(&handle
->cipher
, tag
, tag_size
);
296 void _gnutls_auth_cipher_deinit (auth_cipher_hd_st
* handle
)
300 if (handle
->ssl_hmac
) /* failure here doesn't matter */
301 _gnutls_mac_deinit_ssl3 (&handle
->mac
, NULL
);
303 _gnutls_hmac_deinit(&handle
->mac
, NULL
);
305 if (handle
->is_null
==0)
306 _gnutls_cipher_deinit(&handle
->cipher
);