Fix memory leak.
[gnutls.git] / lib / gnutls_cipher_int.c
bloba7b50b9b1ce0a063813a13af78dd6ade0265b3ae
1 /*
2 * Copyright (C) 2000, 2004, 2005, 2008 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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>
32 #define SR(x, cleanup) if ( (x)<0 ) { \
33 gnutls_assert(); \
34 err = GNUTLS_E_INTERNAL_ERROR; \
35 goto cleanup; \
38 int
39 _gnutls_cipher_init (cipher_hd_st* handle, gnutls_cipher_algorithm_t cipher,
40 const gnutls_datum_t * key, const gnutls_datum_t * iv)
42 int err = GC_INVALID_CIPHER; /* doesn't matter */
43 gnutls_crypto_cipher_st * cc = NULL;
45 /* check if a cipher has been registered
47 cc = _gnutls_get_crypto_cipher( cipher);
48 if (cc != NULL) {
49 handle->registered = 1;
50 handle->hd.rh.cc = cc;
51 SR( cc->init(&handle->hd.rh.ctx), cc_cleanup );
52 SR(cc->setkey( handle->hd.rh.ctx, key->data, key->size), cc_cleanup);
53 if (iv->data && iv->size && cc->setiv)
54 SR(cc->setiv( handle->hd.rh.ctx, iv->data, iv->size), cc_cleanup);
55 return 0;
58 handle->registered = 0;
59 /* otherwise use included ciphers
61 switch (cipher)
63 case GNUTLS_CIPHER_AES_128_CBC:
64 err = gc_cipher_open (GC_AES128, GC_CBC, &handle->hd.gc);
65 break;
67 case GNUTLS_CIPHER_AES_256_CBC:
68 err = gc_cipher_open (GC_AES256, GC_CBC, &handle->hd.gc);
69 break;
71 case GNUTLS_CIPHER_3DES_CBC:
72 err = gc_cipher_open (GC_3DES, GC_CBC, &handle->hd.gc);
73 break;
75 case GNUTLS_CIPHER_DES_CBC:
76 err = gc_cipher_open (GC_DES, GC_CBC, &handle->hd.gc);
77 break;
79 case GNUTLS_CIPHER_ARCFOUR_128:
80 err = gc_cipher_open (GC_ARCFOUR128, GC_STREAM, &handle->hd.gc);
81 break;
83 case GNUTLS_CIPHER_ARCFOUR_40:
84 err = gc_cipher_open (GC_ARCFOUR40, GC_STREAM, &handle->hd.gc);
85 break;
87 case GNUTLS_CIPHER_RC2_40_CBC:
88 err = gc_cipher_open (GC_ARCTWO40, GC_CBC, &handle->hd.gc);
89 break;
91 #ifdef ENABLE_CAMELLIA
92 case GNUTLS_CIPHER_CAMELLIA_128_CBC:
93 err = gc_cipher_open (GC_CAMELLIA128, GC_CBC, &handle->hd.gc);
94 break;
96 case GNUTLS_CIPHER_CAMELLIA_256_CBC:
97 err = gc_cipher_open (GC_CAMELLIA256, GC_CBC, &handle->hd.gc);
98 break;
99 #endif
101 default:
102 gnutls_assert();
103 return GNUTLS_E_INVALID_REQUEST;
106 if (err == 0)
108 gc_cipher_setkey (handle->hd.gc, key->size, key->data);
109 if (iv->data != NULL && iv->size > 0)
110 gc_cipher_setiv (handle->hd.gc, iv->size, iv->data);
112 else if (cipher != GNUTLS_CIPHER_NULL)
114 gnutls_assert ();
115 _gnutls_x509_log ("Crypto cipher[%d] error: %d\n", cipher, err);
116 return GNUTLS_E_INTERNAL_ERROR;
117 /* FIXME: gc_strerror */
120 return 0;
122 cc_cleanup:
124 if (handle->hd.rh.cc)
125 cc->deinit(handle->hd.rh.ctx);
127 return err;
131 _gnutls_cipher_encrypt (const cipher_hd_st* handle, void *text, int textlen)
133 if (handle != NULL)
135 if (handle->registered) {
136 if (handle->hd.rh.ctx == NULL) return 0;
137 return handle->hd.rh.cc->encrypt( handle->hd.rh.ctx, text, textlen, text, textlen);
140 if (handle->hd.gc == NULL) return 0;
141 if (gc_cipher_encrypt_inline (handle->hd.gc, textlen, text) != 0)
143 gnutls_assert ();
144 return GNUTLS_E_INTERNAL_ERROR;
147 return 0;
151 _gnutls_cipher_decrypt (const cipher_hd_st *handle, void *ciphertext,
152 int ciphertextlen)
154 if (handle != NULL)
156 if (handle->registered) {
157 if (handle->hd.rh.ctx == NULL) return 0;
158 return handle->hd.rh.cc->decrypt( handle->hd.rh.ctx, ciphertext, ciphertextlen, ciphertext, ciphertextlen);
161 if (handle->hd.gc == NULL) return 0;
162 if (gc_cipher_decrypt_inline (handle->hd.gc, ciphertextlen, ciphertext) != 0)
164 gnutls_assert ();
165 return GNUTLS_E_INTERNAL_ERROR;
168 return 0;
171 void
172 _gnutls_cipher_deinit (cipher_hd_st* handle)
174 if (handle != NULL)
176 if (handle->registered && handle->hd.rh.ctx != NULL) {
177 return handle->hd.rh.cc->deinit( handle->hd.rh.ctx);
179 gc_cipher_close (handle->hd.gc);