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.
17 * @file util/crypto_symmetric.c
18 * @brief Symmetric encryption services; combined cipher AES+TWOFISH (256-bit each)
19 * @author Christian Grothoff
20 * @author Ioana Patrascu
24 #include "gnunet_crypto_lib.h"
27 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-symmetric", __VA_ARGS__)
30 * Create a new SessionKey (for symmetric encryption).
32 * @param key session key to initialize
35 GNUNET_CRYPTO_symmetric_create_session_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key)
37 gcry_randomize (key->aes_key,
38 GNUNET_CRYPTO_AES_KEY_LENGTH,
40 gcry_randomize (key->twofish_key,
41 GNUNET_CRYPTO_AES_KEY_LENGTH,
47 * Initialize AES cipher.
49 * @param handle handle to initialize
50 * @param sessionkey session key to use
51 * @param iv initialization vector to use
52 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
55 setup_cipher_aes (gcry_cipher_hd_t *handle,
56 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
57 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
62 gcry_cipher_open (handle, GCRY_CIPHER_AES256,
63 GCRY_CIPHER_MODE_CFB, 0));
64 rc = gcry_cipher_setkey (*handle,
66 sizeof (sessionkey->aes_key));
67 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
68 rc = gcry_cipher_setiv (*handle,
71 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
77 * Initialize TWOFISH cipher.
79 * @param handle handle to initialize
80 * @param sessionkey session key to use
81 * @param iv initialization vector to use
82 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
85 setup_cipher_twofish (gcry_cipher_hd_t *handle,
86 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
87 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv)
92 gcry_cipher_open (handle, GCRY_CIPHER_TWOFISH,
93 GCRY_CIPHER_MODE_CFB, 0));
94 rc = gcry_cipher_setkey (*handle,
95 sessionkey->twofish_key,
96 sizeof (sessionkey->twofish_key));
97 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
98 rc = gcry_cipher_setiv (*handle,
100 sizeof (iv->twofish_iv));
101 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
107 * Encrypt a block with a symmetric session key.
109 * @param block the block to encrypt
110 * @param size the size of the @a block
111 * @param sessionkey the key used to encrypt
112 * @param iv the initialization vector to use, use INITVALUE for streams
113 * @param result the output parameter in which to store the encrypted result
114 * can be the same or overlap with @c block
115 * @returns the size of the encrypted block, -1 for errors.
116 * Due to the use of CFB and therefore an effective stream cipher,
117 * this size should be the same as @c len.
120 GNUNET_CRYPTO_symmetric_encrypt (const void *block,
122 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
123 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
126 gcry_cipher_hd_t handle;
129 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
131 GNUNET_assert (0 == gcry_cipher_encrypt (handle, tmp, size, block, size));
132 gcry_cipher_close (handle);
133 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
135 GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, tmp, size));
136 gcry_cipher_close (handle);
137 memset (tmp, 0, sizeof (tmp));
143 * Decrypt a given block with the session key.
145 * @param block the data to decrypt, encoded as returned by encrypt
146 * @param size the size of the @a block to decrypt
147 * @param sessionkey the key used to decrypt
148 * @param iv the initialization vector to use, use INITVALUE for streams
149 * @param result address to store the result at
150 * can be the same or overlap with @c block
151 * @return -1 on failure, size of decrypted block on success.
152 * Due to the use of CFB and therefore an effective stream cipher,
153 * this size should be the same as @c size.
156 GNUNET_CRYPTO_symmetric_decrypt (const void *block,
158 const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey,
159 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
162 gcry_cipher_hd_t handle;
165 if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv))
167 GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, block, size));
168 gcry_cipher_close (handle);
169 if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv))
171 GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, tmp, size));
172 gcry_cipher_close (handle);
173 memset (tmp, 0, sizeof (tmp));
179 * @brief Derive an IV
181 * @param iv initialization vector
182 * @param skey session key
183 * @param salt salt for the derivation
184 * @param salt_len size of the @a salt
185 * @param ... pairs of void * & size_t for context chunks, terminated by NULL
188 GNUNET_CRYPTO_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
189 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
196 va_start (argp, salt_len);
197 GNUNET_CRYPTO_symmetric_derive_iv_v (iv, skey, salt, salt_len, argp);
203 * @brief Derive an IV
205 * @param iv initialization vector
206 * @param skey session key
207 * @param salt salt for the derivation
208 * @param salt_len size of the salt
209 * @param argp pairs of void * & size_t for context chunks, terminated by NULL
212 GNUNET_CRYPTO_symmetric_derive_iv_v (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
213 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
218 char aes_salt[salt_len + 4];
219 char twofish_salt[salt_len + 4];
221 GNUNET_memcpy (aes_salt, salt, salt_len);
222 GNUNET_memcpy (&aes_salt[salt_len], "AES!", 4);
223 GNUNET_memcpy (twofish_salt, salt, salt_len);
224 GNUNET_memcpy (&twofish_salt[salt_len], "FISH", 4);
225 GNUNET_CRYPTO_kdf_v (iv->aes_iv,
230 sizeof (skey->aes_key),
232 GNUNET_CRYPTO_kdf_v (iv->twofish_iv,
233 sizeof (iv->twofish_iv),
237 sizeof (skey->twofish_key),
241 /* end of crypto_symmetric.c */