libhashkit/aes: fix code indentation
[awesomized/libmemcached] / src / libhashkit / aes.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached-awesome - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020-2021 Michael Wallner https://awesome.co/ |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "libhashkit/common.h"
17
18 #include <cstring>
19
20 #ifdef HAVE_OPENSSL_CRYPTO
21
22 #include <openssl/evp.h>
23
24 #define DIGEST_ROUNDS 5
25
26 #define AES_KEY_NBYTES 32
27 #define AES_IV_NBYTES 32
28
29 bool aes_initialize(const unsigned char *key, const size_t key_length,
30 encryption_context_t *crypto_context) {
31 unsigned char aes_key[AES_KEY_NBYTES];
32 unsigned char aes_iv[AES_IV_NBYTES];
33 if (!key) {
34 return false;
35 }
36
37 int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), NULL, key, key_length, DIGEST_ROUNDS,
38 aes_key, aes_iv);
39 if (i != AES_KEY_NBYTES) {
40 return false;
41 }
42
43 EVP_CIPHER_CTX_init(crypto_context->encryption_context);
44 EVP_CIPHER_CTX_init(crypto_context->decryption_context);
45 if (EVP_EncryptInit_ex(crypto_context->encryption_context, EVP_aes_256_cbc(), NULL, key, aes_iv)
46 != 1
47 || EVP_DecryptInit_ex(crypto_context->decryption_context, EVP_aes_256_cbc(), NULL, key,
48 aes_iv)
49 != 1)
50 {
51 return false;
52 }
53 return true;
54 }
55
56 hashkit_string_st *aes_encrypt(encryption_context_t *crypto_context, const unsigned char *source,
57 size_t source_length) {
58 EVP_CIPHER_CTX *encryption_context = crypto_context->encryption_context;
59 int cipher_length = source_length + EVP_CIPHER_CTX_block_size(encryption_context);
60 int final_length = 0;
61 unsigned char *cipher_text = (unsigned char *) malloc(cipher_length);
62 if (cipher_text == NULL) {
63 return NULL;
64 }
65 if (EVP_EncryptInit_ex(encryption_context, NULL, NULL, NULL, NULL) != 1
66 || EVP_EncryptUpdate(encryption_context, cipher_text, &cipher_length, source, source_length)
67 != 1
68 || EVP_EncryptFinal_ex(encryption_context, cipher_text + cipher_length, &final_length) != 1)
69 {
70 free(cipher_text);
71 return NULL;
72 }
73
74 hashkit_string_st *destination = hashkit_string_create(cipher_length + final_length);
75 if (destination == NULL) {
76 return NULL;
77 }
78 char *dest = hashkit_string_c_str_mutable(destination);
79 memcpy(dest, cipher_text, cipher_length + final_length);
80 hashkit_string_set_length(destination, cipher_length + final_length);
81 return destination;
82 }
83
84 hashkit_string_st *aes_decrypt(encryption_context_t *crypto_context, const unsigned char *source,
85 size_t source_length) {
86 EVP_CIPHER_CTX *decryption_context = crypto_context->decryption_context;
87 int plain_text_length = source_length;
88 int final_length = 0;
89 unsigned char *plain_text = (unsigned char *) malloc(plain_text_length);
90 if (plain_text == NULL) {
91 return NULL;
92 }
93 if (EVP_DecryptInit_ex(decryption_context, NULL, NULL, NULL, NULL) != 1
94 || EVP_DecryptUpdate(decryption_context, plain_text, &plain_text_length, source,
95 source_length)
96 != 1
97 || EVP_DecryptFinal_ex(decryption_context, plain_text + plain_text_length, &final_length)
98 != 1)
99 {
100 free(plain_text);
101 return NULL;
102 }
103
104 hashkit_string_st *destination = hashkit_string_create(plain_text_length + final_length);
105 if (destination == NULL) {
106 return NULL;
107 }
108 char *dest = hashkit_string_c_str_mutable(destination);
109 memcpy(dest, plain_text, plain_text_length + final_length);
110 hashkit_string_set_length(destination, plain_text_length + final_length);
111 return destination;
112 }
113
114 encryption_context_t *aes_clone_cryptographic_context(encryption_context_t *source) {
115 encryption_context_t *new_context = (encryption_context_t *) malloc(sizeof(encryption_context_t));
116 if (new_context == NULL)
117 return NULL;
118
119 new_context->encryption_context = EVP_CIPHER_CTX_new();
120 new_context->decryption_context = EVP_CIPHER_CTX_new();
121 if (new_context->encryption_context == NULL || new_context->decryption_context == NULL) {
122 free(new_context);
123 return NULL;
124 }
125 EVP_CIPHER_CTX_copy(new_context->encryption_context, source->encryption_context);
126 EVP_CIPHER_CTX_copy(new_context->decryption_context, source->decryption_context);
127 return new_context;
128 }
129
130 #else
131
132 # include "libhashkit/rijndael.hpp"
133
134 # define AES_KEY_LENGTH 256 /* 128, 192, 256 */
135 # define AES_BLOCK_SIZE 16
136
137 enum encrypt_t { AES_ENCRYPT, AES_DECRYPT };
138
139 struct _key_t {
140 int nr;
141 uint32_t rk[4 * (AES_MAXNR + 1)];
142 };
143
144 struct aes_key_t {
145 _key_t encode_key;
146 _key_t decode_key;
147 };
148
149 aes_key_t *aes_create_key(const char *key, const size_t key_length) {
150 aes_key_t *_aes_key = (aes_key_t *) (calloc(1, sizeof(aes_key_t)));
151 if (_aes_key) {
152 uint8_t rkey[AES_KEY_LENGTH / 8];
153 uint8_t *rkey_end = rkey + AES_KEY_LENGTH / 8;
154 const char *key_end = key + key_length;
155
156 memset(rkey, 0, sizeof(rkey)); /* Set initial key */
157
158 uint8_t *ptr = rkey;
159 const char *sptr = key;
160 for (; sptr < key_end; ptr++, sptr++) {
161 if (ptr == rkey_end) {
162 ptr = rkey; /* Just loop over tmp_key until we used all key */
163 }
164 *ptr ^= (uint8_t) (*sptr);
165 }
166
167 _aes_key->decode_key.nr = rijndaelKeySetupDec(_aes_key->decode_key.rk, rkey, AES_KEY_LENGTH);
168 _aes_key->encode_key.nr = rijndaelKeySetupEnc(_aes_key->encode_key.rk, rkey, AES_KEY_LENGTH);
169 }
170
171 return _aes_key;
172 }
173
174 aes_key_t *aes_clone_key(aes_key_t *_aes_key) {
175 if (_aes_key == NULL) {
176 return NULL;
177 }
178
179 aes_key_t *_aes_clone_key = (aes_key_t *) (calloc(1, sizeof(aes_key_t)));
180 if (_aes_clone_key) {
181 memcpy(_aes_clone_key, _aes_key, sizeof(aes_key_t));
182 }
183
184 return _aes_clone_key;
185 }
186
187 hashkit_string_st *aes_encrypt(aes_key_t *_aes_key, const char *source, size_t source_length) {
188 if (_aes_key == NULL) {
189 return NULL;
190 }
191
192 size_t num_blocks = source_length / AES_BLOCK_SIZE;
193
194 hashkit_string_st *destination = hashkit_string_create(source_length);
195 if (destination) {
196 char *dest = hashkit_string_c_str_mutable(destination);
197
198 for (size_t x = num_blocks; x > 0; x--) /* Encode complete blocks */ {
199 rijndaelEncrypt(_aes_key->encode_key.rk, _aes_key->encode_key.nr, (const uint8_t *) (source),
200 (uint8_t *) (dest));
201 source += AES_BLOCK_SIZE;
202 dest += AES_BLOCK_SIZE;
203 }
204
205 uint8_t block[AES_BLOCK_SIZE];
206 char pad_len = AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE * num_blocks);
207 memcpy(block, source, 16 - pad_len);
208 memset(block + AES_BLOCK_SIZE - pad_len, pad_len, pad_len);
209 rijndaelEncrypt(_aes_key->encode_key.rk, _aes_key->encode_key.nr, block, (uint8_t *) (dest));
210 hashkit_string_set_length(destination, AES_BLOCK_SIZE * (num_blocks + 1));
211 }
212
213 return destination;
214 }
215
216 hashkit_string_st *aes_decrypt(aes_key_t *_aes_key, const char *source, size_t source_length) {
217 if (_aes_key == NULL) {
218 return NULL;
219 }
220
221 size_t num_blocks = source_length / AES_BLOCK_SIZE;
222 if ((source_length != num_blocks * AES_BLOCK_SIZE) or num_blocks == 0) {
223 return NULL;
224 }
225
226 hashkit_string_st *destination = hashkit_string_create(source_length);
227 if (destination) {
228 char *dest = hashkit_string_c_str_mutable(destination);
229
230 for (size_t x = num_blocks - 1; x > 0; x--) {
231 rijndaelDecrypt(_aes_key->decode_key.rk, _aes_key->decode_key.nr, (const uint8_t *) (source),
232 (uint8_t *) (dest));
233 source += AES_BLOCK_SIZE;
234 dest += AES_BLOCK_SIZE;
235 }
236
237 uint8_t block[AES_BLOCK_SIZE];
238 rijndaelDecrypt(_aes_key->decode_key.rk, _aes_key->decode_key.nr, (const uint8_t *) (source),
239 block);
240 /* Use last char in the block as size */
241 unsigned int pad_len = (unsigned int) (unsigned char) (block[AES_BLOCK_SIZE - 1]);
242 if (pad_len > AES_BLOCK_SIZE) {
243 hashkit_string_free(destination);
244 return NULL;
245 }
246
247 /* We could also check whole padding but we do not really need this */
248
249 memcpy(dest, block, AES_BLOCK_SIZE - pad_len);
250 hashkit_string_set_length(destination, AES_BLOCK_SIZE * num_blocks - pad_len);
251 }
252
253 return destination;
254 }
255 #endif