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/>.
20 * @file util/crypto_symmetric.c
21 * @brief Symmetric encryption services; combined cipher AES+TWOFISH (256-bit each)
22 * @author Christian Grothoff
23 * @author Ioana Patrascu
27 #include "gnunet_crypto_lib.h"
30 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-symmetric", __VA_ARGS__)
33 * Create a new SessionKey (for symmetric encryption).
35 * @param key session key to initialize
38 GNUNET_CRYPTO_symmetric_create_session_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key)
40 gcry_randomize (key->aes_key,
41 GNUNET_CRYPTO_AES_KEY_LENGTH,
43 gcry_randomize (key->twofish_key,
44 GNUNET_CRYPTO_AES_KEY_LENGTH,
50 * Initialize AES cipher.
52 * @param handle handle to initialize
53 * @param sessionkey session key to use
54 * @param iv initialization vector to use
55 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
58 setup_cipher_aes (gcry_cipher_hd_t *handle,
59 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
60 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
65 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
66 GCRY_CIPHER_MODE_CFB, 0));
67 rc = gcry_cipher_setkey (*handle,
69 sizeof (sessionkey->aes_key));
70 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
71 rc = gcry_cipher_setiv (*handle,
74 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
80 * Initialize TWOFISH cipher.
82 * @param handle handle to initialize
83 * @param sessionkey session key to use
84 * @param iv initialization vector to use
85 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
88 setup_cipher_twofish (gcry_cipher_hd_t *handle,
89 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
90 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
95 gcry_cipher_open (handle, GCRY_CIPHER_TWOFISH,
96 GCRY_CIPHER_MODE_CFB, 0));
97 rc = gcry_cipher_setkey (*handle,
98 sessionkey->twofish_key,
99 sizeof (sessionkey->twofish_key));
100 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
101 rc = gcry_cipher_setiv (*handle,
103 sizeof (iv->twofish_iv));
104 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
110 * Encrypt a block with a symmetric session key.
112 * @param block the block to encrypt
113 * @param size the size of the @a block
114 * @param sessionkey the key used to encrypt
115 * @param iv the initialization vector to use, use INITVALUE for streams
116 * @param result the output parameter in which to store the encrypted result
117 * can be the same or overlap with @c block
118 * @returns the size of the encrypted block, -1 for errors.
119 * Due to the use of CFB and therefore an effective stream cipher,
120 * this size should be the same as @c len.
123 GNUNET_CRYPTO_symmetric_encrypt (const void *block,
125 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
126 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
129 gcry_cipher_hd_t handle;
132 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
134 GNUNET_assert (0 == gcry_cipher_encrypt (handle, tmp, size, block, size));
135 gcry_cipher_close (handle);
136 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
138 GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, tmp, size));
139 gcry_cipher_close (handle);
140 memset (tmp, 0, sizeof (tmp));
146 * Decrypt a given block with the session key.
148 * @param block the data to decrypt, encoded as returned by encrypt
149 * @param size the size of the @a block to decrypt
150 * @param sessionkey the key used to decrypt
151 * @param iv the initialization vector to use, use INITVALUE for streams
152 * @param result address to store the result at
153 * can be the same or overlap with @c block
154 * @return -1 on failure, size of decrypted block on success.
155 * Due to the use of CFB and therefore an effective stream cipher,
156 * this size should be the same as @c size.
159 GNUNET_CRYPTO_symmetric_decrypt (const void *block,
161 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
162 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
165 gcry_cipher_hd_t handle;
168 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
170 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, block, size));
171 gcry_cipher_close (handle);
172 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
174 GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, tmp, size));
175 gcry_cipher_close (handle);
176 memset (tmp, 0, sizeof (tmp));
182 * @brief Derive an IV
184 * @param iv initialization vector
185 * @param skey session key
186 * @param salt salt for the derivation
187 * @param salt_len size of the @a salt
188 * @param ... pairs of void * & size_t for context chunks, terminated by NULL
191 GNUNET_CRYPTO_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
192 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
199 va_start (argp, salt_len);
200 GNUNET_CRYPTO_symmetric_derive_iv_v (iv, skey, salt, salt_len, argp);
206 * @brief Derive an IV
208 * @param iv initialization vector
209 * @param skey session key
210 * @param salt salt for the derivation
211 * @param salt_len size of the salt
212 * @param argp pairs of void * & size_t for context chunks, terminated by NULL
215 GNUNET_CRYPTO_symmetric_derive_iv_v (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
216 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
221 char aes_salt[salt_len + 4];
222 char twofish_salt[salt_len + 4];
224 GNUNET_memcpy (aes_salt, salt, salt_len);
225 GNUNET_memcpy (&aes_salt[salt_len], "AES!", 4);
226 GNUNET_memcpy (twofish_salt, salt, salt_len);
227 GNUNET_memcpy (&twofish_salt[salt_len], "FISH", 4);
228 GNUNET_CRYPTO_kdf_v (iv->aes_iv,
233 sizeof (skey->aes_key),
235 GNUNET_CRYPTO_kdf_v (iv->twofish_iv,
236 sizeof (iv->twofish_iv),
240 sizeof (skey->twofish_key),
244 /* end of crypto_symmetric.c */