added new functions
[gnutls.git] / lib / gnutls_cipher_int.c
blobcbb6a401aef8aa1ffe588fd404029c37833a8357
1 /*
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>
28 #include <crypto.h>
29 #include <algorithms.h>
31 #define SR(x, cleanup) if ( (x)<0 ) { \
32 gnutls_assert(); \
33 ret = GNUTLS_E_INTERNAL_ERROR; \
34 goto cleanup; \
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;
43 int ret;
45 cc = _gnutls_get_crypto_cipher (cipher);
46 if (cc != NULL) return 1;
48 ret = _gnutls_cipher_ops.exists(cipher);
49 return ret;
52 int
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);
63 if (handle->is_aead)
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);
69 if (cc != NULL)
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);
80 if (iv)
82 SR (cc->setiv( handle->handle, iv->data, iv->size), cc_cleanup);
85 return 0;
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);
98 if (ret < 0)
100 gnutls_assert ();
101 return ret;
104 ret = _gnutls_cipher_ops.setkey(handle->handle, key->data, key->size);
105 if (ret < 0)
107 gnutls_assert ();
108 goto cc_cleanup;
111 if (iv)
113 ret = _gnutls_cipher_ops.setiv(handle->handle, iv->data, iv->size);
114 if (ret < 0)
116 gnutls_assert ();
117 goto cc_cleanup;
121 return 0;
123 cc_cleanup:
125 if (handle->handle)
126 handle->deinit (handle->handle);
128 return ret;
131 /* Auth_cipher API
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)
141 int ret;
143 memset(handle, 0, sizeof(*handle));
145 if (cipher != GNUTLS_CIPHER_NULL)
147 ret = _gnutls_cipher_init(&handle->cipher, cipher, cipher_key, iv, enc);
148 if (ret < 0)
149 return gnutls_assert_val(ret);
151 else
152 handle->is_null = 1;
154 if (mac != GNUTLS_MAC_AEAD)
156 handle->is_mac = 1;
157 handle->ssl_hmac = ssl_hmac;
159 if (ssl_hmac)
160 ret = _gnutls_mac_init_ssl3(&handle->mac, mac, mac_key->data, mac_key->size);
161 else
162 ret = _gnutls_hmac_init(&handle->mac, mac, mac_key->data, mac_key->size);
163 if (ret < 0)
165 gnutls_assert();
166 goto cleanup;
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);
174 return 0;
175 cleanup:
176 if (handle->is_null == 0)
177 _gnutls_cipher_deinit(&handle->cipher);
178 return ret;
182 int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st * handle, const void *text,
183 int textlen)
185 if (handle->is_mac)
187 if (handle->ssl_hmac)
188 return _gnutls_hash(&handle->mac, text, textlen);
189 else
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);
194 else
195 return 0;
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,
201 int auth_size)
203 int ret;
205 if (handle->is_mac)
207 if (handle->ssl_hmac)
208 ret = _gnutls_hash(&handle->mac, text, auth_size);
209 else
210 ret = _gnutls_hmac(&handle->mac, text, auth_size);
211 if (ret < 0)
213 gnutls_assert();
214 return ret;
216 ret = _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size);
217 if (ret < 0)
218 return gnutls_assert_val(ret);
220 if (handle->is_null==0)
222 ret = _gnutls_cipher_encrypt2(&handle->cipher, text, textlen, ciphertext, ciphertextlen);
223 if (ret < 0)
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);
230 if (ret < 0)
231 return gnutls_assert_val(ret);
233 ret = _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size);
234 if (ret < 0)
235 return gnutls_assert_val(ret);
238 return 0;
241 int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st * handle,
242 const void *ciphertext, int ciphertextlen,
243 void *text, int textlen)
245 int ret;
247 if (handle->is_null==0)
249 ret = _gnutls_cipher_decrypt2(&handle->cipher, ciphertext, ciphertextlen,
250 text, textlen);
251 if (ret < 0)
252 return gnutls_assert_val(ret);
255 if (handle->is_mac)
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);
262 else
263 return _gnutls_hmac(&handle->mac, text, textlen);
266 return 0;
269 int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void* tag, int tag_size)
271 int ret = 0;
272 if (handle->is_mac)
274 if (handle->ssl_hmac)
276 ret = _gnutls_mac_output_ssl3 (&handle->mac, tag);
277 if (ret < 0)
278 return gnutls_assert_val(ret);
280 _gnutls_mac_reset_ssl3 (&handle->mac);
282 else
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);
293 return 0;
296 void _gnutls_auth_cipher_deinit (auth_cipher_hd_st * handle)
298 if (handle->is_mac)
300 if (handle->ssl_hmac) /* failure here doesn't matter */
301 _gnutls_mac_deinit_ssl3 (&handle->mac, NULL);
302 else
303 _gnutls_hmac_deinit(&handle->mac, NULL);
305 if (handle->is_null==0)
306 _gnutls_cipher_deinit(&handle->cipher);