2 +--------------------------------------------------------------------+
3 | libmemcached - 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 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
16 #include "libhashkit/common.h"
18 #include "libhashkit/rijndael.hpp"
22 #define AES_KEY_LENGTH 256 /* 128, 192, 256 */
23 #define AES_BLOCK_SIZE 16
25 enum encrypt_t
{ AES_ENCRYPT
, AES_DECRYPT
};
29 uint32_t rk
[4 * (AES_MAXNR
+ 1)];
37 aes_key_t
*aes_create_key(const char *key
, const size_t key_length
) {
38 aes_key_t
*_aes_key
= (aes_key_t
*) (calloc(1, sizeof(aes_key_t
)));
40 uint8_t rkey
[AES_KEY_LENGTH
/ 8];
41 uint8_t *rkey_end
= rkey
+ AES_KEY_LENGTH
/ 8;
42 const char *key_end
= key
+ key_length
;
44 memset(rkey
, 0, sizeof(rkey
)); /* Set initial key */
47 const char *sptr
= key
;
48 for (; sptr
< key_end
; ptr
++, sptr
++) {
49 if (ptr
== rkey_end
) {
50 ptr
= rkey
; /* Just loop over tmp_key until we used all key */
52 *ptr
^= (uint8_t)(*sptr
);
55 _aes_key
->decode_key
.nr
= rijndaelKeySetupDec(_aes_key
->decode_key
.rk
, rkey
, AES_KEY_LENGTH
);
56 _aes_key
->encode_key
.nr
= rijndaelKeySetupEnc(_aes_key
->encode_key
.rk
, rkey
, AES_KEY_LENGTH
);
62 aes_key_t
*aes_clone_key(aes_key_t
*_aes_key
) {
63 if (_aes_key
== NULL
) {
67 aes_key_t
*_aes_clone_key
= (aes_key_t
*) (calloc(1, sizeof(aes_key_t
)));
69 memcpy(_aes_clone_key
, _aes_key
, sizeof(aes_key_t
));
72 return _aes_clone_key
;
75 hashkit_string_st
*aes_encrypt(aes_key_t
*_aes_key
, const char *source
, size_t source_length
) {
76 if (_aes_key
== NULL
) {
80 size_t num_blocks
= source_length
/ AES_BLOCK_SIZE
;
82 hashkit_string_st
*destination
= hashkit_string_create(source_length
);
84 char *dest
= hashkit_string_c_str_mutable(destination
);
86 for (size_t x
= num_blocks
; x
> 0; x
--) /* Encode complete blocks */ {
87 rijndaelEncrypt(_aes_key
->encode_key
.rk
, _aes_key
->encode_key
.nr
, (const uint8_t *) (source
),
89 source
+= AES_BLOCK_SIZE
;
90 dest
+= AES_BLOCK_SIZE
;
93 uint8_t block
[AES_BLOCK_SIZE
];
94 char pad_len
= AES_BLOCK_SIZE
- (source_length
- AES_BLOCK_SIZE
* num_blocks
);
95 memcpy(block
, source
, 16 - pad_len
);
96 memset(block
+ AES_BLOCK_SIZE
- pad_len
, pad_len
, pad_len
);
97 rijndaelEncrypt(_aes_key
->encode_key
.rk
, _aes_key
->encode_key
.nr
, block
, (uint8_t *) (dest
));
98 hashkit_string_set_length(destination
, AES_BLOCK_SIZE
* (num_blocks
+ 1));
104 hashkit_string_st
*aes_decrypt(aes_key_t
*_aes_key
, const char *source
, size_t source_length
) {
105 if (_aes_key
== NULL
) {
109 size_t num_blocks
= source_length
/ AES_BLOCK_SIZE
;
110 if ((source_length
!= num_blocks
* AES_BLOCK_SIZE
) or num_blocks
== 0) {
114 hashkit_string_st
*destination
= hashkit_string_create(source_length
);
116 char *dest
= hashkit_string_c_str_mutable(destination
);
118 for (size_t x
= num_blocks
- 1; x
> 0; x
--) {
119 rijndaelDecrypt(_aes_key
->decode_key
.rk
, _aes_key
->decode_key
.nr
, (const uint8_t *) (source
),
121 source
+= AES_BLOCK_SIZE
;
122 dest
+= AES_BLOCK_SIZE
;
125 uint8_t block
[AES_BLOCK_SIZE
];
126 rijndaelDecrypt(_aes_key
->decode_key
.rk
, _aes_key
->decode_key
.nr
, (const uint8_t *) (source
),
128 /* Use last char in the block as size */
129 unsigned int pad_len
= (unsigned int) (unsigned char) (block
[AES_BLOCK_SIZE
- 1]);
130 if (pad_len
> AES_BLOCK_SIZE
) {
131 hashkit_string_free(destination
);
135 /* We could also check whole padding but we do not really need this */
137 memcpy(dest
, block
, AES_BLOCK_SIZE
- pad_len
);
138 hashkit_string_set_length(destination
, AES_BLOCK_SIZE
* num_blocks
- pad_len
);