1 #include "test_common.h"
2
3 #include <limits.h>
4 #include <openssl/opensslv.h>
5 #include <openssl/evp.h>
6 #include <openssl/hmac.h>
7 #include <openssl/rand.h>
8 #include <openssl/sha.h>
9
test_random_generator(uint8_t * data,size_t len,void * user_data)10 int test_random_generator(uint8_t *data, size_t len, void *user_data)
11 {
12 if(RAND_bytes(data, len)) {
13 return 0;
14 }
15 else {
16 return SG_ERR_UNKNOWN;
17 }
18 }
19
test_hmac_sha256_init(void ** hmac_context,const uint8_t * key,size_t key_len,void * user_data)20 int test_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data)
21 {
22 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
23 HMAC_CTX *ctx = HMAC_CTX_new();
24 if(!ctx) {
25 return SG_ERR_NOMEM;
26 }
27 #else
28 HMAC_CTX *ctx = malloc(sizeof(HMAC_CTX));
29 if(!ctx) {
30 return SG_ERR_NOMEM;
31 }
32 HMAC_CTX_init(ctx);
33 #endif
34
35 *hmac_context = ctx;
36
37 if(HMAC_Init_ex(ctx, key, key_len, EVP_sha256(), 0) != 1) {
38 return SG_ERR_UNKNOWN;
39 }
40
41 return 0;
42 }
43
test_hmac_sha256_update(void * hmac_context,const uint8_t * data,size_t data_len,void * user_data)44 int test_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data)
45 {
46 HMAC_CTX *ctx = hmac_context;
47 int result = HMAC_Update(ctx, data, data_len);
48 return (result == 1) ? 0 : -1;
49 }
50
test_hmac_sha256_final(void * hmac_context,signal_buffer ** output,void * user_data)51 int test_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data)
52 {
53 int result = 0;
54 unsigned char md[EVP_MAX_MD_SIZE];
55 unsigned int len = 0;
56 HMAC_CTX *ctx = hmac_context;
57
58 if(HMAC_Final(ctx, md, &len) != 1) {
59 return SG_ERR_UNKNOWN;
60 }
61
62 signal_buffer *output_buffer = signal_buffer_create(md, len);
63 if(!output_buffer) {
64 result = SG_ERR_NOMEM;
65 goto complete;
66 }
67
68 *output = output_buffer;
69
70 complete:
71 return result;
72 }
73
test_hmac_sha256_cleanup(void * hmac_context,void * user_data)74 void test_hmac_sha256_cleanup(void *hmac_context, void *user_data)
75 {
76 if(hmac_context) {
77 HMAC_CTX *ctx = hmac_context;
78 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
79 HMAC_CTX_free(ctx);
80 #else
81 HMAC_CTX_cleanup(ctx);
82 free(ctx);
83 #endif
84 }
85 }
86
aes_cipher(int cipher,size_t key_len)87 const EVP_CIPHER *aes_cipher(int cipher, size_t key_len)
88 {
89 if(cipher == SG_CIPHER_AES_CBC_PKCS5) {
90 if(key_len == 16) {
91 return EVP_aes_128_cbc();
92 }
93 else if(key_len == 24) {
94 return EVP_aes_192_cbc();
95 }
96 else if(key_len == 32) {
97 return EVP_aes_256_cbc();
98 }
99 }
100 else if(cipher == SG_CIPHER_AES_CTR_NOPADDING) {
101 if(key_len == 16) {
102 return EVP_aes_128_ctr();
103 }
104 else if(key_len == 24) {
105 return EVP_aes_192_ctr();
106 }
107 else if(key_len == 32) {
108 return EVP_aes_256_ctr();
109 }
110 }
111 return 0;
112 }
113
test_sha512_digest_init(void ** digest_context,void * user_data)114 int test_sha512_digest_init(void **digest_context, void *user_data)
115 {
116 int result = 0;
117 EVP_MD_CTX *ctx;
118
119 ctx = EVP_MD_CTX_create();
120 if(!ctx) {
121 result = SG_ERR_NOMEM;
122 goto complete;
123 }
124
125 result = EVP_DigestInit_ex(ctx, EVP_sha512(), 0);
126 if(result == 1) {
127 result = SG_SUCCESS;
128 }
129 else {
130 result = SG_ERR_UNKNOWN;
131 }
132
133 complete:
134 if(result < 0) {
135 if(ctx) {
136 EVP_MD_CTX_destroy(ctx);
137 }
138 }
139 else {
140 *digest_context = ctx;
141 }
142 return result;
143 }
144
test_sha512_digest_update(void * digest_context,const uint8_t * data,size_t data_len,void * user_data)145 int test_sha512_digest_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data)
146 {
147 EVP_MD_CTX *ctx = digest_context;
148
149 int result = EVP_DigestUpdate(ctx, data, data_len);
150
151 return (result == 1) ? SG_SUCCESS : SG_ERR_UNKNOWN;
152 }
153
test_sha512_digest_final(void * digest_context,signal_buffer ** output,void * user_data)154 int test_sha512_digest_final(void *digest_context, signal_buffer **output, void *user_data)
155 {
156 int result = 0;
157 unsigned char md[EVP_MAX_MD_SIZE];
158 unsigned int len = 0;
159 EVP_MD_CTX *ctx = digest_context;
160
161 result = EVP_DigestFinal_ex(ctx, md, &len);
162 if(result == 1) {
163 result = SG_SUCCESS;
164 }
165 else {
166 result = SG_ERR_UNKNOWN;
167 goto complete;
168 }
169
170 result = EVP_DigestInit_ex(ctx, EVP_sha512(), 0);
171 if(result == 1) {
172 result = SG_SUCCESS;
173 }
174 else {
175 result = SG_ERR_UNKNOWN;
176 goto complete;
177 }
178
179 signal_buffer *output_buffer = signal_buffer_create(md, len);
180 if(!output_buffer) {
181 result = SG_ERR_NOMEM;
182 goto complete;
183 }
184
185 *output = output_buffer;
186
187 complete:
188 return result;
189 }
190
test_sha512_digest_cleanup(void * digest_context,void * user_data)191 void test_sha512_digest_cleanup(void *digest_context, void *user_data)
192 {
193 EVP_MD_CTX *ctx = digest_context;
194 EVP_MD_CTX_destroy(ctx);
195 }
196
test_encrypt(signal_buffer ** output,int cipher,const uint8_t * key,size_t key_len,const uint8_t * iv,size_t iv_len,const uint8_t * plaintext,size_t plaintext_len,void * user_data)197 int test_encrypt(signal_buffer **output,
198 int cipher,
199 const uint8_t *key, size_t key_len,
200 const uint8_t *iv, size_t iv_len,
201 const uint8_t *plaintext, size_t plaintext_len,
202 void *user_data)
203 {
204 int result = 0;
205 EVP_CIPHER_CTX *ctx = 0;
206 uint8_t *out_buf = 0;
207
208 const EVP_CIPHER *evp_cipher = aes_cipher(cipher, key_len);
209 if(!evp_cipher) {
210 fprintf(stderr, "invalid AES mode or key size: %zu\n", key_len);
211 return SG_ERR_UNKNOWN;
212 }
213
214 if(iv_len != 16) {
215 fprintf(stderr, "invalid AES IV size: %zu\n", iv_len);
216 return SG_ERR_UNKNOWN;
217 }
218
219 if(plaintext_len > INT_MAX - EVP_CIPHER_block_size(evp_cipher)) {
220 fprintf(stderr, "invalid plaintext length: %zu\n", plaintext_len);
221 return SG_ERR_UNKNOWN;
222 }
223
224 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
225 ctx = EVP_CIPHER_CTX_new();
226 if(!ctx) {
227 result = SG_ERR_NOMEM;
228 goto complete;
229 }
230 #else
231 ctx = malloc(sizeof(EVP_CIPHER_CTX));
232 if(!ctx) {
233 result = SG_ERR_NOMEM;
234 goto complete;
235 }
236 EVP_CIPHER_CTX_init(ctx);
237 #endif
238
239 result = EVP_EncryptInit_ex(ctx, evp_cipher, 0, key, iv);
240 if(!result) {
241 fprintf(stderr, "cannot initialize cipher\n");
242 result = SG_ERR_UNKNOWN;
243 goto complete;
244 }
245
246 if(cipher == SG_CIPHER_AES_CTR_NOPADDING) {
247 result = EVP_CIPHER_CTX_set_padding(ctx, 0);
248 if(!result) {
249 fprintf(stderr, "cannot set padding\n");
250 result = SG_ERR_UNKNOWN;
251 goto complete;
252 }
253 }
254
255 out_buf = malloc(sizeof(uint8_t) * (plaintext_len + EVP_CIPHER_block_size(evp_cipher)));
256 if(!out_buf) {
257 fprintf(stderr, "cannot allocate output buffer\n");
258 result = SG_ERR_NOMEM;
259 goto complete;
260 }
261
262 int out_len = 0;
263 result = EVP_EncryptUpdate(ctx,
264 out_buf, &out_len, plaintext, plaintext_len);
265 if(!result) {
266 fprintf(stderr, "cannot encrypt plaintext\n");
267 result = SG_ERR_UNKNOWN;
268 goto complete;
269 }
270
271 int final_len = 0;
272 result = EVP_EncryptFinal_ex(ctx, out_buf + out_len, &final_len);
273 if(!result) {
274 fprintf(stderr, "cannot finish encrypting plaintext\n");
275 result = SG_ERR_UNKNOWN;
276 goto complete;
277 }
278
279 *output = signal_buffer_create(out_buf, out_len + final_len);
280
281 complete:
282 if(ctx) {
283 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
284 EVP_CIPHER_CTX_free(ctx);
285 #else
286 EVP_CIPHER_CTX_cleanup(ctx);
287 free(ctx);
288 #endif
289 }
290 if(out_buf) {
291 free(out_buf);
292 }
293 return result;
294 }
295
test_decrypt(signal_buffer ** output,int cipher,const uint8_t * key,size_t key_len,const uint8_t * iv,size_t iv_len,const uint8_t * ciphertext,size_t ciphertext_len,void * user_data)296 int test_decrypt(signal_buffer **output,
297 int cipher,
298 const uint8_t *key, size_t key_len,
299 const uint8_t *iv, size_t iv_len,
300 const uint8_t *ciphertext, size_t ciphertext_len,
301 void *user_data)
302 {
303 int result = 0;
304 EVP_CIPHER_CTX *ctx = 0;
305 uint8_t *out_buf = 0;
306
307 const EVP_CIPHER *evp_cipher = aes_cipher(cipher, key_len);
308 if(!evp_cipher) {
309 fprintf(stderr, "invalid AES mode or key size: %zu\n", key_len);
310 return SG_ERR_INVAL;
311 }
312
313 if(iv_len != 16) {
314 fprintf(stderr, "invalid AES IV size: %zu\n", iv_len);
315 return SG_ERR_INVAL;
316 }
317
318 if(ciphertext_len > INT_MAX - EVP_CIPHER_block_size(evp_cipher)) {
319 fprintf(stderr, "invalid ciphertext length: %zu\n", ciphertext_len);
320 return SG_ERR_UNKNOWN;
321 }
322
323 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
324 ctx = EVP_CIPHER_CTX_new();
325 if(!ctx) {
326 result = SG_ERR_NOMEM;
327 goto complete;
328 }
329 #else
330 ctx = malloc(sizeof(EVP_CIPHER_CTX));
331 if(!ctx) {
332 result = SG_ERR_NOMEM;
333 goto complete;
334 }
335 EVP_CIPHER_CTX_init(ctx);
336 #endif
337
338 result = EVP_DecryptInit_ex(ctx, evp_cipher, 0, key, iv);
339 if(!result) {
340 fprintf(stderr, "cannot initialize cipher\n");
341 result = SG_ERR_UNKNOWN;
342 goto complete;
343 }
344
345 if(cipher == SG_CIPHER_AES_CTR_NOPADDING) {
346 result = EVP_CIPHER_CTX_set_padding(ctx, 0);
347 if(!result) {
348 fprintf(stderr, "cannot set padding\n");
349 result = SG_ERR_UNKNOWN;
350 goto complete;
351 }
352 }
353
354 out_buf = malloc(sizeof(uint8_t) * (ciphertext_len + EVP_CIPHER_block_size(evp_cipher)));
355 if(!out_buf) {
356 fprintf(stderr, "cannot allocate output buffer\n");
357 result = SG_ERR_UNKNOWN;
358 goto complete;
359 }
360
361 int out_len = 0;
362 result = EVP_DecryptUpdate(ctx,
363 out_buf, &out_len, ciphertext, ciphertext_len);
364 if(!result) {
365 fprintf(stderr, "cannot decrypt ciphertext\n");
366 result = SG_ERR_UNKNOWN;
367 goto complete;
368 }
369
370 int final_len = 0;
371 result = EVP_DecryptFinal_ex(ctx, out_buf + out_len, &final_len);
372 if(!result) {
373 fprintf(stderr, "cannot finish decrypting ciphertext\n");
374 result = SG_ERR_UNKNOWN;
375 goto complete;
376 }
377
378 *output = signal_buffer_create(out_buf, out_len + final_len);
379
380 complete:
381 if(ctx) {
382 #if OPENSSL_VERSION_NUMBER >= 0x1010000fL
383 EVP_CIPHER_CTX_free(ctx);
384 #else
385 EVP_CIPHER_CTX_cleanup(ctx);
386 free(ctx);
387 #endif
388 }
389 if(out_buf) {
390 free(out_buf);
391 }
392 return result;
393 }
394