2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2013 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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
29 #include "gnunet_crypto_lib.h"
32 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-symmetric", \
36 * Create a new SessionKey (for symmetric encryption).
38 * @param key session key to initialize
41 GNUNET_CRYPTO_symmetric_create_session_key (struct
42 GNUNET_CRYPTO_SymmetricSessionKey *
45 gcry_randomize (key->aes_key,
46 GNUNET_CRYPTO_AES_KEY_LENGTH,
48 gcry_randomize (key->twofish_key,
49 GNUNET_CRYPTO_AES_KEY_LENGTH,
55 * Initialize AES cipher.
57 * @param handle handle to initialize
58 * @param sessionkey session key to use
59 * @param iv initialization vector to use
60 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
63 setup_cipher_aes (gcry_cipher_hd_t *handle,
64 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
65 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
70 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
71 GCRY_CIPHER_MODE_CFB, 0));
72 rc = gcry_cipher_setkey (*handle,
74 sizeof(sessionkey->aes_key));
75 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
76 rc = gcry_cipher_setiv (*handle,
79 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
85 * Initialize TWOFISH cipher.
87 * @param handle handle to initialize
88 * @param sessionkey session key to use
89 * @param iv initialization vector to use
90 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
93 setup_cipher_twofish (gcry_cipher_hd_t *handle,
95 GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
97 GNUNET_CRYPTO_SymmetricInitializationVector *iv)
102 gcry_cipher_open (handle, GCRY_CIPHER_TWOFISH,
103 GCRY_CIPHER_MODE_CFB, 0));
104 rc = gcry_cipher_setkey (*handle,
105 sessionkey->twofish_key,
106 sizeof(sessionkey->twofish_key));
107 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
108 rc = gcry_cipher_setiv (*handle,
110 sizeof(iv->twofish_iv));
111 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
117 * Encrypt a block with a symmetric session key.
119 * @param block the block to encrypt
120 * @param size the size of the @a block
121 * @param sessionkey the key used to encrypt
122 * @param iv the initialization vector to use, use INITVALUE for streams
123 * @param result the output parameter in which to store the encrypted result
124 * can be the same or overlap with @c block
125 * @returns the size of the encrypted block, -1 for errors.
126 * Due to the use of CFB and therefore an effective stream cipher,
127 * this size should be the same as @c len.
130 GNUNET_CRYPTO_symmetric_encrypt (const void *block,
133 GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
135 GNUNET_CRYPTO_SymmetricInitializationVector *iv,
138 gcry_cipher_hd_t handle;
141 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
143 GNUNET_assert (0 == gcry_cipher_encrypt (handle, tmp, size, block, size));
144 gcry_cipher_close (handle);
145 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
147 GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, tmp, size));
148 gcry_cipher_close (handle);
149 memset (tmp, 0, sizeof(tmp));
155 * Decrypt a given block with the session key.
157 * @param block the data to decrypt, encoded as returned by encrypt
158 * @param size the size of the @a block to decrypt
159 * @param sessionkey the key used to decrypt
160 * @param iv the initialization vector to use, use INITVALUE for streams
161 * @param result address to store the result at
162 * can be the same or overlap with @c block
163 * @return -1 on failure, size of decrypted block on success.
164 * Due to the use of CFB and therefore an effective stream cipher,
165 * this size should be the same as @c size.
168 GNUNET_CRYPTO_symmetric_decrypt (const void *block,
171 GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
173 GNUNET_CRYPTO_SymmetricInitializationVector *iv,
176 gcry_cipher_hd_t handle;
179 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
181 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, block, size));
182 gcry_cipher_close (handle);
183 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
185 GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, tmp, size));
186 gcry_cipher_close (handle);
187 memset (tmp, 0, sizeof(tmp));
193 * @brief Derive an IV
195 * @param iv initialization vector
196 * @param skey session key
197 * @param salt salt for the derivation
198 * @param salt_len size of the @a salt
199 * @param ... pairs of void * & size_t for context chunks, terminated by NULL
202 GNUNET_CRYPTO_symmetric_derive_iv (struct
203 GNUNET_CRYPTO_SymmetricInitializationVector *
206 GNUNET_CRYPTO_SymmetricSessionKey *skey,
213 va_start (argp, salt_len);
214 GNUNET_CRYPTO_symmetric_derive_iv_v (iv, skey, salt, salt_len, argp);
220 * @brief Derive an IV
222 * @param iv initialization vector
223 * @param skey session key
224 * @param salt salt for the derivation
225 * @param salt_len size of the salt
226 * @param argp pairs of void * & size_t for context chunks, terminated by NULL
229 GNUNET_CRYPTO_symmetric_derive_iv_v (struct
230 GNUNET_CRYPTO_SymmetricInitializationVector
233 GNUNET_CRYPTO_SymmetricSessionKey *skey,
238 char aes_salt[salt_len + 4];
239 char twofish_salt[salt_len + 4];
241 GNUNET_memcpy (aes_salt, salt, salt_len);
242 GNUNET_memcpy (&aes_salt[salt_len], "AES!", 4);
243 GNUNET_memcpy (twofish_salt, salt, salt_len);
244 GNUNET_memcpy (&twofish_salt[salt_len], "FISH", 4);
245 GNUNET_CRYPTO_kdf_v (iv->aes_iv,
250 sizeof(skey->aes_key),
252 GNUNET_CRYPTO_kdf_v (iv->twofish_iv,
253 sizeof(iv->twofish_iv),
257 sizeof(skey->twofish_key),
261 /* end of crypto_symmetric.c */