1
/* $Id: encryption.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include <pjlib-util.h>
25
#if INCLUDE_ENCRYPTION_TEST
28
* Encryption algorithm tests.
30
#define THIS_FILE "encryption.c"
34
* SHA1 test from the original sha1.c source file.
36
static char *sha1_test_data[] = {
38
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
39
"A million repetitions of 'a'"
41
static char *sha1_test_results[] = {
42
"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
43
"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
44
"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"
48
static void digest_to_hex(const pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE],
54
for (i = 0; i < PJ_SHA1_DIGEST_SIZE/4; i++) {
55
for (j = 0; j < 4; j++) {
56
sprintf(c,"%02X", digest[i*4+j]);
65
static int sha1_test1(void)
67
enum { MILLION = 1000000 };
69
pj_sha1_context context;
70
pj_uint8_t digest[20];
75
PJ_LOG(3, (THIS_FILE, " SHA1 test vector 1 from sha1.c.."));
77
for (k = 0; k < 2; k++){
78
pj_sha1_init(&context);
79
pj_sha1_update(&context, (pj_uint8_t*)sha1_test_data[k],
80
pj_ansi_strlen(sha1_test_data[k]));
81
pj_sha1_final(&context, digest);
82
digest_to_hex(digest, output);
84
if (pj_ansi_strcmp(output, sha1_test_results[k])) {
85
PJ_LOG(3, (THIS_FILE, " incorrect hash result on k=%d", k));
90
/* million 'a' vector we feed separately */
91
pj_sha1_init(&context);
92
for (k = 0; k < MILLION; k++)
93
pj_sha1_update(&context, (pj_uint8_t*)"a", 1);
94
pj_sha1_final(&context, digest);
95
digest_to_hex(digest, output);
96
if (strcmp(output, sha1_test_results[2])) {
97
PJ_LOG(3, (THIS_FILE, " incorrect hash result!"));
101
/* million 'a' test, using block */
102
pool = pj_pool_create(mem, "sha1test", 256, 512, NULL);
103
block = (pj_uint8_t*)pj_pool_alloc(pool, MILLION);
104
pj_memset(block, 'a', MILLION);
106
pj_sha1_init(&context);
107
pj_sha1_update(&context, block, MILLION);
108
pj_sha1_final(&context, digest);
109
digest_to_hex(digest, output);
110
if (strcmp(output, sha1_test_results[2])) {
111
pj_pool_release(pool);
112
PJ_LOG(3, (THIS_FILE, " incorrect hash result for block update!"));
116
/* verify that original buffer was not modified */
117
for (k=0; k<MILLION; ++k) {
118
if (block[k] != 'a') {
119
pj_pool_release(pool);
120
PJ_LOG(3, (THIS_FILE, " block was modified!"));
125
pj_pool_release(pool);
133
* SHA1 test from RFC 3174
136
* Define patterns for testing
139
#define TEST2a "abcdbcdecdefdefgefghfghighijhi"
140
#define TEST2b "jkijkljklmklmnlmnomnopnopq"
141
#define TEST2 TEST2a TEST2b
143
#define TEST4a "01234567012345670123456701234567"
144
#define TEST4b "01234567012345670123456701234567"
145
/* an exact multiple of 512 bits */
146
#define TEST4 TEST4a TEST4b
148
static char *testarray[4] =
155
static int repeatcount[4] = { 1, 1, 1000000, 10 };
156
static char *resultarray[4] =
158
"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
159
"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
160
"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F",
161
"DEA356A2 CDDD90C7 A7ECEDC5 EBB56393 4F460452"
164
static int sha1_test2(void)
168
pj_uint8_t digest[20];
169
char char_digest[64];
171
PJ_LOG(3, (THIS_FILE, " SHA1 test vector 2 from rfc 3174.."));
173
for(i = 0; i < 4; ++i) {
178
for(j = 0; j < repeatcount[i]; ++j) {
180
(const pj_uint8_t *) testarray[i],
181
pj_ansi_strlen(testarray[i]));
184
pj_sha1_final(&sha, digest);
186
digest_to_hex(digest, char_digest);
187
if (pj_ansi_strcmp(char_digest, resultarray[i])) {
188
PJ_LOG(3, (THIS_FILE, " digest mismatch in test %d", i));
198
* HMAC-MD5 and HMAC-SHA1 test vectors from RFC 2202
211
struct rfc2202_test rfc2202_test_vector[] =
214
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
218
"\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
222
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
223
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
228
"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
233
"what do ya want for nothing?",
235
"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
236
"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
239
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
240
"\xaa\xaa\xaa\xaa\xaa\xaa",
242
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
243
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
244
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
245
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
246
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
248
"\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6",
252
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
253
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
255
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
256
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
257
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
258
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
259
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
262
"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
265
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
267
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
268
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
269
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
270
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
271
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
273
"\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79",
274
"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
277
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
278
"\x0c\x0c\x0c\x0c\x0c\x0c",
280
"Test With Truncation",
282
"\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c",
286
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
287
"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
289
"Test With Truncation",
292
"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
295
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
296
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
297
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
298
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
299
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
300
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
301
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
302
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
304
"Test Using Larger Than Block-Size Key - Hash Key First",
306
"\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd",
307
"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
310
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
311
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
312
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
313
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
314
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
315
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
316
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
317
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
319
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
321
"\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e",
322
"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
327
static int rfc2202_test(void)
331
PJ_LOG(3, (THIS_FILE, " verifying test vectors from rfc 2202.."));
333
/* Verify that test vectors are valid */
334
for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
335
PJ_ASSERT_RETURN(pj_ansi_strlen(rfc2202_test_vector[i].input) ==
336
rfc2202_test_vector[i].input_len, -50);
337
PJ_ASSERT_RETURN(pj_ansi_strlen(rfc2202_test_vector[i].key) ==
338
rfc2202_test_vector[i].key_len, -52);
339
PJ_ASSERT_RETURN(rfc2202_test_vector[i].md5_digest==NULL ||
340
pj_ansi_strlen(rfc2202_test_vector[i].md5_digest)<=16,
342
PJ_ASSERT_RETURN(rfc2202_test_vector[i].sha1_digest==NULL ||
343
pj_ansi_strlen(rfc2202_test_vector[i].sha1_digest)<=20,
348
PJ_LOG(3, (THIS_FILE, " HMAC-MD5 test vectors from rfc 2202.."));
349
for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
350
pj_uint8_t digest_buf[18], *digest;
352
if (rfc2202_test_vector[i].md5_digest == NULL)
355
digest_buf[0] = '\0';
356
digest_buf[17] = '\0';
358
digest = digest_buf+1;
360
pj_hmac_md5((pj_uint8_t*)rfc2202_test_vector[i].input,
361
rfc2202_test_vector[i].input_len,
362
(pj_uint8_t*)rfc2202_test_vector[i].key,
363
rfc2202_test_vector[i].key_len,
366
/* Check for overwrites */
367
if (digest_buf[0] != '\0' || digest_buf[17] != '\0') {
368
PJ_LOG(3, (THIS_FILE, " error: overwriting outside buffer on test %d", i));
373
if (pj_memcmp(rfc2202_test_vector[i].md5_digest, digest, 16)) {
374
PJ_LOG(3, (THIS_FILE, " error: digest mismatch on test %d", i));
380
PJ_LOG(3, (THIS_FILE, " HMAC-SHA1 test vectors from rfc 2202.."));
381
for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
382
pj_uint8_t digest_buf[22], *digest;
384
if (rfc2202_test_vector[i].sha1_digest == NULL)
387
digest_buf[0] = '\0';
388
digest_buf[21] = '\0';
390
digest = digest_buf+1;
392
pj_hmac_sha1((pj_uint8_t*)rfc2202_test_vector[i].input,
393
rfc2202_test_vector[i].input_len,
394
(pj_uint8_t*)rfc2202_test_vector[i].key,
395
rfc2202_test_vector[i].key_len,
398
/* Check for overwrites */
399
if (digest_buf[0] != '\0' || digest_buf[21] != '\0') {
400
PJ_LOG(3, (THIS_FILE, " error: overwriting outside buffer on test %d", i));
405
if (pj_memcmp(rfc2202_test_vector[i].sha1_digest, digest, 20)) {
406
PJ_LOG(3, (THIS_FILE, " error: digest mismatch on test %d", i));
416
/* CRC32 test data, generated from crc32 test on a Linux box */
421
} crc32_test_data[] =
432
/* Something read from /dev/random */
433
"\x21\x21\x98\x10\x62\x59\xbc\x58\x42\x24\xe5\xf3\x92\x0a\x68\x3c\xa7\x67\x73\xc3",
437
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
449
static int crc32_test(void)
453
PJ_LOG(3, (THIS_FILE, " crc32 test.."));
455
/* testing pj_crc32_calc */
456
for (i=0; i<PJ_ARRAY_SIZE(crc32_test_data); ++i) {
459
crc = pj_crc32_calc((pj_uint8_t*)crc32_test_data[i].input,
460
pj_ansi_strlen(crc32_test_data[i].input));
461
if (crc != crc32_test_data[i].crc) {
462
PJ_LOG(3,(THIS_FILE, " error: crc mismatch on test %d", i));
467
/* testing incremental CRC32 calculation */
468
for (i=0; i<PJ_ARRAY_SIZE(crc32_test_data); ++i) {
469
pj_crc32_context ctx;
470
pj_uint32_t crc0, crc1;
473
len = pj_ansi_strlen(crc32_test_data[i].input);
474
crc0 = pj_crc32_calc((pj_uint8_t*)crc32_test_data[i].input, len);
477
pj_crc32_update(&ctx, (pj_uint8_t*)crc32_test_data[i].input,
481
pj_crc32_update(&ctx, (pj_uint8_t*)crc32_test_data[i].input + len/2,
485
crc1 = pj_crc32_final(&ctx);
489
" error: crc algorithm error on test %d", i));
505
* Base64 test vectors (RFC 4648)
507
static struct base64_test_vec
512
} base64_test_vec[] =
550
"\x14\xfb\x9c\x03\xd9\x7e",
555
"\x14\xfb\x9c\x03\xd9",
564
/* with whitespaces */
572
"\nZ\r\nm 9\tv\nYm\nF\ny\n",
578
static int base64_test(void)
584
PJ_LOG(3, (THIS_FILE, " base64 test.."));
586
for (i=0; i<PJ_ARRAY_SIZE(base64_test_vec); ++i) {
591
if (base64_test_vec[i].flag & ENCODE) {
592
out_len = sizeof(output);
593
rc = pj_base64_encode((pj_uint8_t*)base64_test_vec[i].base256,
594
strlen(base64_test_vec[i].base256),
596
if (rc != PJ_SUCCESS)
599
if (out_len != (int)strlen(base64_test_vec[i].base64))
602
output[out_len] = '\0';
603
if (strcmp(output, base64_test_vec[i].base64) != 0)
608
if (base64_test_vec[i].flag & DECODE) {
609
out_len = sizeof(output);
610
input.ptr = (char*)base64_test_vec[i].base64;
611
input.slen = strlen(base64_test_vec[i].base64);
612
rc = pj_base64_decode(&input, (pj_uint8_t*)output, &out_len);
613
if (rc != PJ_SUCCESS)
616
if (out_len != (int)strlen(base64_test_vec[i].base256))
619
output[out_len] = '\0';
621
if (strcmp(output, base64_test_vec[i].base256) != 0)
630
int encryption_test()
657
static void crc32_update(pj_crc32_context *c, const pj_uint8_t *data,
660
pj_crc32_update(c, data, nbytes);
663
static void crc32_final(pj_crc32_context *ctx, pj_uint32_t *digest)
665
*digest = pj_crc32_final(ctx);
668
int encryption_benchmark()
673
pj_md5_context md5_context;
674
pj_sha1_context sha1_context;
676
pj_uint8_t digest[32];
681
void (*init_context)(void*);
682
void (*update)(void*, const pj_uint8_t*, unsigned);
683
void (*final)(void*, void*);
689
(void (*)(void*))&pj_md5_init,
690
(void (*)(void*, const pj_uint8_t*, unsigned))&pj_md5_update,
691
(void (*)(void*, void*))&pj_md5_final
695
(void (*)(void*))&pj_sha1_init,
696
(void (*)(void*, const pj_uint8_t*, unsigned))&pj_sha1_update,
697
(void (*)(void*, void*))&pj_sha1_final
701
(void (*)(void*))&pj_crc32_init,
702
(void (*)(void*, const pj_uint8_t*, unsigned))&crc32_update,
703
(void (*)(void*, void*))&crc32_final
706
#if defined(PJ_DEBUG) && PJ_DEBUG!=0
707
enum { LOOP = 1000 };
709
enum { LOOP = 10000 };
715
total_len = input_len * LOOP;
716
pool = pj_pool_create(mem, "enc", input_len+256, 0, NULL);
720
input = (pj_uint8_t*)pj_pool_alloc(pool, input_len);
721
pj_memset(input, '\xaa', input_len);
723
PJ_LOG(3, (THIS_FILE, " feeding %d Mbytes of data",
724
(unsigned)(total_len/1024/1024)));
727
for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
728
algorithms[i].init_context(&context);
729
algorithms[i].update(&context, input, input_len);
730
algorithms[i].final(&context, digest);
734
for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
738
pj_get_timestamp(&t1);
739
algorithms[i].init_context(&context);
740
for (j=0; j<LOOP; ++j) {
741
algorithms[i].update(&context, input, input_len);
743
algorithms[i].final(&context, digest);
744
pj_get_timestamp(&t2);
746
algorithms[i].t = pj_elapsed_usec(&t1, &t2);
750
for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
753
bytes = (total_len * 1000000 / algorithms[i].t);
754
PJ_LOG(3, (THIS_FILE, " %s:%8d usec (%3d.%03d Mbytes/sec)",
755
algorithms[i].name, algorithms[i].t,
756
(unsigned)(bytes / 1024 / 1024),
757
((unsigned)(bytes) % (1024 * 1024)) / 1024));
765
#endif /* INCLUDE_ENCRYPTION_TEST */