* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/05/051fef84896e76c3f43c27daba87fedab537faf5.svn-base b/jni/pjproject-android/.svn/pristine/05/051fef84896e76c3f43c27daba87fedab537faf5.svn-base
new file mode 100644
index 0000000..4298aa3
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/05/051fef84896e76c3f43c27daba87fedab537faf5.svn-base
@@ -0,0 +1,766 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include "test.h"
+#include <pjlib-util.h>
+#include <pjlib.h>
+
+
+#if INCLUDE_ENCRYPTION_TEST
+
+/*
+ * Encryption algorithm tests.
+ */
+#define THIS_FILE   "encryption.c"
+
+
+/*
+ * SHA1 test from the original sha1.c source file.
+ */
+static char *sha1_test_data[] = {
+    "abc",
+    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+    "A million repetitions of 'a'"
+};
+static char *sha1_test_results[] = {
+    "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
+    "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
+    "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"
+};
+
+
+static void digest_to_hex(const pj_uint8_t digest[PJ_SHA1_DIGEST_SIZE], 
+			  char *output)
+{
+    int i,j;
+    char *c = output;
+    
+    for (i = 0; i < PJ_SHA1_DIGEST_SIZE/4; i++) {
+        for (j = 0; j < 4; j++) {
+            sprintf(c,"%02X", digest[i*4+j]);
+            c += 2;
+        }
+        sprintf(c, " ");
+        c += 1;
+    }
+    *(c - 1) = '\0';
+}
+
+static int sha1_test1(void)
+{
+    enum { MILLION = 1000000 };
+    int k;
+    pj_sha1_context context;
+    pj_uint8_t digest[20];
+    char output[80];
+    pj_pool_t *pool;
+    pj_uint8_t *block;
+
+    PJ_LOG(3, (THIS_FILE, "  SHA1 test vector 1 from sha1.c.."));
+    
+    for (k = 0; k < 2; k++){ 
+        pj_sha1_init(&context);
+        pj_sha1_update(&context, (pj_uint8_t*)sha1_test_data[k], 
+		       pj_ansi_strlen(sha1_test_data[k]));
+        pj_sha1_final(&context, digest);
+	digest_to_hex(digest, output);
+
+        if (pj_ansi_strcmp(output, sha1_test_results[k])) {
+	    PJ_LOG(3, (THIS_FILE, "    incorrect hash result on k=%d", k));
+            return -10;
+        }
+    }
+
+    /* million 'a' vector we feed separately */
+    pj_sha1_init(&context);
+    for (k = 0; k < MILLION; k++)
+        pj_sha1_update(&context, (pj_uint8_t*)"a", 1);
+    pj_sha1_final(&context, digest);
+    digest_to_hex(digest, output);
+    if (strcmp(output, sha1_test_results[2])) {
+	PJ_LOG(3, (THIS_FILE, "    incorrect hash result!"));
+        return -20;
+    }
+
+    /* million 'a' test, using block */
+    pool = pj_pool_create(mem, "sha1test", 256, 512, NULL);
+    block = (pj_uint8_t*)pj_pool_alloc(pool, MILLION);
+    pj_memset(block, 'a', MILLION);
+
+    pj_sha1_init(&context);
+    pj_sha1_update(&context, block, MILLION);
+    pj_sha1_final(&context, digest);
+    digest_to_hex(digest, output);
+    if (strcmp(output, sha1_test_results[2])) {
+	pj_pool_release(pool);
+	PJ_LOG(3, (THIS_FILE, "    incorrect hash result for block update!"));
+        return -21;
+    }
+
+    /* verify that original buffer was not modified */
+    for (k=0; k<MILLION; ++k) {
+	if (block[k] != 'a') {
+	    pj_pool_release(pool);
+	    PJ_LOG(3, (THIS_FILE, "    block was modified!"));
+	    return -22;
+	}
+    }
+
+    pj_pool_release(pool);
+
+    /* success */
+    return(0);
+}
+
+
+/*
+ * SHA1 test from RFC 3174
+ */
+/*
+ *  Define patterns for testing
+ */
+#define TEST1   "abc"
+#define TEST2a  "abcdbcdecdefdefgefghfghighijhi"
+#define TEST2b  "jkijkljklmklmnlmnomnopnopq"
+#define TEST2   TEST2a TEST2b
+#define TEST3   "a"
+#define TEST4a  "01234567012345670123456701234567"
+#define TEST4b  "01234567012345670123456701234567"
+    /* an exact multiple of 512 bits */
+#define TEST4   TEST4a TEST4b
+
+static char *testarray[4] =
+{
+    TEST1,
+    TEST2,
+    TEST3,
+    TEST4
+};
+static int repeatcount[4] = { 1, 1, 1000000, 10 };
+static char *resultarray[4] =
+{
+    "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
+    "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
+    "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F",
+    "DEA356A2 CDDD90C7 A7ECEDC5 EBB56393 4F460452"
+};
+
+static int sha1_test2(void)
+{
+    pj_sha1_context sha;
+    int i;
+    pj_uint8_t digest[20];
+    char char_digest[64];
+
+    PJ_LOG(3, (THIS_FILE, "  SHA1 test vector 2 from rfc 3174.."));
+
+    for(i = 0; i < 4; ++i) {
+	int j;
+
+        pj_sha1_init(&sha);
+
+        for(j = 0; j < repeatcount[i]; ++j) {
+            pj_sha1_update(&sha,
+			   (const pj_uint8_t *) testarray[i],
+			   pj_ansi_strlen(testarray[i]));
+        }
+
+        pj_sha1_final(&sha, digest);
+
+	digest_to_hex(digest, char_digest);
+	if (pj_ansi_strcmp(char_digest, resultarray[i])) {
+	    PJ_LOG(3, (THIS_FILE, "    digest mismatch in test %d", i));
+	    return -40;
+	}
+    }
+
+    return 0;
+}
+
+
+/*
+ * HMAC-MD5 and HMAC-SHA1 test vectors from RFC 2202
+ */
+struct rfc2202_test
+{
+    char       *key;
+    unsigned	key_len;
+    char       *input;
+    unsigned	input_len;
+    char       *md5_digest;
+    char       *sha1_digest;
+};
+
+
+struct rfc2202_test rfc2202_test_vector[] = 
+{
+    {
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+	16,
+	"Hi There",
+	8,
+	"\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
+	NULL
+    },
+    {
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
+	20,
+	"Hi There",
+	8,
+	NULL,
+	"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"
+    },
+    {
+	"Jefe",
+	4,
+	"what do ya want for nothing?",
+	28,
+	"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
+	"\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79"
+    },
+    {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa",
+	16,
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+	50,
+	"\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6",
+	NULL
+    },
+    {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+	20,
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
+	50,
+	NULL,
+	"\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
+    },
+    {
+	"\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",
+	25,
+	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
+	50,
+	"\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79",
+	"\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda"
+    },
+    {
+	"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+	"\x0c\x0c\x0c\x0c\x0c\x0c",
+	16,
+	"Test With Truncation",
+	20,
+	"\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c",
+	NULL
+    },
+    {
+	"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+	"\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
+	20,
+	"Test With Truncation",
+	20,
+	NULL,
+	"\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32\x4a\x9a\x5a\x04"
+    },
+    {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+	80,
+	"Test Using Larger Than Block-Size Key - Hash Key First",
+	54,
+	"\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd",
+	"\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12"
+    },
+    {
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+	80,
+	"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
+	73,
+	"\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e",
+	"\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91"
+    }
+};
+
+
+static int rfc2202_test(void)
+{
+    unsigned i;
+
+    PJ_LOG(3, (THIS_FILE, "  verifying test vectors from rfc 2202.."));
+
+    /* Verify that test vectors are valid */
+    for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
+	PJ_ASSERT_RETURN(pj_ansi_strlen(rfc2202_test_vector[i].input) == 
+			    rfc2202_test_vector[i].input_len, -50);
+	PJ_ASSERT_RETURN(pj_ansi_strlen(rfc2202_test_vector[i].key) == 
+			    rfc2202_test_vector[i].key_len, -52);
+	PJ_ASSERT_RETURN(rfc2202_test_vector[i].md5_digest==NULL ||
+			    pj_ansi_strlen(rfc2202_test_vector[i].md5_digest)<=16,
+			    -54);
+	PJ_ASSERT_RETURN(rfc2202_test_vector[i].sha1_digest==NULL ||
+			    pj_ansi_strlen(rfc2202_test_vector[i].sha1_digest)<=20,
+			    -56);
+    }
+
+    /* Test HMAC-MD5 */
+    PJ_LOG(3, (THIS_FILE, "  HMAC-MD5 test vectors from rfc 2202.."));
+    for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
+	pj_uint8_t digest_buf[18], *digest;
+
+	if (rfc2202_test_vector[i].md5_digest == NULL)
+	    continue;
+
+	digest_buf[0] = '\0';
+	digest_buf[17] = '\0';
+
+	digest = digest_buf+1;
+
+	pj_hmac_md5((pj_uint8_t*)rfc2202_test_vector[i].input, 
+		    rfc2202_test_vector[i].input_len,
+		    (pj_uint8_t*)rfc2202_test_vector[i].key, 
+		    rfc2202_test_vector[i].key_len,
+		    digest);
+
+	/* Check for overwrites */
+	if (digest_buf[0] != '\0' || digest_buf[17] != '\0') {
+	    PJ_LOG(3, (THIS_FILE, "    error: overwriting outside buffer on test %d", i));
+	    return -60;
+	}
+
+	/* Compare digest */
+	if (pj_memcmp(rfc2202_test_vector[i].md5_digest, digest, 16)) {
+	    PJ_LOG(3, (THIS_FILE, "    error: digest mismatch on test %d", i));
+	    return -65;
+	}
+    }
+
+    /* Test HMAC-SHA1 */
+    PJ_LOG(3, (THIS_FILE, "  HMAC-SHA1 test vectors from rfc 2202.."));
+    for (i=0; i<PJ_ARRAY_SIZE(rfc2202_test_vector); ++i) {
+	pj_uint8_t digest_buf[22], *digest;
+
+	if (rfc2202_test_vector[i].sha1_digest == NULL)
+	    continue;
+
+	digest_buf[0] = '\0';
+	digest_buf[21] = '\0';
+
+	digest = digest_buf+1;
+
+	pj_hmac_sha1((pj_uint8_t*)rfc2202_test_vector[i].input, 
+		     rfc2202_test_vector[i].input_len,
+		     (pj_uint8_t*)rfc2202_test_vector[i].key, 
+		     rfc2202_test_vector[i].key_len,
+		     digest);
+
+	/* Check for overwrites */
+	if (digest_buf[0] != '\0' || digest_buf[21] != '\0') {
+	    PJ_LOG(3, (THIS_FILE, "    error: overwriting outside buffer on test %d", i));
+	    return -70;
+	}
+
+	/* Compare digest */
+	if (pj_memcmp(rfc2202_test_vector[i].sha1_digest, digest, 20)) {
+	    PJ_LOG(3, (THIS_FILE, "    error: digest mismatch on test %d", i));
+	    return -75;
+	}
+    }
+
+
+    /* Success */
+    return 0;
+}
+
+/* CRC32 test data, generated from crc32 test on a Linux box */
+struct crc32_test_t
+{
+    char	    *input;
+    pj_uint32_t	     crc;
+} crc32_test_data[] = 
+{
+    {
+	"",
+	0x0
+    },
+    {
+	"Hello World",
+	0x4a17b156
+    },
+    {
+	/* Something read from /dev/random */
+	"\x21\x21\x98\x10\x62\x59\xbc\x58\x42\x24\xe5\xf3\x92\x0a\x68\x3c\xa7\x67\x73\xc3",
+	0x506693be
+    },
+    {
+	"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+	0xcab11777
+    },
+    {
+	"123456789",
+	0xCBF43926
+    }
+};
+
+/*
+ * CRC32 test
+ */
+static int crc32_test(void)
+{
+    unsigned i;
+
+    PJ_LOG(3, (THIS_FILE, "  crc32 test.."));
+
+    /* testing pj_crc32_calc */
+    for (i=0; i<PJ_ARRAY_SIZE(crc32_test_data); ++i) {
+	pj_uint32_t crc;
+
+	crc = pj_crc32_calc((pj_uint8_t*)crc32_test_data[i].input,
+			    pj_ansi_strlen(crc32_test_data[i].input));
+	if (crc != crc32_test_data[i].crc) {
+	    PJ_LOG(3,(THIS_FILE, "    error: crc mismatch on test %d", i));
+	    return -80;
+	}
+    }
+
+    /* testing incremental CRC32 calculation */
+    for (i=0; i<PJ_ARRAY_SIZE(crc32_test_data); ++i) {
+	pj_crc32_context ctx;
+	pj_uint32_t crc0, crc1;
+	pj_size_t len;
+
+	len = pj_ansi_strlen(crc32_test_data[i].input);
+	crc0 = pj_crc32_calc((pj_uint8_t*)crc32_test_data[i].input, len);
+
+	pj_crc32_init(&ctx);
+	pj_crc32_update(&ctx, (pj_uint8_t*)crc32_test_data[i].input,
+			len / 2);
+
+	if (len/2 > 0) {
+	    pj_crc32_update(&ctx, (pj_uint8_t*)crc32_test_data[i].input + len/2,
+			    len - len/2);
+	}
+
+	crc1 = pj_crc32_final(&ctx);
+
+	if (crc0 != crc1) {
+	    PJ_LOG(3,(THIS_FILE, 
+		      "    error: crc algorithm error on test %d", i));
+	    return -85;
+	}
+
+    }
+    return 0;
+}
+
+enum
+{
+    ENCODE = 1,
+    DECODE = 2,
+    ENCODE_DECODE = 3
+};
+
+/*
+ * Base64 test vectors (RFC 4648)
+ */
+static struct base64_test_vec
+{
+    const char *base256;
+    const char *base64;
+    unsigned flag;
+} base64_test_vec[] = 
+{
+    {
+	"",
+	"",
+	ENCODE_DECODE
+    },
+    {
+	"f",
+	"Zg==",
+	ENCODE_DECODE
+    },
+    {
+	"fo",
+	"Zm8=",
+	ENCODE_DECODE
+    },
+    {
+	"foo",
+	"Zm9v",
+	ENCODE_DECODE
+    },
+    {
+	"foob",
+	"Zm9vYg==",
+	ENCODE_DECODE
+    },
+    {
+	"fooba",
+	"Zm9vYmE=",
+	ENCODE_DECODE
+    },
+    {
+	"foobar",
+	"Zm9vYmFy",
+	ENCODE_DECODE
+    },
+    {
+	"\x14\xfb\x9c\x03\xd9\x7e",
+	"FPucA9l+",
+	ENCODE_DECODE
+    },
+    {
+	"\x14\xfb\x9c\x03\xd9",
+	"FPucA9k=",
+	ENCODE_DECODE
+    },
+    {
+	"\x14\xfb\x9c\x03",
+	"FPucAw==",
+	ENCODE_DECODE
+    },
+    /* with whitespaces */
+    {
+	"foobar",
+	"Zm9v\r\nYmFy",
+	DECODE
+    },
+    {
+    	"foobar",
+    	"\nZ\r\nm 9\tv\nYm\nF\ny\n",
+    	DECODE
+    },
+};
+
+
+static int base64_test(void)
+{
+    unsigned i;
+    char output[80];
+    pj_status_t rc;
+
+    PJ_LOG(3, (THIS_FILE, "  base64 test.."));
+
+    for (i=0; i<PJ_ARRAY_SIZE(base64_test_vec); ++i) {
+	pj_str_t input;
+	int out_len;
+
+	/* Encode test */
+	if (base64_test_vec[i].flag & ENCODE) {
+	    out_len = sizeof(output);
+	    rc = pj_base64_encode((pj_uint8_t*)base64_test_vec[i].base256,
+				  (int)strlen(base64_test_vec[i].base256),
+				  output, &out_len);
+	    if (rc != PJ_SUCCESS)
+		return -90;
+
+	    if (out_len != (int)strlen(base64_test_vec[i].base64))
+		return -91;
+
+	    output[out_len] = '\0';
+	    if (strcmp(output, base64_test_vec[i].base64) != 0)
+		return -92;
+	}
+
+	/* Decode test */
+	if (base64_test_vec[i].flag & DECODE) {
+	    out_len = sizeof(output);
+	    input.ptr = (char*)base64_test_vec[i].base64;
+	    input.slen = strlen(base64_test_vec[i].base64);
+	    rc = pj_base64_decode(&input, (pj_uint8_t*)output, &out_len);
+	    if (rc != PJ_SUCCESS)
+		return -95;
+
+	    if (out_len != (int)strlen(base64_test_vec[i].base256))
+		return -96;
+
+	    output[out_len] = '\0';
+
+	    if (strcmp(output, base64_test_vec[i].base256) != 0)
+		return -97;
+	}
+    }
+
+    return 0;
+}
+
+
+int encryption_test()
+{
+    int rc;
+
+    rc = base64_test();
+    if (rc != 0)
+	return rc;
+
+    rc = sha1_test1();
+    if (rc != 0)
+	return rc;
+
+    rc = sha1_test2();
+    if (rc != 0)
+	return rc;
+
+    rc = rfc2202_test();
+    if (rc != 0)
+	return rc;
+
+    rc = crc32_test();
+    if (rc != 0)
+	return rc;
+
+    return 0;
+}
+
+static void crc32_update(pj_crc32_context *c, const pj_uint8_t *data,
+			 pj_size_t nbytes)
+{
+    pj_crc32_update(c, data, nbytes);
+}
+
+static void crc32_final(pj_crc32_context *ctx, pj_uint32_t *digest)
+{
+    *digest = pj_crc32_final(ctx);
+}
+
+int encryption_benchmark()
+{
+    pj_pool_t *pool;
+    pj_uint8_t *input;
+    union {
+	pj_md5_context md5_context;
+	pj_sha1_context sha1_context;
+    } context;
+    pj_uint8_t digest[32];
+    pj_size_t input_len;
+    struct algorithm
+    {
+	const char *name;
+	void (*init_context)(void*);
+	void (*update)(void*, const pj_uint8_t*, unsigned);
+	void (*final)(void*, void*);
+	pj_uint32_t t;
+    } algorithms[] = 
+    {
+	{
+	    "MD5  ",
+	    (void (*)(void*))&pj_md5_init,
+	    (void (*)(void*, const pj_uint8_t*, unsigned))&pj_md5_update,
+	    (void (*)(void*, void*))&pj_md5_final
+	},
+	{
+	    "SHA1 ",
+	    (void (*)(void*))&pj_sha1_init,
+	    (void (*)(void*, const pj_uint8_t*, unsigned))&pj_sha1_update,
+	    (void (*)(void*, void*))&pj_sha1_final
+	},
+	{
+	    "CRC32",
+	    (void (*)(void*))&pj_crc32_init,
+	    (void (*)(void*, const pj_uint8_t*, unsigned))&crc32_update,
+	    (void (*)(void*, void*))&crc32_final
+	}
+    };
+#if defined(PJ_DEBUG) && PJ_DEBUG!=0
+    enum { LOOP = 1000 };
+#else
+    enum { LOOP = 10000 };
+#endif
+    unsigned i;
+    double total_len;
+
+    input_len = 2048;
+    total_len = (unsigned)input_len * LOOP;
+    pool = pj_pool_create(mem, "enc", input_len+256, 0, NULL);
+    if (!pool)
+	return PJ_ENOMEM;
+
+    input = (pj_uint8_t*)pj_pool_alloc(pool, input_len);
+    pj_memset(input, '\xaa', input_len);
+    
+    PJ_LOG(3, (THIS_FILE, "  feeding %d Mbytes of data",
+	       (unsigned)(total_len/1024/1024)));
+
+    /* Dry run */
+    for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
+	algorithms[i].init_context(&context);
+	algorithms[i].update(&context, input, (unsigned)input_len);
+	algorithms[i].final(&context, digest);
+    }
+
+    /* Run */
+    for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
+	int j;
+	pj_timestamp t1, t2;
+
+	pj_get_timestamp(&t1);
+	algorithms[i].init_context(&context);
+	for (j=0; j<LOOP; ++j) {
+	    algorithms[i].update(&context, input, (unsigned)input_len);
+	}
+	algorithms[i].final(&context, digest);
+	pj_get_timestamp(&t2);
+
+	algorithms[i].t = pj_elapsed_usec(&t1, &t2);
+    }
+
+    /* Results */
+    for (i=0; i<PJ_ARRAY_SIZE(algorithms); ++i) {
+	double bytes;
+
+	bytes = (total_len * 1000000 / algorithms[i].t);
+	PJ_LOG(3, (THIS_FILE, "    %s:%8d usec (%3d.%03d Mbytes/sec)",
+		   algorithms[i].name, algorithms[i].t,
+		   (unsigned)(bytes / 1024 / 1024),
+		   ((unsigned)(bytes) % (1024 * 1024)) / 1024));
+    }
+
+    return 0;
+}
+
+
+
+#endif /* INCLUDE_ENCRYPTION_TEST */
+