blob: 7cfdc1c06ab2a2594456400f7705863bc567d2ee [file] [log] [blame]
Dees_Troy83bd4832013-05-04 12:39:56 +00001/*
2 * ---------------------------------------------------------------------------
3 * OpenAES License
4 * ---------------------------------------------------------------------------
5 * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 * ---------------------------------------------------------------------------
29 */
30static const char _NR[] = {
31 0x4e,0x61,0x62,0x69,0x6c,0x20,0x53,0x2e,0x20,
32 0x41,0x6c,0x20,0x52,0x61,0x6d,0x6c,0x69,0x00 };
33
34#include <stddef.h>
35#include <time.h>
36#include <sys/timeb.h>
37#include <malloc.h>
38#include <string.h>
39
40#ifdef WIN32
41#include <process.h>
42#endif
43
44#include "oaes_config.h"
45#include "oaes_lib.h"
46
47#ifdef OAES_HAVE_ISAAC
48#include "rand.h"
49#endif // OAES_HAVE_ISAAC
50
51#define OAES_RKEY_LEN 4
52#define OAES_COL_LEN 4
53#define OAES_ROUND_BASE 7
54
55// the block is padded
56#define OAES_FLAG_PAD 0x01
57
58#ifndef min
59# define min(a,b) (((a)<(b)) ? (a) : (b))
60#endif /* min */
61
62typedef struct _oaes_key
63{
64 size_t data_len;
65 uint8_t *data;
66 size_t exp_data_len;
67 uint8_t *exp_data;
68 size_t num_keys;
69 size_t key_base;
70} oaes_key;
71
72typedef struct _oaes_ctx
73{
74#ifdef OAES_HAVE_ISAAC
75 randctx * rctx;
76#endif // OAES_HAVE_ISAAC
77
78#ifdef OAES_DEBUG
79 oaes_step_cb step_cb;
80#endif // OAES_DEBUG
81
82 oaes_key * key;
83 OAES_OPTION options;
84 uint8_t iv[OAES_BLOCK_SIZE];
85} oaes_ctx;
86
87// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>"
88static uint8_t oaes_header[OAES_BLOCK_SIZE] = {
89 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
90 /*0*/ 0x4f, 0x41, 0x45, 0x53, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91};
92static uint8_t oaes_gf_8[] = {
93 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
94
95static uint8_t oaes_sub_byte_value[16][16] = {
96 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
97 /*0*/ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
98 /*1*/ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
99 /*2*/ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
100 /*3*/ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
101 /*4*/ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
102 /*5*/ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
103 /*6*/ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
104 /*7*/ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
105 /*8*/ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
106 /*9*/ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
107 /*a*/ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
108 /*b*/ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
109 /*c*/ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
110 /*d*/ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
111 /*e*/ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
112 /*f*/ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
113};
114
115static uint8_t oaes_inv_sub_byte_value[16][16] = {
116 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
117 /*0*/ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
118 /*1*/ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
119 /*2*/ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
120 /*3*/ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
121 /*4*/ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
122 /*5*/ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
123 /*6*/ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
124 /*7*/ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
125 /*8*/ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
126 /*9*/ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
127 /*a*/ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
128 /*b*/ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
129 /*c*/ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
130 /*d*/ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
131 /*e*/ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
132 /*f*/ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
133};
134
135static uint8_t oaes_gf_mul_2[16][16] = {
136 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
137 /*0*/ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
138 /*1*/ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
139 /*2*/ 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
140 /*3*/ 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
141 /*4*/ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
142 /*5*/ 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
143 /*6*/ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
144 /*7*/ 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
145 /*8*/ 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
146 /*9*/ 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
147 /*a*/ 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
148 /*b*/ 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
149 /*c*/ 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
150 /*d*/ 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
151 /*e*/ 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
152 /*f*/ 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
153};
154
155static uint8_t oaes_gf_mul_3[16][16] = {
156 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
157 /*0*/ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
158 /*1*/ 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
159 /*2*/ 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
160 /*3*/ 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
161 /*4*/ 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
162 /*5*/ 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
163 /*6*/ 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
164 /*7*/ 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
165 /*8*/ 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
166 /*9*/ 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
167 /*a*/ 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
168 /*b*/ 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
169 /*c*/ 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
170 /*d*/ 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
171 /*e*/ 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
172 /*f*/ 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
173};
174
175static uint8_t oaes_gf_mul_9[16][16] = {
176 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
177 /*0*/ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
178 /*1*/ 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
179 /*2*/ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
180 /*3*/ 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
181 /*4*/ 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
182 /*5*/ 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
183 /*6*/ 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
184 /*7*/ 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
185 /*8*/ 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
186 /*9*/ 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
187 /*a*/ 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
188 /*b*/ 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
189 /*c*/ 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
190 /*d*/ 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
191 /*e*/ 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
192 /*f*/ 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
193};
194
195static uint8_t oaes_gf_mul_b[16][16] = {
196 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
197 /*0*/ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
198 /*1*/ 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
199 /*2*/ 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
200 /*3*/ 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
201 /*4*/ 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
202 /*5*/ 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
203 /*6*/ 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
204 /*7*/ 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
205 /*8*/ 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
206 /*9*/ 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
207 /*a*/ 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
208 /*b*/ 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
209 /*c*/ 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
210 /*d*/ 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
211 /*e*/ 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
212 /*f*/ 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
213};
214
215static uint8_t oaes_gf_mul_d[16][16] = {
216 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
217 /*0*/ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
218 /*1*/ 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
219 /*2*/ 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
220 /*3*/ 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
221 /*4*/ 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
222 /*5*/ 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
223 /*6*/ 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
224 /*7*/ 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
225 /*8*/ 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
226 /*9*/ 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
227 /*a*/ 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
228 /*b*/ 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
229 /*c*/ 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
230 /*d*/ 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
231 /*e*/ 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
232 /*f*/ 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
233};
234
235static uint8_t oaes_gf_mul_e[16][16] = {
236 // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
237 /*0*/ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
238 /*1*/ 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
239 /*2*/ 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
240 /*3*/ 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
241 /*4*/ 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
242 /*5*/ 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
243 /*6*/ 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
244 /*7*/ 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
245 /*8*/ 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
246 /*9*/ 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
247 /*a*/ 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
248 /*b*/ 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
249 /*c*/ 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
250 /*d*/ 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
251 /*e*/ 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
252 /*f*/ 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
253};
254
255static OAES_RET oaes_sub_byte( uint8_t * byte )
256{
257 size_t _x, _y;
258
259 if( NULL == byte )
260 return OAES_RET_ARG1;
261
262 _x = _y = *byte;
263 _x &= 0x0f;
264 _y &= 0xf0;
265 _y >>= 4;
266 *byte = oaes_sub_byte_value[_y][_x];
267
268 return OAES_RET_SUCCESS;
269}
270
271static OAES_RET oaes_inv_sub_byte( uint8_t * byte )
272{
273 size_t _x, _y;
274
275 if( NULL == byte )
276 return OAES_RET_ARG1;
277
278 _x = _y = *byte;
279 _x &= 0x0f;
280 _y &= 0xf0;
281 _y >>= 4;
282 *byte = oaes_inv_sub_byte_value[_y][_x];
283
284 return OAES_RET_SUCCESS;
285}
286
287static OAES_RET oaes_word_rot_right( uint8_t word[OAES_COL_LEN] )
288{
289 uint8_t _temp[OAES_COL_LEN];
290
291 if( NULL == word )
292 return OAES_RET_ARG1;
293
294 memcpy( _temp + 1, word, OAES_COL_LEN - 1 );
295 _temp[0] = word[OAES_COL_LEN - 1];
296 memcpy( word, _temp, OAES_COL_LEN );
297
298 return OAES_RET_SUCCESS;
299}
300
301static OAES_RET oaes_word_rot_left( uint8_t word[OAES_COL_LEN] )
302{
303 uint8_t _temp[OAES_COL_LEN];
304
305 if( NULL == word )
306 return OAES_RET_ARG1;
307
308 memcpy( _temp, word + 1, OAES_COL_LEN - 1 );
309 _temp[OAES_COL_LEN - 1] = word[0];
310 memcpy( word, _temp, OAES_COL_LEN );
311
312 return OAES_RET_SUCCESS;
313}
314
315static OAES_RET oaes_shift_rows( uint8_t block[OAES_BLOCK_SIZE] )
316{
317 uint8_t _temp[OAES_BLOCK_SIZE];
318
319 if( NULL == block )
320 return OAES_RET_ARG1;
321
322 _temp[0x00] = block[0x00];
323 _temp[0x01] = block[0x05];
324 _temp[0x02] = block[0x0a];
325 _temp[0x03] = block[0x0f];
326 _temp[0x04] = block[0x04];
327 _temp[0x05] = block[0x09];
328 _temp[0x06] = block[0x0e];
329 _temp[0x07] = block[0x03];
330 _temp[0x08] = block[0x08];
331 _temp[0x09] = block[0x0d];
332 _temp[0x0a] = block[0x02];
333 _temp[0x0b] = block[0x07];
334 _temp[0x0c] = block[0x0c];
335 _temp[0x0d] = block[0x01];
336 _temp[0x0e] = block[0x06];
337 _temp[0x0f] = block[0x0b];
338 memcpy( block, _temp, OAES_BLOCK_SIZE );
339
340 return OAES_RET_SUCCESS;
341}
342
343static OAES_RET oaes_inv_shift_rows( uint8_t block[OAES_BLOCK_SIZE] )
344{
345 uint8_t _temp[OAES_BLOCK_SIZE];
346
347 if( NULL == block )
348 return OAES_RET_ARG1;
349
350 _temp[0x00] = block[0x00];
351 _temp[0x01] = block[0x0d];
352 _temp[0x02] = block[0x0a];
353 _temp[0x03] = block[0x07];
354 _temp[0x04] = block[0x04];
355 _temp[0x05] = block[0x01];
356 _temp[0x06] = block[0x0e];
357 _temp[0x07] = block[0x0b];
358 _temp[0x08] = block[0x08];
359 _temp[0x09] = block[0x05];
360 _temp[0x0a] = block[0x02];
361 _temp[0x0b] = block[0x0f];
362 _temp[0x0c] = block[0x0c];
363 _temp[0x0d] = block[0x09];
364 _temp[0x0e] = block[0x06];
365 _temp[0x0f] = block[0x03];
366 memcpy( block, _temp, OAES_BLOCK_SIZE );
367
368 return OAES_RET_SUCCESS;
369}
370
371static uint8_t oaes_gf_mul(uint8_t left, uint8_t right)
372{
373 size_t _x, _y;
374
375 _x = _y = left;
376 _x &= 0x0f;
377 _y &= 0xf0;
378 _y >>= 4;
379
380 switch( right )
381 {
382 case 0x02:
383 return oaes_gf_mul_2[_y][_x];
384 break;
385 case 0x03:
386 return oaes_gf_mul_3[_y][_x];
387 break;
388 case 0x09:
389 return oaes_gf_mul_9[_y][_x];
390 break;
391 case 0x0b:
392 return oaes_gf_mul_b[_y][_x];
393 break;
394 case 0x0d:
395 return oaes_gf_mul_d[_y][_x];
396 break;
397 case 0x0e:
398 return oaes_gf_mul_e[_y][_x];
399 break;
400 default:
401 return left;
402 break;
403 }
404}
405
406static OAES_RET oaes_mix_cols( uint8_t word[OAES_COL_LEN] )
407{
408 uint8_t _temp[OAES_COL_LEN];
409
410 if( NULL == word )
411 return OAES_RET_ARG1;
412
413 _temp[0] = oaes_gf_mul(word[0], 0x02) ^ oaes_gf_mul( word[1], 0x03 ) ^
414 word[2] ^ word[3];
415 _temp[1] = word[0] ^ oaes_gf_mul( word[1], 0x02 ) ^
416 oaes_gf_mul( word[2], 0x03 ) ^ word[3];
417 _temp[2] = word[0] ^ word[1] ^
418 oaes_gf_mul( word[2], 0x02 ) ^ oaes_gf_mul( word[3], 0x03 );
419 _temp[3] = oaes_gf_mul( word[0], 0x03 ) ^ word[1] ^
420 word[2] ^ oaes_gf_mul( word[3], 0x02 );
421 memcpy( word, _temp, OAES_COL_LEN );
422
423 return OAES_RET_SUCCESS;
424}
425
426static OAES_RET oaes_inv_mix_cols( uint8_t word[OAES_COL_LEN] )
427{
428 uint8_t _temp[OAES_COL_LEN];
429
430 if( NULL == word )
431 return OAES_RET_ARG1;
432
433 _temp[0] = oaes_gf_mul( word[0], 0x0e ) ^ oaes_gf_mul( word[1], 0x0b ) ^
434 oaes_gf_mul( word[2], 0x0d ) ^ oaes_gf_mul( word[3], 0x09 );
435 _temp[1] = oaes_gf_mul( word[0], 0x09 ) ^ oaes_gf_mul( word[1], 0x0e ) ^
436 oaes_gf_mul( word[2], 0x0b ) ^ oaes_gf_mul( word[3], 0x0d );
437 _temp[2] = oaes_gf_mul( word[0], 0x0d ) ^ oaes_gf_mul( word[1], 0x09 ) ^
438 oaes_gf_mul( word[2], 0x0e ) ^ oaes_gf_mul( word[3], 0x0b );
439 _temp[3] = oaes_gf_mul( word[0], 0x0b ) ^ oaes_gf_mul( word[1], 0x0d ) ^
440 oaes_gf_mul( word[2], 0x09 ) ^ oaes_gf_mul( word[3], 0x0e );
441 memcpy( word, _temp, OAES_COL_LEN );
442
443 return OAES_RET_SUCCESS;
444}
445
446OAES_RET oaes_sprintf(
447 char * buf, size_t * buf_len, const uint8_t * data, size_t data_len )
448{
449 size_t _i, _buf_len_in;
450 char _temp[4];
451
452 if( NULL == buf_len )
453 return OAES_RET_ARG2;
454
455 _buf_len_in = *buf_len;
456 *buf_len = data_len * 3 + data_len / OAES_BLOCK_SIZE + 1;
457
458 if( NULL == buf )
459 return OAES_RET_SUCCESS;
460
461 if( *buf_len > _buf_len_in )
462 return OAES_RET_BUF;
463
464 if( NULL == data )
465 return OAES_RET_ARG3;
466
467 strcpy( buf, "" );
468
469 for( _i = 0; _i < data_len; _i++ )
470 {
471 sprintf( _temp, "%02x ", data[_i] );
472 strcat( buf, _temp );
473 if( _i && 0 == ( _i + 1 ) % OAES_BLOCK_SIZE )
474 strcat( buf, "\n" );
475 }
476
477 return OAES_RET_SUCCESS;
478}
479
480#ifdef OAES_HAVE_ISAAC
481static void oaes_get_seed( char buf[RANDSIZ + 1] )
482{
483 struct timeb timer;
484 struct tm *gmTimer;
485 char * _test = NULL;
486
487 ftime (&timer);
488 gmTimer = gmtime( &timer.time );
489 _test = (char *) calloc( sizeof( char ), timer.millitm );
490 sprintf( buf, "%04d%02d%02d%02d%02d%02d%03d%p%d",
491 gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday,
492 gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.millitm,
493 _test + timer.millitm, getpid() );
494
495 if( _test )
496 free( _test );
497}
498#else
499static uint32_t oaes_get_seed()
500{
501 struct timeb timer;
502 struct tm *gmTimer;
503 char * _test = NULL;
504 uint32_t _ret = 0;
505
506 ftime (&timer);
507 gmTimer = gmtime( &timer.time );
508 _test = (char *) calloc( sizeof( char ), timer.millitm );
509 _ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday +
510 gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm +
511 (uint32_t) ( _test + timer.millitm ) + getpid();
512
513 if( _test )
514 free( _test );
515
516 return _ret;
517}
518#endif // OAES_HAVE_ISAAC
519
520static OAES_RET oaes_key_destroy( oaes_key ** key )
521{
522 if( NULL == *key )
523 return OAES_RET_SUCCESS;
524
525 if( (*key)->data )
526 {
527 free( (*key)->data );
528 (*key)->data = NULL;
529 }
530
531 if( (*key)->exp_data )
532 {
533 free( (*key)->exp_data );
534 (*key)->exp_data = NULL;
535 }
536
537 (*key)->data_len = 0;
538 (*key)->exp_data_len = 0;
539 (*key)->num_keys = 0;
540 (*key)->key_base = 0;
541 free( *key );
542 *key = NULL;
543
544 return OAES_RET_SUCCESS;
545}
546
547static OAES_RET oaes_key_expand( OAES_CTX * ctx )
548{
549 size_t _i, _j;
550 oaes_ctx * _ctx = (oaes_ctx *) ctx;
551
552 if( NULL == _ctx )
553 return OAES_RET_ARG1;
554
555 if( NULL == _ctx->key )
556 return OAES_RET_NOKEY;
557
558 _ctx->key->key_base = _ctx->key->data_len / OAES_RKEY_LEN;
559 _ctx->key->num_keys = _ctx->key->key_base + OAES_ROUND_BASE;
560
561 _ctx->key->exp_data_len = _ctx->key->num_keys * OAES_RKEY_LEN * OAES_COL_LEN;
562 _ctx->key->exp_data = (uint8_t *)
563 calloc( _ctx->key->exp_data_len, sizeof( uint8_t ));
564
565 if( NULL == _ctx->key->exp_data )
566 return OAES_RET_MEM;
567
568 // the first _ctx->key->data_len are a direct copy
569 memcpy( _ctx->key->exp_data, _ctx->key->data, _ctx->key->data_len );
570
571 // apply ExpandKey algorithm for remainder
572 for( _i = _ctx->key->key_base; _i < _ctx->key->num_keys * OAES_RKEY_LEN; _i++ )
573 {
574 uint8_t _temp[OAES_COL_LEN];
575
576 memcpy( _temp,
577 _ctx->key->exp_data + ( _i - 1 ) * OAES_RKEY_LEN, OAES_COL_LEN );
578
579 // transform key column
580 if( 0 == _i % _ctx->key->key_base )
581 {
582 oaes_word_rot_left( _temp );
583
584 for( _j = 0; _j < OAES_COL_LEN; _j++ )
585 oaes_sub_byte( _temp + _j );
586
587 _temp[0] = _temp[0] ^ oaes_gf_8[ _i / _ctx->key->key_base - 1 ];
588 }
589 else if( _ctx->key->key_base > 6 && 4 == _i % _ctx->key->key_base )
590 {
591 for( _j = 0; _j < OAES_COL_LEN; _j++ )
592 oaes_sub_byte( _temp + _j );
593 }
594
595 for( _j = 0; _j < OAES_COL_LEN; _j++ )
596 {
597 _ctx->key->exp_data[ _i * OAES_RKEY_LEN + _j ] =
598 _ctx->key->exp_data[ ( _i - _ctx->key->key_base ) *
599 OAES_RKEY_LEN + _j ] ^ _temp[_j];
600 }
601 }
602
603 return OAES_RET_SUCCESS;
604}
605
606static OAES_RET oaes_key_gen( OAES_CTX * ctx, size_t key_size )
607{
608 size_t _i;
609 oaes_key * _key = NULL;
610 oaes_ctx * _ctx = (oaes_ctx *) ctx;
611 OAES_RET _rc = OAES_RET_SUCCESS;
612
613 if( NULL == _ctx )
614 return OAES_RET_ARG1;
615
616 _key = (oaes_key *) calloc( sizeof( oaes_key ), 1 );
617
618 if( NULL == _key )
619 return OAES_RET_MEM;
620
621 if( _ctx->key )
622 oaes_key_destroy( &(_ctx->key) );
623
624 _key->data_len = key_size;
625 _key->data = (uint8_t *) calloc( key_size, sizeof( uint8_t ));
626
627 if( NULL == _key->data )
628 return OAES_RET_MEM;
629
630 for( _i = 0; _i < key_size; _i++ )
631#ifdef OAES_HAVE_ISAAC
632 _key->data[_i] = (uint8_t) rand( _ctx->rctx );
633#else
634 _key->data[_i] = (uint8_t) rand();
635#endif // OAES_HAVE_ISAAC
636
637 _ctx->key = _key;
638 _rc = _rc || oaes_key_expand( ctx );
639
640 if( _rc != OAES_RET_SUCCESS )
641 {
642 oaes_key_destroy( &(_ctx->key) );
643 return _rc;
644 }
645
646 return OAES_RET_SUCCESS;
647}
648
649OAES_RET oaes_key_gen_128( OAES_CTX * ctx )
650{
651 return oaes_key_gen( ctx, 16 );
652}
653
654OAES_RET oaes_key_gen_192( OAES_CTX * ctx )
655{
656 return oaes_key_gen( ctx, 24 );
657}
658
659OAES_RET oaes_key_gen_256( OAES_CTX * ctx )
660{
661 return oaes_key_gen( ctx, 32 );
662}
663
664OAES_RET oaes_key_export( OAES_CTX * ctx,
665 uint8_t * data, size_t * data_len )
666{
667 size_t _data_len_in;
668 oaes_ctx * _ctx = (oaes_ctx *) ctx;
669
670 if( NULL == _ctx )
671 return OAES_RET_ARG1;
672
673 if( NULL == _ctx->key )
674 return OAES_RET_NOKEY;
675
676 if( NULL == data_len )
677 return OAES_RET_ARG3;
678
679 _data_len_in = *data_len;
680 // data + header
681 *data_len = _ctx->key->data_len + OAES_BLOCK_SIZE;
682
683 if( NULL == data )
684 return OAES_RET_SUCCESS;
685
686 if( _data_len_in < *data_len )
687 return OAES_RET_BUF;
688
689 // header
690 memcpy( data, oaes_header, OAES_BLOCK_SIZE );
691 data[5] = 0x01;
692 data[7] = _ctx->key->data_len;
693 memcpy( data + OAES_BLOCK_SIZE, _ctx->key->data, _ctx->key->data_len );
694
695 return OAES_RET_SUCCESS;
696}
697
698OAES_RET oaes_key_export_data( OAES_CTX * ctx,
699 uint8_t * data, size_t * data_len )
700{
701 size_t _data_len_in;
702 oaes_ctx * _ctx = (oaes_ctx *) ctx;
703
704 if( NULL == _ctx )
705 return OAES_RET_ARG1;
706
707 if( NULL == _ctx->key )
708 return OAES_RET_NOKEY;
709
710 if( NULL == data_len )
711 return OAES_RET_ARG3;
712
713 _data_len_in = *data_len;
714 *data_len = _ctx->key->data_len;
715
716 if( NULL == data )
717 return OAES_RET_SUCCESS;
718
719 if( _data_len_in < *data_len )
720 return OAES_RET_BUF;
721
722 memcpy( data, _ctx->key->data, *data_len );
723
724 return OAES_RET_SUCCESS;
725}
726
727OAES_RET oaes_key_import( OAES_CTX * ctx,
728 const uint8_t * data, size_t data_len )
729{
730 oaes_ctx * _ctx = (oaes_ctx *) ctx;
731 OAES_RET _rc = OAES_RET_SUCCESS;
732 int _key_length;
733
734 if( NULL == _ctx )
735 return OAES_RET_ARG1;
736
737 if( NULL == data )
738 return OAES_RET_ARG2;
739
740 switch( data_len )
741 {
742 case 16 + OAES_BLOCK_SIZE:
743 case 24 + OAES_BLOCK_SIZE:
744 case 32 + OAES_BLOCK_SIZE:
745 break;
746 default:
747 return OAES_RET_ARG3;
748 }
749
750 // header
751 if( 0 != memcmp( data, oaes_header, 4 ) )
752 return OAES_RET_HEADER;
753
754 // header version
755 switch( data[4] )
756 {
757 case 0x01:
758 break;
759 default:
760 return OAES_RET_HEADER;
761 }
762
763 // header type
764 switch( data[5] )
765 {
766 case 0x01:
767 break;
768 default:
769 return OAES_RET_HEADER;
770 }
771
772 // options
773 _key_length = data[7];
774 switch( _key_length )
775 {
776 case 16:
777 case 24:
778 case 32:
779 break;
780 default:
781 return OAES_RET_HEADER;
782 }
783
784 if( data_len != _key_length + OAES_BLOCK_SIZE )
785 return OAES_RET_ARG3;
786
787 if( _ctx->key )
788 oaes_key_destroy( &(_ctx->key) );
789
790 _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 );
791
792 if( NULL == _ctx->key )
793 return OAES_RET_MEM;
794
795 _ctx->key->data_len = _key_length;
796 _ctx->key->data = (uint8_t *)
797 calloc( _key_length, sizeof( uint8_t ));
798
799 if( NULL == _ctx->key->data )
800 {
801 oaes_key_destroy( &(_ctx->key) );
802 return OAES_RET_MEM;
803 }
804
805 memcpy( _ctx->key->data, data + OAES_BLOCK_SIZE, _key_length );
806 _rc = _rc || oaes_key_expand( ctx );
807
808 if( _rc != OAES_RET_SUCCESS )
809 {
810 oaes_key_destroy( &(_ctx->key) );
811 return _rc;
812 }
813
814 return OAES_RET_SUCCESS;
815}
816
817OAES_RET oaes_key_import_data( OAES_CTX * ctx,
818 const uint8_t * data, size_t data_len )
819{
820 oaes_ctx * _ctx = (oaes_ctx *) ctx;
821 OAES_RET _rc = OAES_RET_SUCCESS;
822
823 if( NULL == _ctx )
824 return OAES_RET_ARG1;
825
826 if( NULL == data )
827 return OAES_RET_ARG2;
828
829 switch( data_len )
830 {
831 case 16:
832 case 24:
833 case 32:
834 break;
835 default:
836 return OAES_RET_ARG3;
837 }
838
839 if( _ctx->key )
840 oaes_key_destroy( &(_ctx->key) );
841
842 _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 );
843
844 if( NULL == _ctx->key )
845 return OAES_RET_MEM;
846
847 _ctx->key->data_len = data_len;
848 _ctx->key->data = (uint8_t *)
849 calloc( data_len, sizeof( uint8_t ));
850
851 if( NULL == _ctx->key->data )
852 {
853 oaes_key_destroy( &(_ctx->key) );
854 return OAES_RET_MEM;
855 }
856
857 memcpy( _ctx->key->data, data, data_len );
858 _rc = _rc || oaes_key_expand( ctx );
859
860 if( _rc != OAES_RET_SUCCESS )
861 {
862 oaes_key_destroy( &(_ctx->key) );
863 return _rc;
864 }
865
866 return OAES_RET_SUCCESS;
867}
868
869OAES_CTX * oaes_alloc()
870{
871 oaes_ctx * _ctx = (oaes_ctx *) calloc( sizeof( oaes_ctx ), 1 );
872
873 if( NULL == _ctx )
874 return NULL;
875
876#ifdef OAES_HAVE_ISAAC
877 {
878 ub4 _i = 0;
879 char _seed[RANDSIZ + 1];
880
881 _ctx->rctx = (randctx *) calloc( sizeof( randctx ), 1 );
882
883 if( NULL == _ctx->rctx )
884 {
885 free( _ctx );
886 return NULL;
887 }
888
889 oaes_get_seed( _seed );
890 memset( _ctx->rctx->randrsl, 0, RANDSIZ );
891 memcpy( _ctx->rctx->randrsl, _seed, RANDSIZ );
892 randinit( _ctx->rctx, TRUE);
893 }
894#else
895 srand( oaes_get_seed() );
896#endif // OAES_HAVE_ISAAC
897
898 _ctx->key = NULL;
899 oaes_set_option( _ctx, OAES_OPTION_CBC, NULL );
900
901#ifdef OAES_DEBUG
902 _ctx->step_cb = NULL;
903 oaes_set_option( _ctx, OAES_OPTION_STEP_OFF, NULL );
904#endif // OAES_DEBUG
905
906 return (OAES_CTX *) _ctx;
907}
908
909OAES_RET oaes_free( OAES_CTX ** ctx )
910{
911 oaes_ctx ** _ctx = (oaes_ctx **) ctx;
912
913 if( NULL == _ctx )
914 return OAES_RET_ARG1;
915
916 if( NULL == *_ctx )
917 return OAES_RET_SUCCESS;
918
919 if( (*_ctx)->key )
920 oaes_key_destroy( &((*_ctx)->key) );
921
922#ifdef OAES_HAVE_ISAAC
923 if( (*_ctx)->rctx )
924 {
925 free( (*_ctx)->rctx );
926 (*_ctx)->rctx = NULL;
927 }
928#endif // OAES_HAVE_ISAAC
929
930 free( *_ctx );
931 *_ctx = NULL;
932
933 return OAES_RET_SUCCESS;
934}
935
936OAES_RET oaes_set_option( OAES_CTX * ctx,
937 OAES_OPTION option, const void * value )
938{
939 size_t _i;
940 oaes_ctx * _ctx = (oaes_ctx *) ctx;
941
942 if( NULL == _ctx )
943 return OAES_RET_ARG1;
944
945 switch( option )
946 {
947 case OAES_OPTION_ECB:
948 _ctx->options &= ~OAES_OPTION_CBC;
949 memset( _ctx->iv, 0, OAES_BLOCK_SIZE );
950 break;
951
952 case OAES_OPTION_CBC:
953 _ctx->options &= ~OAES_OPTION_ECB;
954 if( value )
955 memcpy( _ctx->iv, value, OAES_BLOCK_SIZE );
956 else
957 {
958 for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ )
959#ifdef OAES_HAVE_ISAAC
960 _ctx->iv[_i] = (uint8_t) rand( _ctx->rctx );
961#else
962 _ctx->iv[_i] = (uint8_t) rand();
963#endif // OAES_HAVE_ISAAC
964 }
965 break;
966
967#ifdef OAES_DEBUG
968
969 case OAES_OPTION_STEP_ON:
970 if( value )
971 {
972 _ctx->options &= ~OAES_OPTION_STEP_OFF;
973 _ctx->step_cb = value;
974 }
975 else
976 {
977 _ctx->options &= ~OAES_OPTION_STEP_ON;
978 _ctx->options |= OAES_OPTION_STEP_OFF;
979 _ctx->step_cb = NULL;
980 return OAES_RET_ARG3;
981 }
982 break;
983
984 case OAES_OPTION_STEP_OFF:
985 _ctx->options &= ~OAES_OPTION_STEP_ON;
986 _ctx->step_cb = NULL;
987 break;
988
989#endif // OAES_DEBUG
990
991 default:
992 return OAES_RET_ARG2;
993 }
994
995 _ctx->options |= option;
996
997 return OAES_RET_SUCCESS;
998}
999
1000static OAES_RET oaes_encrypt_block(
1001 OAES_CTX * ctx, uint8_t * c, size_t c_len )
1002{
1003 size_t _i, _j;
1004 oaes_ctx * _ctx = (oaes_ctx *) ctx;
1005
1006 if( NULL == _ctx )
1007 return OAES_RET_ARG1;
1008
1009 if( NULL == c )
1010 return OAES_RET_ARG2;
1011
1012 if( c_len != OAES_BLOCK_SIZE )
1013 return OAES_RET_ARG3;
1014
1015 if( NULL == _ctx->key )
1016 return OAES_RET_NOKEY;
1017
1018#ifdef OAES_DEBUG
1019 if( _ctx->step_cb )
1020 _ctx->step_cb( c, "input", 1, NULL );
1021#endif // OAES_DEBUG
1022
1023 // AddRoundKey(State, K0)
1024 for( _i = 0; _i < c_len; _i++ )
1025 c[_i] = c[_i] ^ _ctx->key->exp_data[_i];
1026
1027#ifdef OAES_DEBUG
1028 if( _ctx->step_cb )
1029 {
1030 _ctx->step_cb( _ctx->key->exp_data, "k_sch", 1, NULL );
1031 _ctx->step_cb( c, "k_add", 1, NULL );
1032 }
1033#endif // OAES_DEBUG
1034
1035 // for round = 1 step 1 to Nr–1
1036 for( _i = 1; _i < _ctx->key->num_keys - 1; _i++ )
1037 {
1038 // SubBytes(state)
1039 for( _j = 0; _j < c_len; _j++ )
1040 oaes_sub_byte( c + _j );
1041
1042#ifdef OAES_DEBUG
1043 if( _ctx->step_cb )
1044 _ctx->step_cb( c, "s_box", _i, NULL );
1045#endif // OAES_DEBUG
1046
1047 // ShiftRows(state)
1048 oaes_shift_rows( c );
1049
1050#ifdef OAES_DEBUG
1051 if( _ctx->step_cb )
1052 _ctx->step_cb( c, "s_row", _i, NULL );
1053#endif // OAES_DEBUG
1054
1055 // MixColumns(state)
1056 oaes_mix_cols( c );
1057 oaes_mix_cols( c + 4 );
1058 oaes_mix_cols( c + 8 );
1059 oaes_mix_cols( c + 12 );
1060
1061#ifdef OAES_DEBUG
1062 if( _ctx->step_cb )
1063 _ctx->step_cb( c, "m_col", _i, NULL );
1064#endif // OAES_DEBUG
1065
1066 // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1])
1067 for( _j = 0; _j < c_len; _j++ )
1068 c[_j] = c[_j] ^
1069 _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j];
1070
1071#ifdef OAES_DEBUG
1072 if( _ctx->step_cb )
1073 {
1074 _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN,
1075 "k_sch", _i, NULL );
1076 _ctx->step_cb( c, "k_add", _i, NULL );
1077 }
1078#endif // OAES_DEBUG
1079
1080 }
1081
1082 // SubBytes(state)
1083 for( _i = 0; _i < c_len; _i++ )
1084 oaes_sub_byte( c + _i );
1085
1086#ifdef OAES_DEBUG
1087 if( _ctx->step_cb )
1088 _ctx->step_cb( c, "s_box", _ctx->key->num_keys - 1, NULL );
1089#endif // OAES_DEBUG
1090
1091 // ShiftRows(state)
1092 oaes_shift_rows( c );
1093
1094#ifdef OAES_DEBUG
1095 if( _ctx->step_cb )
1096 _ctx->step_cb( c, "s_row", _ctx->key->num_keys - 1, NULL );
1097#endif // OAES_DEBUG
1098
1099 // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
1100 for( _i = 0; _i < c_len; _i++ )
1101 c[_i] = c[_i] ^ _ctx->key->exp_data[
1102 ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ];
1103
1104#ifdef OAES_DEBUG
1105 if( _ctx->step_cb )
1106 {
1107 _ctx->step_cb( _ctx->key->exp_data +
1108 ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN,
1109 "k_sch", _ctx->key->num_keys - 1, NULL );
1110 _ctx->step_cb( c, "output", _ctx->key->num_keys - 1, NULL );
1111 }
1112#endif // OAES_DEBUG
1113
1114 return OAES_RET_SUCCESS;
1115}
1116
1117static OAES_RET oaes_decrypt_block(
1118 OAES_CTX * ctx, uint8_t * c, size_t c_len )
1119{
1120 size_t _i, _j;
1121 oaes_ctx * _ctx = (oaes_ctx *) ctx;
1122
1123 if( NULL == _ctx )
1124 return OAES_RET_ARG1;
1125
1126 if( NULL == c )
1127 return OAES_RET_ARG2;
1128
1129 if( c_len != OAES_BLOCK_SIZE )
1130 return OAES_RET_ARG3;
1131
1132 if( NULL == _ctx->key )
1133 return OAES_RET_NOKEY;
1134
1135#ifdef OAES_DEBUG
1136 if( _ctx->step_cb )
1137 _ctx->step_cb( c, "iinput", _ctx->key->num_keys - 1, NULL );
1138#endif // OAES_DEBUG
1139
1140 // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
1141 for( _i = 0; _i < c_len; _i++ )
1142 c[_i] = c[_i] ^ _ctx->key->exp_data[
1143 ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ];
1144
1145#ifdef OAES_DEBUG
1146 if( _ctx->step_cb )
1147 {
1148 _ctx->step_cb( _ctx->key->exp_data +
1149 ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN,
1150 "ik_sch", _ctx->key->num_keys - 1, NULL );
1151 _ctx->step_cb( c, "ik_add", _ctx->key->num_keys - 1, NULL );
1152 }
1153#endif // OAES_DEBUG
1154
1155 for( _i = _ctx->key->num_keys - 2; _i > 0; _i-- )
1156 {
1157 // InvShiftRows(state)
1158 oaes_inv_shift_rows( c );
1159
1160#ifdef OAES_DEBUG
1161 if( _ctx->step_cb )
1162 _ctx->step_cb( c, "is_row", _i, NULL );
1163#endif // OAES_DEBUG
1164
1165 // InvSubBytes(state)
1166 for( _j = 0; _j < c_len; _j++ )
1167 oaes_inv_sub_byte( c + _j );
1168
1169#ifdef OAES_DEBUG
1170 if( _ctx->step_cb )
1171 _ctx->step_cb( c, "is_box", _i, NULL );
1172#endif // OAES_DEBUG
1173
1174 // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1])
1175 for( _j = 0; _j < c_len; _j++ )
1176 c[_j] = c[_j] ^
1177 _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j];
1178
1179#ifdef OAES_DEBUG
1180 if( _ctx->step_cb )
1181 {
1182 _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN,
1183 "ik_sch", _i, NULL );
1184 _ctx->step_cb( c, "ik_add", _i, NULL );
1185 }
1186#endif // OAES_DEBUG
1187
1188 // InvMixColums(state)
1189 oaes_inv_mix_cols( c );
1190 oaes_inv_mix_cols( c + 4 );
1191 oaes_inv_mix_cols( c + 8 );
1192 oaes_inv_mix_cols( c + 12 );
1193
1194#ifdef OAES_DEBUG
1195 if( _ctx->step_cb )
1196 _ctx->step_cb( c, "im_col", _i, NULL );
1197#endif // OAES_DEBUG
1198
1199 }
1200
1201 // InvShiftRows(state)
1202 oaes_inv_shift_rows( c );
1203
1204#ifdef OAES_DEBUG
1205 if( _ctx->step_cb )
1206 _ctx->step_cb( c, "is_row", 1, NULL );
1207#endif // OAES_DEBUG
1208
1209 // InvSubBytes(state)
1210 for( _i = 0; _i < c_len; _i++ )
1211 oaes_inv_sub_byte( c + _i );
1212
1213#ifdef OAES_DEBUG
1214 if( _ctx->step_cb )
1215 _ctx->step_cb( c, "is_box", 1, NULL );
1216#endif // OAES_DEBUG
1217
1218 // AddRoundKey(state, w[0, Nb-1])
1219 for( _i = 0; _i < c_len; _i++ )
1220 c[_i] = c[_i] ^ _ctx->key->exp_data[_i];
1221
1222#ifdef OAES_DEBUG
1223 if( _ctx->step_cb )
1224 {
1225 _ctx->step_cb( _ctx->key->exp_data, "ik_sch", 1, NULL );
1226 _ctx->step_cb( c, "ioutput", 1, NULL );
1227 }
1228#endif // OAES_DEBUG
1229
1230 return OAES_RET_SUCCESS;
1231}
1232
1233OAES_RET oaes_encrypt( OAES_CTX * ctx,
1234 const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len )
1235{
1236 size_t _i, _j, _c_len_in, _c_data_len;
1237 size_t _pad_len = m_len % OAES_BLOCK_SIZE == 0 ?
1238 0 : OAES_BLOCK_SIZE - m_len % OAES_BLOCK_SIZE;
1239 oaes_ctx * _ctx = (oaes_ctx *) ctx;
1240 OAES_RET _rc = OAES_RET_SUCCESS;
1241 uint8_t _flags = _pad_len ? OAES_FLAG_PAD : 0;
1242
1243 if( NULL == _ctx )
1244 return OAES_RET_ARG1;
1245
1246 if( NULL == m )
1247 return OAES_RET_ARG2;
1248
1249 if( NULL == c_len )
1250 return OAES_RET_ARG5;
1251
1252 _c_len_in = *c_len;
1253 // data + pad
1254 _c_data_len = m_len + _pad_len;
1255 // header + iv + data + pad
1256 *c_len = 2 * OAES_BLOCK_SIZE + m_len + _pad_len;
1257
1258 if( NULL == c )
1259 return OAES_RET_SUCCESS;
1260
1261 if( _c_len_in < *c_len )
1262 return OAES_RET_BUF;
1263
1264 if( NULL == _ctx->key )
1265 return OAES_RET_NOKEY;
1266
1267 // header
1268 memcpy(c, oaes_header, OAES_BLOCK_SIZE );
1269 memcpy(c + 6, &_ctx->options, sizeof(_ctx->options));
1270 memcpy(c + 8, &_flags, sizeof(_flags));
1271 // iv
1272 memcpy(c + OAES_BLOCK_SIZE, _ctx->iv, OAES_BLOCK_SIZE );
1273 // data
1274 memcpy(c + 2 * OAES_BLOCK_SIZE, m, m_len );
1275
1276 for( _i = 0; _i < _c_data_len; _i += OAES_BLOCK_SIZE )
1277 {
1278 uint8_t _block[OAES_BLOCK_SIZE];
1279 size_t _block_size = min( m_len - _i, OAES_BLOCK_SIZE );
1280
1281 memcpy( _block, c + 2 * OAES_BLOCK_SIZE + _i, _block_size );
1282
1283 // insert pad
1284 for( _j = 0; _j < OAES_BLOCK_SIZE - _block_size; _j++ )
1285 _block[ _block_size + _j ] = _j + 1;
1286
1287 // CBC
1288 if( _ctx->options & OAES_OPTION_CBC )
1289 {
1290 for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ )
1291 _block[_j] = _block[_j] ^ _ctx->iv[_j];
1292 }
1293
1294 _rc = _rc ||
1295 oaes_encrypt_block( ctx, _block, OAES_BLOCK_SIZE );
1296 memcpy( c + 2 * OAES_BLOCK_SIZE + _i, _block, OAES_BLOCK_SIZE );
1297
1298 if( _ctx->options & OAES_OPTION_CBC )
1299 memcpy( _ctx->iv, _block, OAES_BLOCK_SIZE );
1300 }
1301
1302 return _rc;
1303}
1304
1305OAES_RET oaes_decrypt( OAES_CTX * ctx,
1306 const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len )
1307{
1308 size_t _i, _j, _m_len_in;
1309 oaes_ctx * _ctx = (oaes_ctx *) ctx;
1310 OAES_RET _rc = OAES_RET_SUCCESS;
1311 uint8_t _iv[OAES_BLOCK_SIZE];
1312 uint8_t _flags;
1313 OAES_OPTION _options;
1314
1315 if( NULL == ctx )
1316 return OAES_RET_ARG1;
1317
1318 if( NULL == c )
1319 return OAES_RET_ARG2;
1320
1321 if( c_len % OAES_BLOCK_SIZE )
1322 return OAES_RET_ARG3;
1323
1324 if( NULL == m_len )
1325 return OAES_RET_ARG5;
1326
1327 _m_len_in = *m_len;
1328 *m_len = c_len - 2 * OAES_BLOCK_SIZE;
1329
1330 if( NULL == m )
1331 return OAES_RET_SUCCESS;
1332
1333 if( _m_len_in < *m_len )
1334 return OAES_RET_BUF;
1335
1336 if( NULL == _ctx->key )
1337 return OAES_RET_NOKEY;
1338
1339 // header
1340 if( 0 != memcmp( c, oaes_header, 4 ) )
1341 return OAES_RET_HEADER;
1342
1343 // header version
1344 switch( c[4] )
1345 {
1346 case 0x01:
1347 break;
1348 default:
1349 return OAES_RET_HEADER;
1350 }
1351
1352 // header type
1353 switch( c[5] )
1354 {
1355 case 0x02:
1356 break;
1357 default:
1358 return OAES_RET_HEADER;
1359 }
1360
1361 // options
1362 memcpy(&_options, c + 6, sizeof(_options));
1363 // validate that all options are valid
1364 if( _options & ~(
1365 OAES_OPTION_ECB
1366 | OAES_OPTION_CBC
1367#ifdef OAES_DEBUG
1368 | OAES_OPTION_STEP_ON
1369 | OAES_OPTION_STEP_OFF
1370#endif // OAES_DEBUG
1371 ) )
1372 return OAES_RET_HEADER;
1373 if( ( _options & OAES_OPTION_ECB ) &&
1374 ( _options & OAES_OPTION_CBC ) )
1375 return OAES_RET_HEADER;
1376 if( _options == OAES_OPTION_NONE )
1377 return OAES_RET_HEADER;
1378
1379 // flags
1380 memcpy(&_flags, c + 8, sizeof(_flags));
1381 // validate that all flags are valid
1382 if( _flags & ~(
1383 OAES_FLAG_PAD
1384 ) )
1385 return OAES_RET_HEADER;
1386
1387 // iv
1388 memcpy( _iv, c + OAES_BLOCK_SIZE, OAES_BLOCK_SIZE);
1389 // data + pad
1390 memcpy( m, c + 2 * OAES_BLOCK_SIZE, *m_len );
1391
1392 for( _i = 0; _i < *m_len; _i += OAES_BLOCK_SIZE )
1393 {
1394 if( ( _options & OAES_OPTION_CBC ) && _i > 0 )
1395 memcpy( _iv, c + OAES_BLOCK_SIZE + _i, OAES_BLOCK_SIZE );
1396
1397 _rc = _rc ||
1398 oaes_decrypt_block( ctx, m + _i, min( *m_len - _i, OAES_BLOCK_SIZE ) );
1399
1400 // CBC
1401 if( _options & OAES_OPTION_CBC )
1402 {
1403 for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ )
1404 m[ _i + _j ] = m[ _i + _j ] ^ _iv[_j];
1405 }
1406 }
1407
1408 // remove pad
1409 if( _flags & OAES_FLAG_PAD )
1410 {
1411 int _is_pad = 1;
1412 size_t _temp = (size_t) m[*m_len - 1];
1413
1414 if( _temp <= 0x00 || _temp > 0x0f )
1415 return OAES_RET_HEADER;
1416 for( _i = 0; _i < _temp; _i++ )
1417 if( m[*m_len - 1 - _i] != _temp - _i )
1418 _is_pad = 0;
1419 if( _is_pad )
1420 {
1421 memset( m + *m_len - _temp, 0, _temp );
1422 *m_len -= _temp;
1423 }
1424 else
1425 return OAES_RET_HEADER;
1426 }
1427
1428 return OAES_RET_SUCCESS;
1429}