Add `gnutls/dtls.h' to the distribution.
[gnutls.git] / lib / gnutls_cipher_int.c
blobe766504513e553cf21f4c686f044830f9feecca7
1 /*
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,
21 * USA
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>
30 #include <crypto.h>
31 #include <gnutls_algorithms.h>
33 #define SR(x, cleanup) if ( (x)<0 ) { \
34 gnutls_assert(); \
35 ret = GNUTLS_E_INTERNAL_ERROR; \
36 goto cleanup; \
39 int
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);
47 if (handle->is_aead)
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);
53 if (cc != NULL)
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);
64 if (iv)
66 SR (cc->setiv( handle->handle, iv->data, iv->size), cc_cleanup);
69 return 0;
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);
82 if (ret < 0)
84 gnutls_assert ();
85 return ret;
88 ret = _gnutls_cipher_ops.setkey(handle->handle, key->data, key->size);
89 if (ret < 0)
91 gnutls_assert ();
92 goto cc_cleanup;
95 if (iv)
97 ret = _gnutls_cipher_ops.setiv(handle->handle, iv->data, iv->size);
98 if (ret < 0)
100 gnutls_assert ();
101 goto cc_cleanup;
105 return 0;
107 cc_cleanup:
109 if (handle->handle)
110 handle->deinit (handle->handle);
112 return ret;
115 /* Auth_cipher API
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,
123 int ssl_hmac)
125 int ret;
127 memset(handle, 0, sizeof(*handle));
129 ret = _gnutls_cipher_init(&handle->cipher, cipher, cipher_key, iv);
130 if (ret < 0)
132 gnutls_assert();
133 return ret;
136 if (mac != GNUTLS_MAC_AEAD)
138 handle->is_mac = 1;
139 handle->ssl_hmac = ssl_hmac;
141 if (ssl_hmac)
142 ret = _gnutls_mac_init_ssl3(&handle->mac, mac, mac_key->data, mac_key->size);
143 else
144 ret = _gnutls_hmac_init(&handle->mac, mac, mac_key->data, mac_key->size);
145 if (ret < 0)
147 gnutls_assert();
148 goto cleanup;
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);
156 return 0;
157 cleanup:
158 _gnutls_cipher_deinit(&handle->cipher);
159 return ret;
163 int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st * handle, const void *text,
164 int textlen)
166 if (handle->is_mac)
168 if (handle->ssl_hmac)
169 return _gnutls_hash(&handle->mac, text, textlen);
170 else
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);
175 else
176 return 0;
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,
182 int auth_size)
184 int ret;
186 if (handle->is_mac)
188 if (handle->ssl_hmac)
189 ret = _gnutls_hash(&handle->mac, text, auth_size);
190 else
191 ret = _gnutls_hmac(&handle->mac, text, auth_size);
192 if (ret < 0)
194 gnutls_assert();
195 return ret;
197 ret = _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size);
198 if (ret < 0)
199 return gnutls_assert_val(ret);
201 ret = _gnutls_cipher_encrypt2(&handle->cipher, text, textlen, ciphertext, ciphertextlen);
202 if (ret < 0)
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);
208 if (ret < 0)
209 return gnutls_assert_val(ret);
211 ret = _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size);
212 if (ret < 0)
213 return gnutls_assert_val(ret);
216 return 0;
219 int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st * handle,
220 const void *ciphertext, int ciphertextlen,
221 void *text, int textlen)
223 int ret;
225 ret = _gnutls_cipher_decrypt2(&handle->cipher, ciphertext, ciphertextlen,
226 text, textlen);
227 if (ret < 0)
229 gnutls_assert();
230 return ret;
233 if (handle->is_mac)
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);
240 else
241 return _gnutls_hmac(&handle->mac, text, textlen);
244 return 0;
247 int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void* tag, int tag_size)
249 int ret = 0;
250 if (handle->is_mac)
252 if (handle->ssl_hmac)
254 ret = _gnutls_mac_output_ssl3 (&handle->mac, tag);
255 if (ret < 0)
256 return gnutls_assert_val(ret);
258 _gnutls_hash_reset (&handle->mac);
260 else
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);
271 return 0;
274 void _gnutls_auth_cipher_deinit (auth_cipher_hd_st * handle)
276 if (handle->is_mac)
278 if (handle->ssl_hmac) /* failure here doesn't matter */
279 _gnutls_mac_deinit_ssl3 (&handle->mac, NULL);
280 else
281 _gnutls_hmac_deinit(&handle->mac, NULL);
283 _gnutls_cipher_deinit(&handle->cipher);