2 * Copyright (C) 2009, 2010 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
27 #include <gnutls_cipher_int.h>
28 #include <gnutls_datum.h>
29 #include <gnutls/crypto.h>
31 #include <gnutls_algorithms.h>
33 #define SR(x, cleanup) if ( (x)<0 ) { \
35 ret = GNUTLS_E_INTERNAL_ERROR; \
40 _gnutls_cipher_init (cipher_hd_st
* handle
, gnutls_cipher_algorithm_t cipher
,
41 const gnutls_datum_t
* key
, const gnutls_datum_t
* iv
)
43 int ret
= GNUTLS_E_INTERNAL_ERROR
;
44 const gnutls_crypto_cipher_st
*cc
= NULL
;
46 handle
->is_aead
= _gnutls_cipher_algo_is_aead(cipher
);
48 handle
->tag_size
= gnutls_cipher_get_block_size(cipher
);
50 /* check if a cipher has been registered
52 cc
= _gnutls_get_crypto_cipher (cipher
);
55 handle
->encrypt
= cc
->encrypt
;
56 handle
->decrypt
= cc
->decrypt
;
57 handle
->deinit
= cc
->deinit
;
58 handle
->auth
= cc
->auth
;
59 handle
->tag
= cc
->tag
;
60 handle
->setiv
= cc
->setiv
;
62 SR (cc
->init (cipher
, &handle
->handle
), cc_cleanup
);
63 SR (cc
->setkey( handle
->handle
, key
->data
, key
->size
), cc_cleanup
);
66 SR (cc
->setiv( handle
->handle
, iv
->data
, iv
->size
), cc_cleanup
);
72 handle
->encrypt
= _gnutls_cipher_ops
.encrypt
;
73 handle
->decrypt
= _gnutls_cipher_ops
.decrypt
;
74 handle
->deinit
= _gnutls_cipher_ops
.deinit
;
75 handle
->auth
= _gnutls_cipher_ops
.auth
;
76 handle
->tag
= _gnutls_cipher_ops
.tag
;
77 handle
->setiv
= _gnutls_cipher_ops
.setiv
;
79 /* otherwise use generic cipher interface
81 ret
= _gnutls_cipher_ops
.init (cipher
, &handle
->handle
);
88 ret
= _gnutls_cipher_ops
.setkey(handle
->handle
, key
->data
, key
->size
);
97 ret
= _gnutls_cipher_ops
.setiv(handle
->handle
, iv
->data
, iv
->size
);
110 handle
->deinit (handle
->handle
);
117 int _gnutls_auth_cipher_init (auth_cipher_hd_st
* handle
,
118 gnutls_cipher_algorithm_t cipher
,
119 const gnutls_datum_t
* cipher_key
,
120 const gnutls_datum_t
* iv
,
121 gnutls_mac_algorithm_t mac
,
122 const gnutls_datum_t
* mac_key
,
127 memset(handle
, 0, sizeof(*handle
));
129 ret
= _gnutls_cipher_init(&handle
->cipher
, cipher
, cipher_key
, iv
);
136 if (mac
!= GNUTLS_MAC_AEAD
)
139 handle
->ssl_hmac
= ssl_hmac
;
142 ret
= _gnutls_mac_init_ssl3(&handle
->mac
, mac
, mac_key
->data
, mac_key
->size
);
144 ret
= _gnutls_hmac_init(&handle
->mac
, mac
, mac_key
->data
, mac_key
->size
);
151 handle
->tag_size
= _gnutls_hash_get_algo_len(mac
);
153 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
154 handle
->tag_size
= _gnutls_cipher_tag_len(&handle
->cipher
);
158 _gnutls_cipher_deinit(&handle
->cipher
);
163 int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st
* handle
, const void *text
,
168 if (handle
->ssl_hmac
)
169 return _gnutls_hash(&handle
->mac
, text
, textlen
);
171 return _gnutls_hmac(&handle
->mac
, text
, textlen
);
173 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
174 return _gnutls_cipher_auth(&handle
->cipher
, text
, textlen
);
179 int _gnutls_auth_cipher_encrypt2_tag (auth_cipher_hd_st
* handle
, const uint8_t *text
,
180 int textlen
, void *ciphertext
, int ciphertextlen
,
181 void* tag_ptr
, int tag_size
,
188 if (handle
->ssl_hmac
)
189 ret
= _gnutls_hash(&handle
->mac
, text
, auth_size
);
191 ret
= _gnutls_hmac(&handle
->mac
, text
, auth_size
);
197 ret
= _gnutls_auth_cipher_tag(handle
, tag_ptr
, tag_size
);
199 return gnutls_assert_val(ret
);
201 ret
= _gnutls_cipher_encrypt2(&handle
->cipher
, text
, textlen
, ciphertext
, ciphertextlen
);
203 return gnutls_assert_val(ret
);
205 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
207 ret
= _gnutls_cipher_encrypt2(&handle
->cipher
, text
, textlen
, ciphertext
, ciphertextlen
);
209 return gnutls_assert_val(ret
);
211 ret
= _gnutls_auth_cipher_tag(handle
, tag_ptr
, tag_size
);
213 return gnutls_assert_val(ret
);
219 int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st
* handle
,
220 const void *ciphertext
, int ciphertextlen
,
221 void *text
, int textlen
)
225 ret
= _gnutls_cipher_decrypt2(&handle
->cipher
, ciphertext
, ciphertextlen
,
235 /* The MAC is not to be hashed */
236 textlen
-= handle
->tag_size
;
238 if (handle
->ssl_hmac
)
239 return _gnutls_hash(&handle
->mac
, text
, textlen
);
241 return _gnutls_hmac(&handle
->mac
, text
, textlen
);
247 int _gnutls_auth_cipher_tag(auth_cipher_hd_st
* handle
, void* tag
, int tag_size
)
252 if (handle
->ssl_hmac
)
254 ret
= _gnutls_mac_output_ssl3 (&handle
->mac
, tag
);
256 return gnutls_assert_val(ret
);
258 _gnutls_hash_reset (&handle
->mac
);
262 _gnutls_hmac_output (&handle
->mac
, tag
);
263 _gnutls_hmac_reset (&handle
->mac
);
266 else if (_gnutls_cipher_is_aead(&handle
->cipher
))
268 _gnutls_cipher_tag(&handle
->cipher
, tag
, tag_size
);
274 void _gnutls_auth_cipher_deinit (auth_cipher_hd_st
* handle
)
278 if (handle
->ssl_hmac
) /* failure here doesn't matter */
279 _gnutls_mac_deinit_ssl3 (&handle
->mac
, NULL
);
281 _gnutls_hmac_deinit(&handle
->mac
, NULL
);
283 _gnutls_cipher_deinit(&handle
->cipher
);