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