1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5 * Copyright (C) 2012 Data Differential, http://datadifferential.com/
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
19 * * The names of its contributors may not be used to endorse or
20 * promote products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include "libhashkit/common.h"
40 #include "libhashkit/rijndael.hpp"
44 #define AES_KEY_LENGTH 256 /* 128, 192, 256 */
45 #define AES_BLOCK_SIZE 16
55 uint32_t rk
[4*(AES_MAXNR
+1)];
63 aes_key_t
* aes_create_key(const char *key
, const size_t key_length
)
65 aes_key_t
* _aes_key
= (aes_key_t
*)calloc(1, sizeof(aes_key_t
));
68 uint8_t rkey
[AES_KEY_LENGTH
/8];
69 uint8_t *rkey_end
= rkey
+AES_KEY_LENGTH
/8;
70 const char *key_end
= key
+key_length
;
72 memset(rkey
, 0, sizeof(rkey
)); /* Set initial key */
75 const char* sptr
= key
;
76 for (; sptr
< key_end
; ptr
++,sptr
++)
80 ptr
= rkey
; /* Just loop over tmp_key until we used all key */
82 *ptr
^= (uint8_t) *sptr
;
85 _aes_key
->decode_key
.nr
= rijndaelKeySetupDec(_aes_key
->decode_key
.rk
, rkey
, AES_KEY_LENGTH
);
86 _aes_key
->encode_key
.nr
= rijndaelKeySetupEnc(_aes_key
->encode_key
.rk
, rkey
, AES_KEY_LENGTH
);
92 aes_key_t
* aes_clone_key(aes_key_t
*_aes_key
)
99 aes_key_t
* _aes_clone_key
= (aes_key_t
*)calloc(1, sizeof(aes_key_t
));
102 memcpy(_aes_clone_key
, _aes_key
, sizeof(aes_key_t
));
105 return _aes_clone_key
;
108 hashkit_string_st
* aes_encrypt(aes_key_t
*_aes_key
,
109 const char* source
, size_t source_length
)
111 if (_aes_key
== NULL
)
116 size_t num_blocks
= source_length
/AES_BLOCK_SIZE
;
118 hashkit_string_st
* destination
= hashkit_string_create(source_length
);
121 char *dest
= hashkit_string_c_str_mutable(destination
);
123 for (size_t x
= num_blocks
; x
> 0; x
--) /* Encode complete blocks */
125 rijndaelEncrypt(_aes_key
->encode_key
.rk
, _aes_key
->encode_key
.nr
, (const uint8_t*) source
,
127 source
+= AES_BLOCK_SIZE
;
128 dest
+= AES_BLOCK_SIZE
;
131 uint8_t block
[AES_BLOCK_SIZE
];
132 char pad_len
= AES_BLOCK_SIZE
- (source_length
- AES_BLOCK_SIZE
*num_blocks
);
133 memcpy(block
, source
, 16 -pad_len
);
134 memset(block
+ AES_BLOCK_SIZE
-pad_len
, pad_len
, pad_len
);
135 rijndaelEncrypt(_aes_key
->encode_key
.rk
, _aes_key
->encode_key
.nr
, block
, (uint8_t*) dest
);
136 hashkit_string_set_length(destination
, AES_BLOCK_SIZE
*(num_blocks
+ 1));
142 hashkit_string_st
* aes_decrypt(aes_key_t
*_aes_key
,
143 const char* source
, size_t source_length
)
145 if (_aes_key
== NULL
)
150 size_t num_blocks
= source_length
/AES_BLOCK_SIZE
;
151 if ((source_length
!= num_blocks
*AES_BLOCK_SIZE
) or num_blocks
==0 )
156 hashkit_string_st
* destination
= hashkit_string_create(source_length
);
159 char *dest
= hashkit_string_c_str_mutable(destination
);
161 for (size_t x
= num_blocks
-1; x
> 0; x
--)
163 rijndaelDecrypt(_aes_key
->decode_key
.rk
, _aes_key
->decode_key
.nr
, (const uint8_t*) source
, (uint8_t*) dest
);
164 source
+= AES_BLOCK_SIZE
;
165 dest
+= AES_BLOCK_SIZE
;
168 uint8_t block
[AES_BLOCK_SIZE
];
169 rijndaelDecrypt(_aes_key
->decode_key
.rk
, _aes_key
->decode_key
.nr
, (const uint8_t*) source
, block
);
170 /* Use last char in the block as size */
171 unsigned int pad_len
= (unsigned int) (unsigned char) block
[AES_BLOCK_SIZE
-1];
172 if (pad_len
> AES_BLOCK_SIZE
)
174 hashkit_string_free(destination
);
178 /* We could also check whole padding but we do not really need this */
180 memcpy(dest
, block
, AES_BLOCK_SIZE
- pad_len
);
181 hashkit_string_set_length(destination
, AES_BLOCK_SIZE
*num_blocks
- pad_len
);