156bcd3d0292fad27e0e3786a7c988a20c2fb0e1
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 +--------------------------------------------------------------------+
16 #include "libhashkit/common.h"
20 #ifdef HAVE_OPENSSL_CRYPTO
22 #include <openssl/evp.h>
24 #define DIGEST_ROUNDS 5
26 #define AES_KEY_NBYTES 32
27 #define AES_IV_NBYTES 32
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
];
37 int i
= EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), NULL
, key
, key_length
, DIGEST_ROUNDS
,
39 if (i
!= AES_KEY_NBYTES
) {
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
)
47 || EVP_DecryptInit_ex(crypto_context
->decryption_context
, EVP_aes_256_cbc(), NULL
, key
,
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
);
61 unsigned char *cipher_text
= (unsigned char *) malloc(cipher_length
);
62 if (cipher_text
== NULL
) {
65 if (EVP_EncryptInit_ex(encryption_context
, NULL
, NULL
, NULL
, NULL
) != 1
66 || EVP_EncryptUpdate(encryption_context
, cipher_text
, &cipher_length
, source
, source_length
)
68 || EVP_EncryptFinal_ex(encryption_context
, cipher_text
+ cipher_length
, &final_length
) != 1)
74 hashkit_string_st
*destination
= hashkit_string_create(cipher_length
+ final_length
);
75 if (destination
== NULL
) {
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
);
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
;
89 unsigned char *plain_text
= (unsigned char *) malloc(plain_text_length
);
90 if (plain_text
== NULL
) {
93 if (EVP_DecryptInit_ex(decryption_context
, NULL
, NULL
, NULL
, NULL
) != 1
94 || EVP_DecryptUpdate(decryption_context
, plain_text
, &plain_text_length
, source
,
97 || EVP_DecryptFinal_ex(decryption_context
, plain_text
+ plain_text_length
, &final_length
)
104 hashkit_string_st
*destination
= hashkit_string_create(plain_text_length
+ final_length
);
105 if (destination
== NULL
) {
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
);
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
)
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
) {
125 EVP_CIPHER_CTX_copy(new_context
->encryption_context
, source
->encryption_context
);
126 EVP_CIPHER_CTX_copy(new_context
->decryption_context
, source
->decryption_context
);
132 # include "libhashkit/rijndael.hpp"
134 # define AES_KEY_LENGTH 256 /* 128, 192, 256 */
135 # define AES_BLOCK_SIZE 16
137 enum encrypt_t
{ AES_ENCRYPT
, AES_DECRYPT
};
141 uint32_t rk
[4 * (AES_MAXNR
+ 1)];
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
)));
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
;
156 memset(rkey
, 0, sizeof(rkey
)); /* Set initial key */
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 */
164 *ptr
^= (uint8_t) (*sptr
);
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
);
174 aes_key_t
*aes_clone_key(aes_key_t
*_aes_key
) {
175 if (_aes_key
== NULL
) {
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
));
184 return _aes_clone_key
;
187 hashkit_string_st
*aes_encrypt(aes_key_t
*_aes_key
, const char *source
, size_t source_length
) {
188 if (_aes_key
== NULL
) {
192 size_t num_blocks
= source_length
/ AES_BLOCK_SIZE
;
194 hashkit_string_st
*destination
= hashkit_string_create(source_length
);
196 char *dest
= hashkit_string_c_str_mutable(destination
);
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
),
201 source
+= AES_BLOCK_SIZE
;
202 dest
+= AES_BLOCK_SIZE
;
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));
216 hashkit_string_st
*aes_decrypt(aes_key_t
*_aes_key
, const char *source
, size_t source_length
) {
217 if (_aes_key
== NULL
) {
221 size_t num_blocks
= source_length
/ AES_BLOCK_SIZE
;
222 if ((source_length
!= num_blocks
* AES_BLOCK_SIZE
) or num_blocks
== 0) {
226 hashkit_string_st
*destination
= hashkit_string_create(source_length
);
228 char *dest
= hashkit_string_c_str_mutable(destination
);
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
),
233 source
+= AES_BLOCK_SIZE
;
234 dest
+= AES_BLOCK_SIZE
;
237 uint8_t block
[AES_BLOCK_SIZE
];
238 rijndaelDecrypt(_aes_key
->decode_key
.rk
, _aes_key
->decode_key
.nr
, (const uint8_t *) (source
),
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
);
247 /* We could also check whole padding but we do not really need this */
249 memcpy(dest
, block
, AES_BLOCK_SIZE
- pad_len
);
250 hashkit_string_set_length(destination
, AES_BLOCK_SIZE
* num_blocks
- pad_len
);