aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/crypto_symmetric.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/crypto_symmetric.c')
-rw-r--r--src/lib/util/crypto_symmetric.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/src/lib/util/crypto_symmetric.c b/src/lib/util/crypto_symmetric.c
new file mode 100644
index 000000000..c08b84c17
--- /dev/null
+++ b/src/lib/util/crypto_symmetric.c
@@ -0,0 +1,254 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/crypto_symmetric.c
23 * @brief Symmetric encryption services; combined cipher AES+TWOFISH (256-bit each)
24 * @author Christian Grothoff
25 * @author Ioana Patrascu
26 */
27
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include <gcrypt.h>
32
33#define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-symmetric", \
34 __VA_ARGS__)
35
36/**
37 * Create a new SessionKey (for symmetric encryption).
38 *
39 * @param key session key to initialize
40 */
41void
42GNUNET_CRYPTO_symmetric_create_session_key (struct
43 GNUNET_CRYPTO_SymmetricSessionKey *
44 key)
45{
46 gcry_randomize (key->aes_key,
47 GNUNET_CRYPTO_AES_KEY_LENGTH,
48 GCRY_STRONG_RANDOM);
49 gcry_randomize (key->twofish_key,
50 GNUNET_CRYPTO_AES_KEY_LENGTH,
51 GCRY_STRONG_RANDOM);
52}
53
54
55/**
56 * Initialize AES cipher.
57 *
58 * @param handle handle to initialize
59 * @param sessionkey session key to use
60 * @param iv initialization vector to use
61 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
62 */
63static int
64setup_cipher_aes (gcry_cipher_hd_t *handle,
65 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
66 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
67{
68 int rc;
69
70 GNUNET_assert (0 ==
71 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
72 GCRY_CIPHER_MODE_CFB, 0));
73 rc = gcry_cipher_setkey (*handle,
74 sessionkey->aes_key,
75 sizeof(sessionkey->aes_key));
76 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
77 rc = gcry_cipher_setiv (*handle,
78 iv->aes_iv,
79 sizeof(iv->aes_iv));
80 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
81 return GNUNET_OK;
82}
83
84
85/**
86 * Initialize TWOFISH cipher.
87 *
88 * @param handle handle to initialize
89 * @param sessionkey session key to use
90 * @param iv initialization vector to use
91 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
92 */
93static int
94setup_cipher_twofish (gcry_cipher_hd_t *handle,
95 const struct
96 GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
97 const struct
98 GNUNET_CRYPTO_SymmetricInitializationVector *iv)
99{
100 int rc;
101
102 GNUNET_assert (0 ==
103 gcry_cipher_open (handle, GCRY_CIPHER_TWOFISH,
104 GCRY_CIPHER_MODE_CFB, 0));
105 rc = gcry_cipher_setkey (*handle,
106 sessionkey->twofish_key,
107 sizeof(sessionkey->twofish_key));
108 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
109 rc = gcry_cipher_setiv (*handle,
110 iv->twofish_iv,
111 sizeof(iv->twofish_iv));
112 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
113 return GNUNET_OK;
114}
115
116
117/**
118 * Encrypt a block with a symmetric session key.
119 *
120 * @param block the block to encrypt
121 * @param size the size of the @a block
122 * @param sessionkey the key used to encrypt
123 * @param iv the initialization vector to use, use INITVALUE for streams
124 * @param result the output parameter in which to store the encrypted result
125 * can be the same or overlap with @c block
126 * @returns the size of the encrypted block, -1 for errors.
127 * Due to the use of CFB and therefore an effective stream cipher,
128 * this size should be the same as @c len.
129 */
130ssize_t
131GNUNET_CRYPTO_symmetric_encrypt (const void *block,
132 size_t size,
133 const struct
134 GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
135 const struct
136 GNUNET_CRYPTO_SymmetricInitializationVector *iv,
137 void *result)
138{
139 gcry_cipher_hd_t handle;
140 char tmp[GNUNET_NZL(size)];
141
142 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
143 return -1;
144 GNUNET_assert (0 == gcry_cipher_encrypt (handle, tmp, size, block, size));
145 gcry_cipher_close (handle);
146 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
147 return -1;
148 GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, tmp, size));
149 gcry_cipher_close (handle);
150 memset (tmp, 0, sizeof(tmp));
151 return size;
152}
153
154
155/**
156 * Decrypt a given block with the session key.
157 *
158 * @param block the data to decrypt, encoded as returned by encrypt
159 * @param size the size of the @a block to decrypt
160 * @param sessionkey the key used to decrypt
161 * @param iv the initialization vector to use, use INITVALUE for streams
162 * @param result address to store the result at
163 * can be the same or overlap with @c block
164 * @return -1 on failure, size of decrypted block on success.
165 * Due to the use of CFB and therefore an effective stream cipher,
166 * this size should be the same as @c size.
167 */
168ssize_t
169GNUNET_CRYPTO_symmetric_decrypt (const void *block,
170 size_t size,
171 const struct
172 GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
173 const struct
174 GNUNET_CRYPTO_SymmetricInitializationVector *iv,
175 void *result)
176{
177 gcry_cipher_hd_t handle;
178 char tmp[size];
179
180 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
181 return -1;
182 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, block, size));
183 gcry_cipher_close (handle);
184 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
185 return -1;
186 GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, tmp, size));
187 gcry_cipher_close (handle);
188 memset (tmp, 0, sizeof(tmp));
189 return size;
190}
191
192
193/**
194 * @brief Derive an IV
195 *
196 * @param iv initialization vector
197 * @param skey session key
198 * @param salt salt for the derivation
199 * @param salt_len size of the @a salt
200 * @param ... pairs of void * & size_t for context chunks, terminated by NULL
201 */
202void
203GNUNET_CRYPTO_symmetric_derive_iv (struct
204 GNUNET_CRYPTO_SymmetricInitializationVector *
205 iv,
206 const struct
207 GNUNET_CRYPTO_SymmetricSessionKey *skey,
208 const void *salt,
209 size_t salt_len,
210 ...)
211{
212 va_list argp;
213
214 va_start (argp, salt_len);
215 GNUNET_CRYPTO_symmetric_derive_iv_v (iv, skey, salt, salt_len, argp);
216 va_end (argp);
217}
218
219
220void
221GNUNET_CRYPTO_symmetric_derive_iv_v (struct
222 GNUNET_CRYPTO_SymmetricInitializationVector
223 *iv,
224 const struct
225 GNUNET_CRYPTO_SymmetricSessionKey *skey,
226 const void *salt,
227 size_t salt_len,
228 va_list argp)
229{
230 char aes_salt[salt_len + 4];
231 char twofish_salt[salt_len + 4];
232
233 GNUNET_memcpy (aes_salt, salt, salt_len);
234 GNUNET_memcpy (&aes_salt[salt_len], "AES!", 4);
235 GNUNET_memcpy (twofish_salt, salt, salt_len);
236 GNUNET_memcpy (&twofish_salt[salt_len], "FISH", 4);
237 GNUNET_CRYPTO_kdf_v (iv->aes_iv,
238 sizeof(iv->aes_iv),
239 aes_salt,
240 salt_len + 4,
241 skey->aes_key,
242 sizeof(skey->aes_key),
243 argp);
244 GNUNET_CRYPTO_kdf_v (iv->twofish_iv,
245 sizeof(iv->twofish_iv),
246 twofish_salt,
247 salt_len + 4,
248 skey->twofish_key,
249 sizeof(skey->twofish_key),
250 argp);
251}
252
253
254/* end of crypto_symmetric.c */