2007-12-12 22:09:01 +01:00
|
|
|
/* Copyright (c) 2001, Matej Pfajfar.
|
2006-02-09 06:46:49 +01:00
|
|
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
2007-12-12 22:09:01 +01:00
|
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
2018-06-20 14:13:28 +02:00
|
|
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
2002-07-24 16:02:39 +02:00
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
|
2004-05-10 05:53:24 +02:00
|
|
|
/**
|
2018-07-11 20:08:22 +02:00
|
|
|
* \file crypto_cipher.c
|
|
|
|
* \brief Symmetric cryptography (low-level) with AES.
|
2004-05-10 05:53:24 +02:00
|
|
|
**/
|
|
|
|
|
2004-04-03 06:05:12 +02:00
|
|
|
#include "orconfig.h"
|
2004-03-11 07:19:08 +01:00
|
|
|
|
2018-07-11 20:08:22 +02:00
|
|
|
#include "lib/crypt_ops/crypto_cipher.h"
|
2018-06-21 18:47:11 +02:00
|
|
|
#include "lib/crypt_ops/crypto_rand.h"
|
|
|
|
#include "lib/crypt_ops/crypto_util.h"
|
2015-05-21 17:54:13 +02:00
|
|
|
|
2018-07-10 21:20:28 +02:00
|
|
|
#include "lib/log/log.h"
|
2018-06-28 19:57:23 +02:00
|
|
|
#include "lib/log/util_bug.h"
|
2018-06-21 18:20:52 +02:00
|
|
|
#include "lib/cc/torint.h"
|
2018-06-21 18:47:11 +02:00
|
|
|
#include "lib/crypt_ops/aes.h"
|
2018-06-21 22:52:58 +02:00
|
|
|
|
2018-06-28 19:57:23 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
2012-03-20 20:35:43 +01:00
|
|
|
/** Allocate and return a new symmetric cipher using the provided key and iv.
|
2016-09-16 17:21:33 +02:00
|
|
|
* The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both
|
|
|
|
* must be provided. Key length must be 128, 192, or 256 */
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_cipher_t *
|
2016-09-16 17:21:33 +02:00
|
|
|
crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
|
|
|
|
const uint8_t *iv,
|
|
|
|
int bits)
|
2002-10-02 22:39:51 +02:00
|
|
|
{
|
2016-09-16 16:12:30 +02:00
|
|
|
tor_assert(key);
|
|
|
|
tor_assert(iv);
|
2002-10-02 22:39:51 +02:00
|
|
|
|
2016-09-16 17:21:33 +02:00
|
|
|
return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
|
|
|
|
}
|
2002-10-02 22:39:51 +02:00
|
|
|
|
2016-09-16 17:21:33 +02:00
|
|
|
/** Allocate and return a new symmetric cipher using the provided key and iv.
|
|
|
|
* The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
|
|
|
|
* must be provided.
|
|
|
|
*/
|
|
|
|
crypto_cipher_t *
|
|
|
|
crypto_cipher_new_with_iv(const char *key, const char *iv)
|
|
|
|
{
|
|
|
|
return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
|
|
|
|
128);
|
2002-10-02 22:39:51 +02:00
|
|
|
}
|
|
|
|
|
2012-06-05 01:51:00 +02:00
|
|
|
/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
|
2016-09-16 17:21:33 +02:00
|
|
|
* zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
|
|
|
|
* 256. */
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_cipher_t *
|
2016-09-16 17:21:33 +02:00
|
|
|
crypto_cipher_new_with_bits(const char *key, int bits)
|
2002-07-24 16:02:39 +02:00
|
|
|
{
|
2012-03-20 20:35:43 +01:00
|
|
|
char zeroiv[CIPHER_IV_LEN];
|
|
|
|
memset(zeroiv, 0, sizeof(zeroiv));
|
2016-09-16 17:21:33 +02:00
|
|
|
return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
|
|
|
|
bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Return a new crypto_cipher_t with the provided <b>key</b> (of
|
|
|
|
* CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
|
|
|
|
crypto_cipher_t *
|
|
|
|
crypto_cipher_new(const char *key)
|
|
|
|
{
|
|
|
|
return crypto_cipher_new_with_bits(key, 128);
|
2002-07-24 16:02:39 +02:00
|
|
|
}
|
|
|
|
|
2004-05-10 05:53:24 +02:00
|
|
|
/** Free a symmetric cipher.
|
2004-05-01 23:41:23 +02:00
|
|
|
*/
|
2005-09-30 03:09:52 +02:00
|
|
|
void
|
2017-11-17 17:55:52 +01:00
|
|
|
crypto_cipher_free_(crypto_cipher_t *env)
|
2002-07-24 16:02:39 +02:00
|
|
|
{
|
2009-09-28 16:37:01 +02:00
|
|
|
if (!env)
|
|
|
|
return;
|
2003-03-19 21:41:15 +01:00
|
|
|
|
2016-09-16 16:18:02 +02:00
|
|
|
aes_cipher_free(env);
|
2002-07-24 16:02:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* symmetric crypto */
|
2004-05-01 23:41:23 +02:00
|
|
|
|
2004-05-10 05:53:24 +02:00
|
|
|
/** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
|
|
|
|
* <b>env</b>; on success, store the result to <b>to</b> and return 0.
|
2015-11-23 10:31:57 +01:00
|
|
|
* Does not check for failure.
|
2004-05-01 23:41:23 +02:00
|
|
|
*/
|
2004-11-02 03:28:51 +01:00
|
|
|
int
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
|
2005-05-07 07:55:06 +02:00
|
|
|
const char *from, size_t fromlen)
|
2002-07-24 16:02:39 +02:00
|
|
|
{
|
2004-10-17 00:28:11 +02:00
|
|
|
tor_assert(env);
|
2016-09-16 16:18:02 +02:00
|
|
|
tor_assert(env);
|
2004-10-17 00:28:11 +02:00
|
|
|
tor_assert(from);
|
|
|
|
tor_assert(fromlen);
|
|
|
|
tor_assert(to);
|
2010-12-14 00:40:21 +01:00
|
|
|
tor_assert(fromlen < SIZE_T_CEILING);
|
2003-12-16 06:29:04 +01:00
|
|
|
|
2016-02-06 18:05:32 +01:00
|
|
|
memcpy(to, from, fromlen);
|
2016-09-16 16:18:02 +02:00
|
|
|
aes_crypt_inplace(env, to, fromlen);
|
2004-04-03 04:40:30 +02:00
|
|
|
return 0;
|
2002-07-24 16:02:39 +02:00
|
|
|
}
|
|
|
|
|
2004-05-10 05:53:24 +02:00
|
|
|
/** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
|
|
|
|
* <b>env</b>; on success, store the result to <b>to</b> and return 0.
|
2015-11-23 10:31:57 +01:00
|
|
|
* Does not check for failure.
|
2004-05-01 23:41:23 +02:00
|
|
|
*/
|
2004-11-02 03:28:51 +01:00
|
|
|
int
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
|
2005-05-07 07:55:06 +02:00
|
|
|
const char *from, size_t fromlen)
|
2002-07-24 16:02:39 +02:00
|
|
|
{
|
2004-10-17 00:28:11 +02:00
|
|
|
tor_assert(env);
|
|
|
|
tor_assert(from);
|
|
|
|
tor_assert(to);
|
2010-12-14 00:40:21 +01:00
|
|
|
tor_assert(fromlen < SIZE_T_CEILING);
|
2003-06-30 21:18:32 +02:00
|
|
|
|
2016-02-06 18:05:32 +01:00
|
|
|
memcpy(to, from, fromlen);
|
2016-09-16 16:18:02 +02:00
|
|
|
aes_crypt_inplace(env, to, fromlen);
|
2004-04-03 04:40:30 +02:00
|
|
|
return 0;
|
2003-06-30 21:18:32 +02:00
|
|
|
}
|
|
|
|
|
2008-02-07 17:10:33 +01:00
|
|
|
/** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
|
2016-02-06 18:14:39 +01:00
|
|
|
* on success. Does not check for failure.
|
2008-02-07 17:10:33 +01:00
|
|
|
*/
|
2016-02-06 18:14:39 +01:00
|
|
|
void
|
2012-01-18 21:53:30 +01:00
|
|
|
crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
|
2008-02-07 17:10:33 +01:00
|
|
|
{
|
2010-12-14 00:40:21 +01:00
|
|
|
tor_assert(len < SIZE_T_CEILING);
|
2016-09-16 16:18:02 +02:00
|
|
|
aes_crypt_inplace(env, buf, len);
|
2008-02-07 17:10:33 +01:00
|
|
|
}
|
|
|
|
|
2007-09-19 17:53:41 +02:00
|
|
|
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
|
2012-03-20 20:35:43 +01:00
|
|
|
* <b>key</b> to the buffer in <b>to</b> of length
|
2007-09-19 17:53:41 +02:00
|
|
|
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
|
|
|
|
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
|
|
|
|
* number of bytes written, on failure, return -1.
|
|
|
|
*/
|
|
|
|
int
|
2012-03-20 20:35:43 +01:00
|
|
|
crypto_cipher_encrypt_with_iv(const char *key,
|
2007-09-19 17:53:41 +02:00
|
|
|
char *to, size_t tolen,
|
|
|
|
const char *from, size_t fromlen)
|
|
|
|
{
|
2012-03-20 20:35:43 +01:00
|
|
|
crypto_cipher_t *cipher;
|
2007-09-19 17:53:41 +02:00
|
|
|
tor_assert(from);
|
|
|
|
tor_assert(to);
|
2008-02-21 22:57:47 +01:00
|
|
|
tor_assert(fromlen < INT_MAX);
|
2007-09-19 17:53:41 +02:00
|
|
|
|
2007-09-20 22:08:47 +02:00
|
|
|
if (fromlen < 1)
|
|
|
|
return -1;
|
2007-09-19 17:53:41 +02:00
|
|
|
if (tolen < fromlen + CIPHER_IV_LEN)
|
|
|
|
return -1;
|
|
|
|
|
2016-09-16 16:12:30 +02:00
|
|
|
char iv[CIPHER_IV_LEN];
|
|
|
|
crypto_rand(iv, sizeof(iv));
|
|
|
|
cipher = crypto_cipher_new_with_iv(key, iv);
|
2012-03-20 20:35:43 +01:00
|
|
|
|
2016-09-16 16:12:30 +02:00
|
|
|
memcpy(to, iv, CIPHER_IV_LEN);
|
2007-09-19 17:53:41 +02:00
|
|
|
crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
|
2012-03-20 20:35:43 +01:00
|
|
|
crypto_cipher_free(cipher);
|
2016-09-16 16:12:30 +02:00
|
|
|
memwipe(iv, 0, sizeof(iv));
|
2008-02-21 22:57:47 +01:00
|
|
|
return (int)(fromlen + CIPHER_IV_LEN);
|
2007-09-19 17:53:41 +02:00
|
|
|
}
|
|
|
|
|
2007-09-20 22:08:47 +02:00
|
|
|
/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
|
2012-03-20 20:35:43 +01:00
|
|
|
* with the key in <b>key</b> to the buffer in <b>to</b> of length
|
2007-09-19 17:53:41 +02:00
|
|
|
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
|
|
|
|
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
|
|
|
|
* number of bytes written, on failure, return -1.
|
|
|
|
*/
|
|
|
|
int
|
2012-03-20 20:35:43 +01:00
|
|
|
crypto_cipher_decrypt_with_iv(const char *key,
|
2007-09-19 17:53:41 +02:00
|
|
|
char *to, size_t tolen,
|
|
|
|
const char *from, size_t fromlen)
|
|
|
|
{
|
2012-03-20 20:35:43 +01:00
|
|
|
crypto_cipher_t *cipher;
|
|
|
|
tor_assert(key);
|
2007-09-19 17:53:41 +02:00
|
|
|
tor_assert(from);
|
|
|
|
tor_assert(to);
|
2008-02-21 22:57:47 +01:00
|
|
|
tor_assert(fromlen < INT_MAX);
|
2007-09-19 17:53:41 +02:00
|
|
|
|
2007-09-20 22:08:47 +02:00
|
|
|
if (fromlen <= CIPHER_IV_LEN)
|
2007-09-19 17:53:41 +02:00
|
|
|
return -1;
|
|
|
|
if (tolen < fromlen - CIPHER_IV_LEN)
|
|
|
|
return -1;
|
|
|
|
|
2012-03-20 20:35:43 +01:00
|
|
|
cipher = crypto_cipher_new_with_iv(key, from);
|
|
|
|
|
2007-09-19 17:53:41 +02:00
|
|
|
crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
|
2012-03-20 20:35:43 +01:00
|
|
|
crypto_cipher_free(cipher);
|
2008-02-21 22:57:47 +01:00
|
|
|
return (int)(fromlen - CIPHER_IV_LEN);
|
2007-09-19 17:53:41 +02:00
|
|
|
}
|