Line data Source code
1 : /* Copyright (c) 2001, Matej Pfajfar.
2 : * Copyright (c) 2001-2004, Roger Dingledine.
3 : * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 : /* See LICENSE for licensing information */
6 :
7 : /**
8 : * \file crypto_cipher.c
9 : * \brief Symmetric cryptography (low-level) with AES.
10 : **/
11 :
12 : #include "orconfig.h"
13 :
14 : #include "lib/crypt_ops/crypto_cipher.h"
15 : #include "lib/crypt_ops/crypto_rand.h"
16 : #include "lib/crypt_ops/crypto_util.h"
17 :
18 : #include "lib/log/log.h"
19 : #include "lib/log/util_bug.h"
20 : #include "lib/cc/torint.h"
21 : #include "lib/crypt_ops/aes.h"
22 :
23 : #include <string.h>
24 :
25 : /** Allocate and return a new symmetric cipher using the provided key and iv.
26 : * The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both
27 : * must be provided. Key length must be 128, 192, or 256 */
28 : crypto_cipher_t *
29 13555 : crypto_cipher_new_with_iv_and_bits(const uint8_t *key,
30 : const uint8_t *iv,
31 : int bits)
32 : {
33 13555 : tor_assert(key);
34 13555 : tor_assert(iv);
35 :
36 13555 : return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits);
37 : }
38 :
39 : /** Allocate and return a new symmetric cipher using the provided key and iv.
40 : * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both
41 : * must be provided.
42 : */
43 : crypto_cipher_t *
44 50 : crypto_cipher_new_with_iv(const char *key, const char *iv)
45 : {
46 50 : return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv,
47 : 128);
48 : }
49 :
50 : /** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all
51 : * zero bytes and key length <b>bits</b>. Key length must be 128, 192, or
52 : * 256. */
53 : crypto_cipher_t *
54 260 : crypto_cipher_new_with_bits(const char *key, int bits)
55 : {
56 260 : char zeroiv[CIPHER_IV_LEN];
57 260 : memset(zeroiv, 0, sizeof(zeroiv));
58 260 : return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv,
59 : bits);
60 : }
61 :
62 : /** Return a new crypto_cipher_t with the provided <b>key</b> (of
63 : * CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */
64 : crypto_cipher_t *
65 123 : crypto_cipher_new(const char *key)
66 : {
67 123 : return crypto_cipher_new_with_bits(key, 128);
68 : }
69 :
70 : /** Free a symmetric cipher.
71 : */
72 : void
73 13736 : crypto_cipher_free_(crypto_cipher_t *env)
74 : {
75 13736 : if (!env)
76 : return;
77 :
78 13533 : aes_cipher_free(env);
79 : }
80 :
81 : /* symmetric crypto */
82 :
83 : /** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
84 : * <b>env</b>; on success, store the result to <b>to</b> and return 0.
85 : * Does not check for failure.
86 : */
87 : int
88 846 : crypto_cipher_encrypt(crypto_cipher_t *env, char *to,
89 : const char *from, size_t fromlen)
90 : {
91 846 : tor_assert(env);
92 846 : tor_assert(env);
93 846 : tor_assert(from);
94 846 : tor_assert(fromlen);
95 846 : tor_assert(to);
96 846 : tor_assert(fromlen < SIZE_T_CEILING);
97 :
98 846 : memcpy(to, from, fromlen);
99 846 : aes_crypt_inplace(env, to, fromlen);
100 846 : return 0;
101 : }
102 :
103 : /** Decrypt <b>fromlen</b> bytes from <b>from</b> using the cipher
104 : * <b>env</b>; on success, store the result to <b>to</b> and return 0.
105 : * Does not check for failure.
106 : */
107 : int
108 501 : crypto_cipher_decrypt(crypto_cipher_t *env, char *to,
109 : const char *from, size_t fromlen)
110 : {
111 501 : tor_assert(env);
112 501 : tor_assert(from);
113 501 : tor_assert(to);
114 501 : tor_assert(fromlen < SIZE_T_CEILING);
115 :
116 501 : memcpy(to, from, fromlen);
117 501 : aes_crypt_inplace(env, to, fromlen);
118 501 : return 0;
119 : }
120 :
121 : /** Encrypt <b>len</b> bytes on <b>from</b> using the cipher in <b>env</b>;
122 : * on success. Does not check for failure.
123 : */
124 : void
125 76124 : crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
126 : {
127 76124 : tor_assert(len < SIZE_T_CEILING);
128 76124 : aes_crypt_inplace(env, buf, len);
129 76124 : }
130 :
131 : /** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
132 : * <b>key</b> to the buffer in <b>to</b> of length
133 : * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
134 : * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
135 : * number of bytes written, on failure, return -1.
136 : */
137 : int
138 12 : crypto_cipher_encrypt_with_iv(const char *key,
139 : char *to, size_t tolen,
140 : const char *from, size_t fromlen)
141 : {
142 12 : crypto_cipher_t *cipher;
143 12 : tor_assert(from);
144 12 : tor_assert(to);
145 12 : tor_assert(fromlen < INT_MAX);
146 :
147 12 : if (fromlen < 1)
148 : return -1;
149 12 : if (tolen < fromlen + CIPHER_IV_LEN)
150 : return -1;
151 :
152 12 : char iv[CIPHER_IV_LEN];
153 12 : crypto_rand(iv, sizeof(iv));
154 12 : cipher = crypto_cipher_new_with_iv(key, iv);
155 :
156 12 : memcpy(to, iv, CIPHER_IV_LEN);
157 12 : crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
158 12 : crypto_cipher_free(cipher);
159 12 : memwipe(iv, 0, sizeof(iv));
160 12 : return (int)(fromlen + CIPHER_IV_LEN);
161 : }
162 :
163 : /** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
164 : * with the key in <b>key</b> to the buffer in <b>to</b> of length
165 : * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
166 : * CIPHER_IV_LEN bytes for the initialization vector. On success, return the
167 : * number of bytes written, on failure, return -1.
168 : */
169 : int
170 16 : crypto_cipher_decrypt_with_iv(const char *key,
171 : char *to, size_t tolen,
172 : const char *from, size_t fromlen)
173 : {
174 16 : crypto_cipher_t *cipher;
175 16 : tor_assert(key);
176 16 : tor_assert(from);
177 16 : tor_assert(to);
178 16 : tor_assert(fromlen < INT_MAX);
179 :
180 16 : if (fromlen <= CIPHER_IV_LEN)
181 : return -1;
182 16 : if (tolen < fromlen - CIPHER_IV_LEN)
183 : return -1;
184 :
185 16 : cipher = crypto_cipher_new_with_iv(key, from);
186 :
187 16 : crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
188 16 : crypto_cipher_free(cipher);
189 16 : return (int)(fromlen - CIPHER_IV_LEN);
190 : }
|