encryption.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "test.h"
  20. #include <pjlib-util.h>
  21. #include <pjlib.h>
  22. #if INCLUDE_ENCRYPTION_TEST
  23. /*
  24. * Encryption algorithm tests.
  25. */
  26. #define THIS_FILE "encryption.c"
  27. /*
  28. * SHA1 test from the original sha1.c source file.
  29. */
  30. static char *sha1_test_data[] = {
  31. "abc",
  32. "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
  33. "A million repetitions of 'a'"
  34. };
  35. static char *sha1_test_results[] = {
  36. "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
  37. "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
  38. "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"
  39. };
  40. static void digest_to_hex(const pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE],
  41. char *output, int output_size)
  42. {
  43. int i,j;
  44. char *c = output;
  45. for (i = 0; i < PJ_SHA1_DIGEST_SIZE/4 && output_size >= 2; i++) {
  46. for (j = 0; j < 4 && output_size >= 3; j++) {
  47. pj_ansi_snprintf(c, output_size, "%02X", digest[i*4+j] & 0xFF);
  48. c += 2;
  49. output_size -= 2;
  50. }
  51. pj_ansi_snprintf(c, output_size, " ");
  52. c += 1;
  53. output_size -= 1;
  54. }
  55. *(c - 1) = '\0';
  56. }
  57. static int sha1_test1(void)
  58. {
  59. enum { MILLION = 1000000 };
  60. int k;
  61. pj_sha1_context context;
  62. pj_uint8_t digest[20];
  63. char output[80];
  64. pj_pool_t *pool;
  65. pj_uint8_t *block;
  66. PJ_LOG(3, (THIS_FILE, " SHA1 test vector 1 from sha1.c.."));
  67. for (k = 0; k < 2; k++){
  68. pj_sha1_init(&context);
  69. pj_sha1_update(&context, (pj_uint8_t*)sha1_test_data[k],
  70. pj_ansi_strlen(sha1_test_data[k]));
  71. pj_sha1_final(&context, digest);
  72. digest_to_hex(digest, output, sizeof(output));
  73. if (pj_ansi_strcmp(output, sha1_test_results[k])) {
  74. PJ_LOG(3, (THIS_FILE, " incorrect hash result on k=%d", k));
  75. return -10;
  76. }
  77. }
  78. /* million 'a' vector we feed separately */
  79. pj_sha1_init(&context);
  80. for (k = 0; k < MILLION; k++)
  81. pj_sha1_update(&context, (pj_uint8_t*)"a", 1);
  82. pj_sha1_final(&context, digest);
  83. digest_to_hex(digest, output, sizeof(output));
  84. if (strcmp(output, sha1_test_results[2])) {
  85. PJ_LOG(3, (THIS_FILE, " incorrect hash result!"));
  86. return -20;
  87. }
  88. /* million 'a' test, using block */
  89. pool = pj_pool_create(mem, "sha1test", 256, 512, NULL);
  90. block = (pj_uint8_t*)pj_pool_alloc(pool, MILLION);
  91. pj_memset(block, 'a', MILLION);
  92. pj_sha1_init(&context);
  93. pj_sha1_update(&context, block, MILLION);
  94. pj_sha1_final(&context, digest);
  95. digest_to_hex(digest, output, sizeof(output));
  96. if (strcmp(output, sha1_test_results[2])) {
  97. pj_pool_release(pool);
  98. PJ_LOG(3, (THIS_FILE, " incorrect hash result for block update!"));
  99. return -21;
  100. }
  101. /* verify that original buffer was not modified */
  102. for (k=0; k<MILLION; ++k) {
  103. if (block[k] != 'a') {
  104. pj_pool_release(pool);
  105. PJ_LOG(3, (THIS_FILE, " block was modified!"));
  106. return -22;
  107. }
  108. }
  109. pj_pool_release(pool);
  110. /* success */
  111. return(0);
  112. }
  113. /*
  114. * SHA1 test from RFC 3174
  115. */
  116. /*
  117. * Define patterns for testing
  118. */
  119. #define TEST1 "abc"
  120. #define TEST2a "abcdbcdecdefdefgefghfghighijhi"
  121. #define TEST2b "jkijkljklmklmnlmnomnopnopq"
  122. #define TEST2 TEST2a TEST2b
  123. #define TEST3 "a"
  124. #define TEST4a "01234567012345670123456701234567"
  125. #define TEST4b "01234567012345670123456701234567"
  126. /* an exact multiple of 512 bits */
  127. #define TEST4 TEST4a TEST4b
  128. static char *testarray[4] =
  129. {
  130. TEST1,
  131. TEST2,
  132. TEST3,
  133. TEST4
  134. };
  135. static int repeatcount[4] = { 1, 1, 1000000, 10 };
  136. static char *resultarray[4] =
  137. {
  138. "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
  139. "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
  140. "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F",
  141. "DEA356A2 CDDD90C7 A7ECEDC5 EBB56393 4F460452"
  142. };
  143. static int sha1_test2(void)
  144. {
  145. pj_sha1_context sha;
  146. int i;
  147. pj_uint8_t digest[20];
  148. char char_digest[64];
  149. PJ_LOG(3, (THIS_FILE, " SHA1 test vector 2 from rfc 3174.."));
  150. for(i = 0; i < 4; ++i) {
  151. int j;
  152. pj_sha1_init(&sha);
  153. for(j = 0; j < repeatcount[i]; ++j) {
  154. pj_sha1_update(&sha,
  155. (const pj_uint8_t *) testarray[i],
  156. pj_ansi_strlen(testarray[i]));
  157. }
  158. pj_sha1_final(&sha, digest);
  159. digest_to_hex(digest, char_digest, sizeof(char_digest));
  160. if (pj_ansi_strcmp(char_digest, resultarray[i])) {
  161. PJ_LOG(3, (THIS_FILE, " digest mismatch in test %d", i));
  162. return -40;
  163. }
  164. }
  165. return 0;
  166. }
  167. /*
  168. * HMAC-MD5 and HMAC-SHA1 test vectors from RFC 2202
  169. */
  170. struct rfc2202_test
  171. {
  172. char *key;
  173. unsigned key_len;
  174. char *input;
  175. unsigned input_len;
  176. char *md5_digest;
  177. char *sha1_digest;
  178. };
  179. struct rfc2202_test rfc2202_test_vector[] =
  180. {
  181. {
  182. "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
  183. 16,
  184. "Hi There",
  185. 8,
  186. "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
  187. NULL
  188. },
  189. {
  190. "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
  191. "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
  192. 20,
  193. "Hi There",
  194. 8,
  195. NULL,
  196. "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
  197. },
  198. {
  199. "Jefe",
  200. 4,
  201. "what do ya want for nothing?",
  202. 28,
  203. "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
  204. "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
  205. },
  206. {
  207. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  208. "\xaa\xaa\xaa\xaa\xaa\xaa",
  209. 16,
  210. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  211. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  212. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  213. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  214. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
  215. 50,
  216. "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6",
  217. NULL
  218. },
  219. {
  220. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  221. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
  222. 20,
  223. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  224. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  225. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  226. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
  227. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
  228. 50,
  229. NULL,
  230. "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
  231. },
  232. {
  233. "\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",
  234. 25,
  235. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
  236. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
  237. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
  238. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
  239. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
  240. 50,
  241. "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79",
  242. "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
  243. },
  244. {
  245. "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
  246. "\x0c\x0c\x0c\x0c\x0c\x0c",
  247. 16,
  248. "Test With Truncation",
  249. 20,
  250. "\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c",
  251. NULL
  252. },
  253. {
  254. "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
  255. "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
  256. 20,
  257. "Test With Truncation",
  258. 20,
  259. NULL,
  260. "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
  261. },
  262. {
  263. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  264. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  265. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  266. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  267. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  268. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  269. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  270. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
  271. 80,
  272. "Test Using Larger Than Block-Size Key - Hash Key First",
  273. 54,
  274. "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd",
  275. "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
  276. },
  277. {
  278. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  279. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  280. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  281. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  282. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  283. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  284. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
  285. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
  286. 80,
  287. "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
  288. 73,
  289. "\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e",
  290. "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
  291. }
  292. };
  293. static int rfc2202_test(void)
  294. {
  295. unsigned i;
  296. PJ_LOG(3, (THIS_FILE, " verifying test vectors from rfc 2202.."));
  297. /* Verify that test vectors are valid */
  298. for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
  299. PJ_ASSERT_RETURN(pj_ansi_strlen(rfc2202_test_vector[i].input) ==
  300. rfc2202_test_vector[i].input_len, -50);
  301. PJ_ASSERT_RETURN(pj_ansi_strlen(rfc2202_test_vector[i].key) ==
  302. rfc2202_test_vector[i].key_len, -52);
  303. PJ_ASSERT_RETURN(rfc2202_test_vector[i].md5_digest==NULL ||
  304. pj_ansi_strlen(rfc2202_test_vector[i].md5_digest)<=16,
  305. -54);
  306. PJ_ASSERT_RETURN(rfc2202_test_vector[i].sha1_digest==NULL ||
  307. pj_ansi_strlen(rfc2202_test_vector[i].sha1_digest)<=20,
  308. -56);
  309. }
  310. /* Test HMAC-MD5 */
  311. PJ_LOG(3, (THIS_FILE, " HMAC-MD5 test vectors from rfc 2202.."));
  312. for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
  313. pj_uint8_t digest_buf[18], *digest;
  314. if (rfc2202_test_vector[i].md5_digest == NULL)
  315. continue;
  316. digest_buf[0] = '\0';
  317. digest_buf[17] = '\0';
  318. digest = digest_buf+1;
  319. pj_hmac_md5((pj_uint8_t*)rfc2202_test_vector[i].input,
  320. rfc2202_test_vector[i].input_len,
  321. (pj_uint8_t*)rfc2202_test_vector[i].key,
  322. rfc2202_test_vector[i].key_len,
  323. digest);
  324. /* Check for overwrites */
  325. if (digest_buf[0] != '\0' || digest_buf[17] != '\0') {
  326. PJ_LOG(3, (THIS_FILE, " error: overwriting outside buffer on test %d", i));
  327. return -60;
  328. }
  329. /* Compare digest */
  330. if (pj_memcmp(rfc2202_test_vector[i].md5_digest, digest, 16)) {
  331. PJ_LOG(3, (THIS_FILE, " error: digest mismatch on test %d", i));
  332. return -65;
  333. }
  334. }
  335. /* Test HMAC-SHA1 */
  336. PJ_LOG(3, (THIS_FILE, " HMAC-SHA1 test vectors from rfc 2202.."));
  337. for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
  338. pj_uint8_t digest_buf[22], *digest;
  339. if (rfc2202_test_vector[i].sha1_digest == NULL)
  340. continue;
  341. digest_buf[0] = '\0';
  342. digest_buf[21] = '\0';
  343. digest = digest_buf+1;
  344. pj_hmac_sha1((pj_uint8_t*)rfc2202_test_vector[i].input,
  345. rfc2202_test_vector[i].input_len,
  346. (pj_uint8_t*)rfc2202_test_vector[i].key,
  347. rfc2202_test_vector[i].key_len,
  348. digest);
  349. /* Check for overwrites */
  350. if (digest_buf[0] != '\0' || digest_buf[21] != '\0') {
  351. PJ_LOG(3, (THIS_FILE, " error: overwriting outside buffer on test %d", i));
  352. return -70;
  353. }
  354. /* Compare digest */
  355. if (pj_memcmp(rfc2202_test_vector[i].sha1_digest, digest, 20)) {
  356. PJ_LOG(3, (THIS_FILE, " error: digest mismatch on test %d", i));
  357. return -75;
  358. }
  359. }
  360. /* Success */
  361. return 0;
  362. }
  363. /* CRC32 test data, generated from crc32 test on a Linux box */
  364. struct crc32_test_t
  365. {
  366. char *input;
  367. pj_uint32_t crc;
  368. } crc32_test_data[] =
  369. {
  370. {
  371. "",
  372. 0x0
  373. },
  374. {
  375. "Hello World",
  376. 0x4a17b156
  377. },
  378. {
  379. /* Something read from /dev/random */
  380. "\x21\x21\x98\x10\x62\x59\xbc\x58\x42\x24\xe5\xf3\x92\x0a\x68\x3c\xa7\x67\x73\xc3",
  381. 0x506693be
  382. },
  383. {
  384. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  385. 0xcab11777
  386. },
  387. {
  388. "123456789",
  389. 0xCBF43926
  390. }
  391. };
  392. /*
  393. * CRC32 test
  394. */
  395. static int crc32_test(void)
  396. {
  397. unsigned i;
  398. PJ_LOG(3, (THIS_FILE, " crc32 test.."));
  399. /* testing pj_crc32_calc */
  400. for (i=0; i<PJ_ARRAY_SIZE(crc32_test_data); ++i) {
  401. pj_uint32_t crc;
  402. crc = pj_crc32_calc((pj_uint8_t*)crc32_test_data[i].input,
  403. pj_ansi_strlen(crc32_test_data[i].input));
  404. if (crc != crc32_test_data[i].crc) {
  405. PJ_LOG(3,(THIS_FILE, " error: crc mismatch on test %d", i));
  406. return -80;
  407. }
  408. }
  409. /* testing incremental CRC32 calculation */
  410. for (i=0; i<PJ_ARRAY_SIZE(crc32_test_data); ++i) {
  411. pj_crc32_context ctx;
  412. pj_uint32_t crc0, crc1;
  413. pj_size_t len;
  414. len = pj_ansi_strlen(crc32_test_data[i].input);
  415. crc0 = pj_crc32_calc((pj_uint8_t*)crc32_test_data[i].input, len);
  416. pj_crc32_init(&ctx);
  417. pj_crc32_update(&ctx, (pj_uint8_t*)crc32_test_data[i].input,
  418. len / 2);
  419. if (len/2 > 0) {
  420. pj_crc32_update(&ctx, (pj_uint8_t*)crc32_test_data[i].input + len/2,
  421. len - len/2);
  422. }
  423. crc1 = pj_crc32_final(&ctx);
  424. if (crc0 != crc1) {
  425. PJ_LOG(3,(THIS_FILE,
  426. " error: crc algorithm error on test %d", i));
  427. return -85;
  428. }
  429. }
  430. return 0;
  431. }
  432. enum
  433. {
  434. ENCODE = 1,
  435. DECODE = 2,
  436. ENCODE_DECODE = 3
  437. };
  438. /*
  439. * Base64 test vectors (RFC 4648)
  440. */
  441. static struct base64_test_vec
  442. {
  443. const char *base256;
  444. const char *base64;
  445. unsigned flag;
  446. } base64_test_vec[] =
  447. {
  448. {
  449. "",
  450. "",
  451. ENCODE_DECODE
  452. },
  453. {
  454. "f",
  455. "Zg==",
  456. ENCODE_DECODE
  457. },
  458. {
  459. "fo",
  460. "Zm8=",
  461. ENCODE_DECODE
  462. },
  463. {
  464. "foo",
  465. "Zm9v",
  466. ENCODE_DECODE
  467. },
  468. {
  469. "foob",
  470. "Zm9vYg==",
  471. ENCODE_DECODE
  472. },
  473. {
  474. "fooba",
  475. "Zm9vYmE=",
  476. ENCODE_DECODE
  477. },
  478. {
  479. "foobar",
  480. "Zm9vYmFy",
  481. ENCODE_DECODE
  482. },
  483. {
  484. "\x14\xfb\x9c\x03\xd9\x7e",
  485. "FPucA9l+",
  486. ENCODE_DECODE
  487. },
  488. {
  489. "\x14\xfb\x9c\x03\xd9",
  490. "FPucA9k=",
  491. ENCODE_DECODE
  492. },
  493. {
  494. "\x14\xfb\x9c\x03",
  495. "FPucAw==",
  496. ENCODE_DECODE
  497. },
  498. /* with whitespaces */
  499. {
  500. "foobar",
  501. "Zm9v\r\nYmFy",
  502. DECODE
  503. },
  504. {
  505. "foobar",
  506. "\nZ\r\nm 9\tv\nYm\nF\ny\n",
  507. DECODE
  508. },
  509. };
  510. static int base64_test(void)
  511. {
  512. unsigned i;
  513. char output[80];
  514. pj_status_t rc;
  515. PJ_LOG(3, (THIS_FILE, " base64 test.."));
  516. for (i=0; i<PJ_ARRAY_SIZE(base64_test_vec); ++i) {
  517. pj_str_t input;
  518. int out_len;
  519. /* Encode test */
  520. if (base64_test_vec[i].flag & ENCODE) {
  521. out_len = sizeof(output);
  522. rc = pj_base64_encode((pj_uint8_t*)base64_test_vec[i].base256,
  523. (int)strlen(base64_test_vec[i].base256),
  524. output, &out_len);
  525. if (rc != PJ_SUCCESS)
  526. return -90;
  527. if (out_len != (int)strlen(base64_test_vec[i].base64))
  528. return -91;
  529. output[out_len] = '\0';
  530. if (strcmp(output, base64_test_vec[i].base64) != 0)
  531. return -92;
  532. }
  533. /* Decode test */
  534. if (base64_test_vec[i].flag & DECODE) {
  535. out_len = sizeof(output);
  536. input.ptr = (char*)base64_test_vec[i].base64;
  537. input.slen = strlen(base64_test_vec[i].base64);
  538. rc = pj_base64_decode(&input, (pj_uint8_t*)output, &out_len);
  539. if (rc != PJ_SUCCESS)
  540. return -95;
  541. if (out_len != (int)strlen(base64_test_vec[i].base256))
  542. return -96;
  543. output[out_len] = '\0';
  544. if (strcmp(output, base64_test_vec[i].base256) != 0)
  545. return -97;
  546. }
  547. }
  548. return 0;
  549. }
  550. int encryption_test()
  551. {
  552. int rc;
  553. rc = base64_test();
  554. if (rc != 0)
  555. return rc;
  556. rc = sha1_test1();
  557. if (rc != 0)
  558. return rc;
  559. rc = sha1_test2();
  560. if (rc != 0)
  561. return rc;
  562. rc = rfc2202_test();
  563. if (rc != 0)
  564. return rc;
  565. rc = crc32_test();
  566. if (rc != 0)
  567. return rc;
  568. return 0;
  569. }
  570. static void crc32_update(pj_crc32_context *c, const pj_uint8_t *data,
  571. pj_size_t nbytes)
  572. {
  573. pj_crc32_update(c, data, nbytes);
  574. }
  575. static void crc32_final(pj_crc32_context *ctx, pj_uint32_t *digest)
  576. {
  577. *digest = pj_crc32_final(ctx);
  578. }
  579. /* pj_md5_update() has len argument in unsigned, while other xxx_update
  580. * are in pj_size_t, hence the wrapper
  581. */
  582. static void md5_update_wrapper(pj_md5_context *ctx,
  583. unsigned char const *buf, pj_size_t len)
  584. {
  585. pj_md5_update(ctx, buf, len);
  586. }
  587. int encryption_benchmark()
  588. {
  589. pj_pool_t *pool;
  590. pj_uint8_t *input;
  591. union {
  592. pj_md5_context md5_context;
  593. pj_sha1_context sha1_context;
  594. } context;
  595. pj_uint8_t digest[32];
  596. pj_size_t input_len;
  597. struct algorithm
  598. {
  599. const char *name;
  600. void (*init_context)(void*);
  601. void (*update)(void*, const pj_uint8_t*, pj_size_t);
  602. void (*final)(void*, void*);
  603. pj_uint32_t t;
  604. } algorithms[] =
  605. {
  606. {
  607. "MD5 ",
  608. (void (*)(void*))&pj_md5_init,
  609. (void (*)(void*, const pj_uint8_t*, pj_size_t))&md5_update_wrapper,
  610. (void (*)(void*, void*))&pj_md5_final
  611. },
  612. {
  613. "SHA1 ",
  614. (void (*)(void*))&pj_sha1_init,
  615. (void (*)(void*, const pj_uint8_t*, pj_size_t))&pj_sha1_update,
  616. (void (*)(void*, void*))&pj_sha1_final
  617. },
  618. {
  619. "CRC32",
  620. (void (*)(void*))&pj_crc32_init,
  621. (void (*)(void*, const pj_uint8_t*, pj_size_t))&crc32_update,
  622. (void (*)(void*, void*))&crc32_final
  623. }
  624. };
  625. #if defined(PJ_DEBUG) && PJ_DEBUG!=0
  626. enum { LOOP = 1000 };
  627. #else
  628. enum { LOOP = 10000 };
  629. #endif
  630. unsigned i;
  631. double total_len;
  632. input_len = 2048;
  633. total_len = (unsigned)input_len * LOOP;
  634. pool = pj_pool_create(mem, "enc", input_len+256, 0, NULL);
  635. if (!pool)
  636. return PJ_ENOMEM;
  637. input = (pj_uint8_t*)pj_pool_alloc(pool, input_len);
  638. pj_memset(input, '\xaa', input_len);
  639. PJ_LOG(3, (THIS_FILE, " feeding %d Mbytes of data",
  640. (unsigned)(total_len/1024/1024)));
  641. /* Dry run */
  642. for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
  643. algorithms[i].init_context(&context);
  644. algorithms[i].update(&context, input, (unsigned)input_len);
  645. algorithms[i].final(&context, digest);
  646. }
  647. /* Run */
  648. for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
  649. int j;
  650. pj_timestamp t1, t2;
  651. pj_get_timestamp(&t1);
  652. algorithms[i].init_context(&context);
  653. for (j=0; j<LOOP; ++j) {
  654. algorithms[i].update(&context, input, (unsigned)input_len);
  655. }
  656. algorithms[i].final(&context, digest);
  657. pj_get_timestamp(&t2);
  658. algorithms[i].t = pj_elapsed_usec(&t1, &t2);
  659. }
  660. /* Results */
  661. for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
  662. double bytes;
  663. bytes = (total_len * 1000000 / algorithms[i].t);
  664. PJ_LOG(3, (THIS_FILE, " %s:%8d usec (%3d.%03d Mbytes/sec)",
  665. algorithms[i].name, algorithms[i].t,
  666. (unsigned)(bytes / 1024 / 1024),
  667. ((unsigned)(bytes) % (1024 * 1024)) / 1024));
  668. }
  669. return 0;
  670. }
  671. #endif /* INCLUDE_ENCRYPTION_TEST */