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