summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormcgreer%netscape.com <devnull@localhost>2000-05-12 23:35:06 +0000
committermcgreer%netscape.com <devnull@localhost>2000-05-12 23:35:06 +0000
commit65c22c5b4579c756676c8724cedc97f3f7682aba (patch)
tree31e19168ef2654bc20057deb8241e83531973a51
parent56490c41b6068923651588bd2589223e4bb1bfc6 (diff)
downloadnss-hg-65c22c5b4579c756676c8724cedc97f3f7682aba.tar.gz
Initial checkin of implementations of MD2 and MD5. An empty definition of Diffie-Hellman to allow for building, more later. Changes to Makefile for building with BSAFE.
-rw-r--r--security/nss/lib/freebl/Makefile11
-rw-r--r--security/nss/lib/freebl/dh.c82
-rw-r--r--security/nss/lib/freebl/manifest.mn11
-rw-r--r--security/nss/lib/freebl/md2.c288
-rw-r--r--security/nss/lib/freebl/md5.c519
5 files changed, 911 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile
index 08b7137d5..712a0516a 100644
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -74,3 +74,14 @@ include $(CORE_DEPTH)/coreconf/rules.mk
export:: private_export
+ifdef MOZILLA_BSAFE_BUILD
+ifeq ($(OS_ARCH),WINNT)
+libbsafe=bsafe41.lib
+else
+libbsafe=libbsafe.a
+endif
+
+private_export::
+ $(NSINSTALL) -m 777 $(libbsafe) $(DIST)/lib; \
+
+endif
diff --git a/security/nss/lib/freebl/dh.c b/security/nss/lib/freebl/dh.c
new file mode 100644
index 000000000..f366363bf
--- /dev/null
+++ b/security/nss/lib/freebl/dh.c
@@ -0,0 +1,82 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "prerr.h"
+#include "secerr.h"
+
+#include "blapi.h"
+
+SECStatus
+DH_GenParam(int primeLen, DHParams ** params)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ return SECFailure;
+}
+
+SECStatus
+DH_NewKey(DHParams * params,
+ DHPrivateKey ** privKey)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ return SECFailure;
+}
+
+SECStatus
+DH_Derive(SECItem * publicValue,
+ SECItem * prime,
+ SECItem * privateValue,
+ SECItem * derivedSecret,
+ unsigned int maxOutBytes)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ return SECFailure;
+}
+
+SECStatus
+KEA_Derive(SECItem *prime,
+ SECItem *public1,
+ SECItem *public2,
+ SECItem *private1,
+ SECItem *private2,
+ SECItem *derivedSecret)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ return SECFailure;
+}
+
+PRBool
+KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ return PR_FALSE;
+}
diff --git a/security/nss/lib/freebl/manifest.mn b/security/nss/lib/freebl/manifest.mn
index a8df2bc49..2e910744c 100644
--- a/security/nss/lib/freebl/manifest.mn
+++ b/security/nss/lib/freebl/manifest.mn
@@ -46,7 +46,18 @@ EXPORTS = \
PRIVATE_EXPORTS = \
$(NULL)
+ifdef MOZILLA_BSAFE_BUILD
CSRCS = \
+ fblstdlib.c \
sha_fast.c \
+ md2.c \
+ md5.c \
+ dh.c \
+ blapi_bsf.c \
$(NULL)
+else
+CSRCS = \
+ sha_fast.c \
+ $(NULL)
+endif
diff --git a/security/nss/lib/freebl/md2.c b/security/nss/lib/freebl/md2.c
new file mode 100644
index 000000000..e1a5fe0f4
--- /dev/null
+++ b/security/nss/lib/freebl/md2.c
@@ -0,0 +1,288 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "prerr.h"
+#include "secerr.h"
+
+#include "prtypes.h"
+
+#include "blapi.h"
+
+#define MD2_DIGEST_LEN 16
+#define MD2_BUFSIZE 16
+#define MD2_X_SIZE 48 /* The X array, [CV | INPUT | TMP VARS] */
+#define MD2_CV 0 /* index into X for chaining variables */
+#define MD2_INPUT 16 /* index into X for input */
+#define MD2_TMPVARS 32 /* index into X for temporary variables */
+#define MD2_CHECKSUM_SIZE 16
+
+struct MD2ContextStr {
+ unsigned char checksum[MD2_BUFSIZE];
+ unsigned char X[MD2_X_SIZE];
+ PRUint8 unusedBuffer;
+};
+
+static const PRUint8 MD2S[256] = {
+ 0051, 0056, 0103, 0311, 0242, 0330, 0174, 0001,
+ 0075, 0066, 0124, 0241, 0354, 0360, 0006, 0023,
+ 0142, 0247, 0005, 0363, 0300, 0307, 0163, 0214,
+ 0230, 0223, 0053, 0331, 0274, 0114, 0202, 0312,
+ 0036, 0233, 0127, 0074, 0375, 0324, 0340, 0026,
+ 0147, 0102, 0157, 0030, 0212, 0027, 0345, 0022,
+ 0276, 0116, 0304, 0326, 0332, 0236, 0336, 0111,
+ 0240, 0373, 0365, 0216, 0273, 0057, 0356, 0172,
+ 0251, 0150, 0171, 0221, 0025, 0262, 0007, 0077,
+ 0224, 0302, 0020, 0211, 0013, 0042, 0137, 0041,
+ 0200, 0177, 0135, 0232, 0132, 0220, 0062, 0047,
+ 0065, 0076, 0314, 0347, 0277, 0367, 0227, 0003,
+ 0377, 0031, 0060, 0263, 0110, 0245, 0265, 0321,
+ 0327, 0136, 0222, 0052, 0254, 0126, 0252, 0306,
+ 0117, 0270, 0070, 0322, 0226, 0244, 0175, 0266,
+ 0166, 0374, 0153, 0342, 0234, 0164, 0004, 0361,
+ 0105, 0235, 0160, 0131, 0144, 0161, 0207, 0040,
+ 0206, 0133, 0317, 0145, 0346, 0055, 0250, 0002,
+ 0033, 0140, 0045, 0255, 0256, 0260, 0271, 0366,
+ 0034, 0106, 0141, 0151, 0064, 0100, 0176, 0017,
+ 0125, 0107, 0243, 0043, 0335, 0121, 0257, 0072,
+ 0303, 0134, 0371, 0316, 0272, 0305, 0352, 0046,
+ 0054, 0123, 0015, 0156, 0205, 0050, 0204, 0011,
+ 0323, 0337, 0315, 0364, 0101, 0201, 0115, 0122,
+ 0152, 0334, 0067, 0310, 0154, 0301, 0253, 0372,
+ 0044, 0341, 0173, 0010, 0014, 0275, 0261, 0112,
+ 0170, 0210, 0225, 0213, 0343, 0143, 0350, 0155,
+ 0351, 0313, 0325, 0376, 0073, 0000, 0035, 0071,
+ 0362, 0357, 0267, 0016, 0146, 0130, 0320, 0344,
+ 0246, 0167, 0162, 0370, 0353, 0165, 0113, 0012,
+ 0061, 0104, 0120, 0264, 0217, 0355, 0037, 0032,
+ 0333, 0231, 0215, 0063, 0237, 0021, 0203, 0024
+};
+
+SECStatus
+MD2_Hash(unsigned char *dest, const char *src)
+{
+ unsigned int len;
+ MD2Context *cx = MD2_NewContext();
+ if (!cx) {
+ PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
+ return SECFailure;
+ }
+ MD2_Begin(cx);
+ MD2_Update(cx, (unsigned char *)src, PL_strlen(src));
+ MD2_End(cx, dest, &len, MD2_DIGEST_LEN);
+ MD2_DestroyContext(cx, PR_TRUE);
+ return SECSuccess;
+}
+
+MD2Context *
+MD2_NewContext(void)
+{
+ MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
+ if (cx == NULL) {
+ PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
+ return NULL;
+ }
+ return cx;
+}
+
+void
+MD2_DestroyContext(MD2Context *cx, PRBool freeit)
+{
+ if (freeit)
+ PORT_ZFree(cx, sizeof(*cx));
+}
+
+void
+MD2_Begin(MD2Context *cx)
+{
+ memset(cx, 0, sizeof(*cx));
+ cx->unusedBuffer = MD2_BUFSIZE;
+}
+
+static void
+md2_compress(MD2Context *cx)
+{
+ int j, k, l;
+ unsigned char P;
+ P = cx->checksum[MD2_CHECKSUM_SIZE-1];
+ /* Compute the running checksum, and set the tmp variables to be
+ * CV[i] XOR input[i]
+ */
+#define CKSUMFN(n) \
+ P = cx->checksum[n] ^ MD2S[cx->X[MD2_INPUT+n] ^ P]; \
+ cx->checksum[n] = P; \
+ cx->X[MD2_TMPVARS+n] = cx->X[n] ^ cx->X[MD2_INPUT+n];
+ CKSUMFN(0);
+ CKSUMFN(1);
+ CKSUMFN(2);
+ CKSUMFN(3);
+ CKSUMFN(4);
+ CKSUMFN(5);
+ CKSUMFN(6);
+ CKSUMFN(7);
+ CKSUMFN(8);
+ CKSUMFN(9);
+ CKSUMFN(10);
+ CKSUMFN(11);
+ CKSUMFN(12);
+ CKSUMFN(13);
+ CKSUMFN(14);
+ CKSUMFN(15);
+ /* The compression function. */
+#define COMPRESS(n) \
+ P = cx->X[n] ^ MD2S[P]; \
+ cx->X[n] = P;
+ P = 0x00;
+ for (j=0; j<18; j++) {
+ COMPRESS(0);
+ COMPRESS(1);
+ COMPRESS(2);
+ COMPRESS(3);
+ COMPRESS(4);
+ COMPRESS(5);
+ COMPRESS(6);
+ COMPRESS(7);
+ COMPRESS(8);
+ COMPRESS(9);
+ COMPRESS(10);
+ COMPRESS(11);
+ COMPRESS(12);
+ COMPRESS(13);
+ COMPRESS(14);
+ COMPRESS(15);
+ COMPRESS(16);
+ COMPRESS(17);
+ COMPRESS(18);
+ COMPRESS(19);
+ COMPRESS(20);
+ COMPRESS(21);
+ COMPRESS(22);
+ COMPRESS(23);
+ COMPRESS(24);
+ COMPRESS(25);
+ COMPRESS(26);
+ COMPRESS(27);
+ COMPRESS(28);
+ COMPRESS(29);
+ COMPRESS(30);
+ COMPRESS(31);
+ COMPRESS(32);
+ COMPRESS(33);
+ COMPRESS(34);
+ COMPRESS(35);
+ COMPRESS(36);
+ COMPRESS(37);
+ COMPRESS(38);
+ COMPRESS(39);
+ COMPRESS(40);
+ COMPRESS(41);
+ COMPRESS(42);
+ COMPRESS(43);
+ COMPRESS(44);
+ COMPRESS(45);
+ COMPRESS(46);
+ COMPRESS(47);
+ P = (P + j) % 256;
+ }
+ cx->unusedBuffer = MD2_BUFSIZE;
+}
+
+void
+MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)
+{
+ PRUint32 bytesToConsume;
+
+ /* Fill the remaining input buffer. */
+ if (cx->unusedBuffer != MD2_BUFSIZE) {
+ bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);
+ memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)],
+ input, bytesToConsume);
+ if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE)
+ md2_compress(cx);
+ inputLen -= bytesToConsume;
+ input += bytesToConsume;
+ }
+
+ /* Iterate over 16-byte chunks of the input. */
+ while (inputLen >= MD2_BUFSIZE) {
+ memcpy(&cx->X[MD2_INPUT], input, MD2_BUFSIZE);
+ md2_compress(cx);
+ inputLen -= MD2_BUFSIZE;
+ input += MD2_BUFSIZE;
+ }
+
+ /* Copy any input that remains into the buffer. */
+ if (inputLen)
+ memcpy(&cx->X[MD2_INPUT], input, inputLen);
+ cx->unusedBuffer = MD2_BUFSIZE - inputLen;
+}
+
+void
+MD2_End(MD2Context *cx, unsigned char *digest,
+ unsigned int *digestLen, unsigned int maxDigestLen)
+{
+ PRUint8 padStart;
+ if (maxDigestLen < MD2_BUFSIZE) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return;
+ }
+ padStart = MD2_BUFSIZE - cx->unusedBuffer;
+ memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer,
+ cx->unusedBuffer);
+ md2_compress(cx);
+ memcpy(&cx->X[MD2_INPUT], cx->checksum, MD2_BUFSIZE);
+ md2_compress(cx);
+ *digestLen = MD2_DIGEST_LEN;
+ memcpy(digest, &cx->X[MD2_CV], MD2_DIGEST_LEN);
+}
+
+unsigned int
+MD2_FlattenSize(MD2Context *cx)
+{
+ return sizeof(*cx);
+}
+
+SECStatus
+MD2_Flatten(MD2Context *cx, unsigned char *space)
+{
+ memcpy(space, cx, sizeof(*cx));
+ return SECSuccess;
+}
+
+MD2Context *
+MD2_Resurrect(unsigned char *space, void *arg)
+{
+ MD2Context *cx = MD2_NewContext();
+ if (cx)
+ memcpy(cx, space, sizeof(*cx));
+ return cx;
+}
diff --git a/security/nss/lib/freebl/md5.c b/security/nss/lib/freebl/md5.c
new file mode 100644
index 000000000..3ebd3d8db
--- /dev/null
+++ b/security/nss/lib/freebl/md5.c
@@ -0,0 +1,519 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1994-2000 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL. If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "prerr.h"
+#include "secerr.h"
+
+#include "prtypes.h"
+#include "prlong.h"
+
+#include "blapi.h"
+
+#define MD5_HASH_LEN 16
+#define MD5_BUFFER_SIZE 64
+#define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
+
+#define CV0_1 0x67452301
+#define CV0_2 0xefcdab89
+#define CV0_3 0x98badcfe
+#define CV0_4 0x10325476
+
+#define T1_0 0xd76aa478
+#define T1_1 0xe8c7b756
+#define T1_2 0x242070db
+#define T1_3 0xc1bdceee
+#define T1_4 0xf57c0faf
+#define T1_5 0x4787c62a
+#define T1_6 0xa8304613
+#define T1_7 0xfd469501
+#define T1_8 0x698098d8
+#define T1_9 0x8b44f7af
+#define T1_10 0xffff5bb1
+#define T1_11 0x895cd7be
+#define T1_12 0x6b901122
+#define T1_13 0xfd987193
+#define T1_14 0xa679438e
+#define T1_15 0x49b40821
+
+#define T2_0 0xf61e2562
+#define T2_1 0xc040b340
+#define T2_2 0x265e5a51
+#define T2_3 0xe9b6c7aa
+#define T2_4 0xd62f105d
+#define T2_5 0x02441453
+#define T2_6 0xd8a1e681
+#define T2_7 0xe7d3fbc8
+#define T2_8 0x21e1cde6
+#define T2_9 0xc33707d6
+#define T2_10 0xf4d50d87
+#define T2_11 0x455a14ed
+#define T2_12 0xa9e3e905
+#define T2_13 0xfcefa3f8
+#define T2_14 0x676f02d9
+#define T2_15 0x8d2a4c8a
+
+#define T3_0 0xfffa3942
+#define T3_1 0x8771f681
+#define T3_2 0x6d9d6122
+#define T3_3 0xfde5380c
+#define T3_4 0xa4beea44
+#define T3_5 0x4bdecfa9
+#define T3_6 0xf6bb4b60
+#define T3_7 0xbebfbc70
+#define T3_8 0x289b7ec6
+#define T3_9 0xeaa127fa
+#define T3_10 0xd4ef3085
+#define T3_11 0x04881d05
+#define T3_12 0xd9d4d039
+#define T3_13 0xe6db99e5
+#define T3_14 0x1fa27cf8
+#define T3_15 0xc4ac5665
+
+#define T4_0 0xf4292244
+#define T4_1 0x432aff97
+#define T4_2 0xab9423a7
+#define T4_3 0xfc93a039
+#define T4_4 0x655b59c3
+#define T4_5 0x8f0ccc92
+#define T4_6 0xffeff47d
+#define T4_7 0x85845dd1
+#define T4_8 0x6fa87e4f
+#define T4_9 0xfe2ce6e0
+#define T4_10 0xa3014314
+#define T4_11 0x4e0811a1
+#define T4_12 0xf7537e82
+#define T4_13 0xbd3af235
+#define T4_14 0x2ad7d2bb
+#define T4_15 0xeb86d391
+
+#define R1B0 0
+#define R1B1 1
+#define R1B2 2
+#define R1B3 3
+#define R1B4 4
+#define R1B5 5
+#define R1B6 6
+#define R1B7 7
+#define R1B8 8
+#define R1B9 9
+#define R1B10 10
+#define R1B11 11
+#define R1B12 12
+#define R1B13 13
+#define R1B14 14
+#define R1B15 15
+
+#define R2B0 1
+#define R2B1 6
+#define R2B2 11
+#define R2B3 0
+#define R2B4 5
+#define R2B5 10
+#define R2B6 15
+#define R2B7 4
+#define R2B8 9
+#define R2B9 14
+#define R2B10 3
+#define R2B11 8
+#define R2B12 13
+#define R2B13 2
+#define R2B14 7
+#define R2B15 12
+
+#define R3B0 5
+#define R3B1 8
+#define R3B2 11
+#define R3B3 14
+#define R3B4 1
+#define R3B5 4
+#define R3B6 7
+#define R3B7 10
+#define R3B8 13
+#define R3B9 0
+#define R3B10 3
+#define R3B11 6
+#define R3B12 9
+#define R3B13 12
+#define R3B14 15
+#define R3B15 2
+
+#define R4B0 0
+#define R4B1 7
+#define R4B2 14
+#define R4B3 5
+#define R4B4 12
+#define R4B5 3
+#define R4B6 10
+#define R4B7 1
+#define R4B8 8
+#define R4B9 15
+#define R4B10 6
+#define R4B11 13
+#define R4B12 4
+#define R4B13 11
+#define R4B14 2
+#define R4B15 9
+
+#define S1_0 7
+#define S1_1 12
+#define S1_2 17
+#define S1_3 22
+
+#define S2_0 5
+#define S2_1 9
+#define S2_2 14
+#define S2_3 20
+
+#define S3_0 4
+#define S3_1 11
+#define S3_2 16
+#define S3_3 23
+
+#define S4_0 6
+#define S4_1 10
+#define S4_2 15
+#define S4_3 21
+
+struct MD5ContextStr {
+ PRUint32 lsbInput;
+ PRUint32 msbInput;
+ PRUint32 inBufIndex;
+ PRUint32 cv[4];
+ union {
+ PRUint8 b[64];
+ PRUint32 w[16];
+ } u;
+};
+
+#define inBuf u.b
+
+SECStatus
+MD5_Hash(unsigned char *dest, const char *src)
+{
+ return MD5_HashBuf(dest, (unsigned char *)src, PL_strlen(src));
+}
+
+SECStatus
+MD5_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
+{
+ unsigned int len;
+ MD5Context *cx = MD5_NewContext();
+ if (cx == NULL) {
+ PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
+ return SECFailure;
+ }
+ MD5_Begin(cx);
+ MD5_Update(cx, src, src_length);
+ MD5_End(cx, dest, &len, MD5_HASH_LEN);
+ MD5_DestroyContext(cx, PR_TRUE);
+ return SECSuccess;
+}
+
+MD5Context *
+MD5_NewContext(void)
+{
+ MD5Context *cx = (MD5Context *)PORT_ZAlloc(sizeof(MD5Context));
+ if (cx == NULL) {
+ PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
+ return NULL;
+ }
+ return cx;
+}
+
+void
+MD5_DestroyContext(MD5Context *cx, PRBool freeit)
+{
+ if (freeit) {
+ PORT_ZFree(cx, sizeof(MD5Context));
+ }
+}
+
+void
+MD5_Begin(MD5Context *cx)
+{
+ cx->lsbInput = 0;
+ cx->msbInput = 0;
+ cx->inBufIndex = 0;
+ memset(cx->inBuf, 0, sizeof(cx->inBuf));
+ cx->cv[0] = CV0_1;
+ cx->cv[1] = CV0_2;
+ cx->cv[2] = CV0_3;
+ cx->cv[3] = CV0_4;
+}
+
+#define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s))
+
+#define MASK 0x00ff00ff
+#ifdef IS_LITTLE_ENDIAN
+#define lendian(i32) \
+ (i32)
+#else
+#define lendian(i32) \
+ (tmp = i32 >> 16 | i32 << 16, (tmp & MASK) << 8 | tmp >> 8 & MASK)
+#endif
+
+#if defined(SOLARIS) || defined(HPUX)
+#define addto64(sumhigh, sumlow, addend) \
+ sumlow += addend; sumhigh += (sumlow < addend);
+#else
+#define addto64(sumhigh, sumlow, addend) \
+ sumlow += addend; if (sumlow < addend) ++sumhigh;
+#endif
+
+#define F(X, Y, Z) \
+ ((X & Y) | ((~X) & Z))
+
+#define G(X, Y, Z) \
+ ((X & Z) | (Y & (~Z)))
+
+#define H(X, Y, Z) \
+ (X ^ Y ^ Z)
+
+#define I(X, Y, Z) \
+ (Y ^ (X | (~Z)))
+
+#define FF(a, b, c, d, bufint, s, ti) \
+ a = b + cls(a + F(b, c, d) + bufint + ti, s)
+
+#define GG(a, b, c, d, bufint, s, ti) \
+ a = b + cls(a + G(b, c, d) + bufint + ti, s)
+
+#define HH(a, b, c, d, bufint, s, ti) \
+ a = b + cls(a + H(b, c, d) + bufint + ti, s)
+
+#define II(a, b, c, d, bufint, s, ti) \
+ a = b + cls(a + I(b, c, d) + bufint + ti, s)
+
+static void
+md5_compress(MD5Context *cx)
+{
+ int i;
+ PRUint32 a, b, c, d;
+ PRUint32 tmp;
+ a = cx->cv[0];
+ b = cx->cv[1];
+ c = cx->cv[2];
+ d = cx->cv[3];
+#ifndef IS_LITTLE_ENDIAN
+ for (i=0; i<16; ++i)
+ cx->u.w[i] = lendian(cx->u.w[i]);
+#endif
+ FF(a, b, c, d, cx->u.w[R1B0 ], S1_0, T1_0);
+ FF(d, a, b, c, cx->u.w[R1B1 ], S1_1, T1_1);
+ FF(c, d, a, b, cx->u.w[R1B2 ], S1_2, T1_2);
+ FF(b, c, d, a, cx->u.w[R1B3 ], S1_3, T1_3);
+ FF(a, b, c, d, cx->u.w[R1B4 ], S1_0, T1_4);
+ FF(d, a, b, c, cx->u.w[R1B5 ], S1_1, T1_5);
+ FF(c, d, a, b, cx->u.w[R1B6 ], S1_2, T1_6);
+ FF(b, c, d, a, cx->u.w[R1B7 ], S1_3, T1_7);
+ FF(a, b, c, d, cx->u.w[R1B8 ], S1_0, T1_8);
+ FF(d, a, b, c, cx->u.w[R1B9 ], S1_1, T1_9);
+ FF(c, d, a, b, cx->u.w[R1B10], S1_2, T1_10);
+ FF(b, c, d, a, cx->u.w[R1B11], S1_3, T1_11);
+ FF(a, b, c, d, cx->u.w[R1B12], S1_0, T1_12);
+ FF(d, a, b, c, cx->u.w[R1B13], S1_1, T1_13);
+ FF(c, d, a, b, cx->u.w[R1B14], S1_2, T1_14);
+ FF(b, c, d, a, cx->u.w[R1B15], S1_3, T1_15);
+ GG(a, b, c, d, cx->u.w[R2B0 ], S2_0, T2_0);
+ GG(d, a, b, c, cx->u.w[R2B1 ], S2_1, T2_1);
+ GG(c, d, a, b, cx->u.w[R2B2 ], S2_2, T2_2);
+ GG(b, c, d, a, cx->u.w[R2B3 ], S2_3, T2_3);
+ GG(a, b, c, d, cx->u.w[R2B4 ], S2_0, T2_4);
+ GG(d, a, b, c, cx->u.w[R2B5 ], S2_1, T2_5);
+ GG(c, d, a, b, cx->u.w[R2B6 ], S2_2, T2_6);
+ GG(b, c, d, a, cx->u.w[R2B7 ], S2_3, T2_7);
+ GG(a, b, c, d, cx->u.w[R2B8 ], S2_0, T2_8);
+ GG(d, a, b, c, cx->u.w[R2B9 ], S2_1, T2_9);
+ GG(c, d, a, b, cx->u.w[R2B10], S2_2, T2_10);
+ GG(b, c, d, a, cx->u.w[R2B11], S2_3, T2_11);
+ GG(a, b, c, d, cx->u.w[R2B12], S2_0, T2_12);
+ GG(d, a, b, c, cx->u.w[R2B13], S2_1, T2_13);
+ GG(c, d, a, b, cx->u.w[R2B14], S2_2, T2_14);
+ GG(b, c, d, a, cx->u.w[R2B15], S2_3, T2_15);
+ HH(a, b, c, d, cx->u.w[R3B0 ], S3_0, T3_0);
+ HH(d, a, b, c, cx->u.w[R3B1 ], S3_1, T3_1);
+ HH(c, d, a, b, cx->u.w[R3B2 ], S3_2, T3_2);
+ HH(b, c, d, a, cx->u.w[R3B3 ], S3_3, T3_3);
+ HH(a, b, c, d, cx->u.w[R3B4 ], S3_0, T3_4);
+ HH(d, a, b, c, cx->u.w[R3B5 ], S3_1, T3_5);
+ HH(c, d, a, b, cx->u.w[R3B6 ], S3_2, T3_6);
+ HH(b, c, d, a, cx->u.w[R3B7 ], S3_3, T3_7);
+ HH(a, b, c, d, cx->u.w[R3B8 ], S3_0, T3_8);
+ HH(d, a, b, c, cx->u.w[R3B9 ], S3_1, T3_9);
+ HH(c, d, a, b, cx->u.w[R3B10], S3_2, T3_10);
+ HH(b, c, d, a, cx->u.w[R3B11], S3_3, T3_11);
+ HH(a, b, c, d, cx->u.w[R3B12], S3_0, T3_12);
+ HH(d, a, b, c, cx->u.w[R3B13], S3_1, T3_13);
+ HH(c, d, a, b, cx->u.w[R3B14], S3_2, T3_14);
+ HH(b, c, d, a, cx->u.w[R3B15], S3_3, T3_15);
+ II(a, b, c, d, cx->u.w[R4B0 ], S4_0, T4_0);
+ II(d, a, b, c, cx->u.w[R4B1 ], S4_1, T4_1);
+ II(c, d, a, b, cx->u.w[R4B2 ], S4_2, T4_2);
+ II(b, c, d, a, cx->u.w[R4B3 ], S4_3, T4_3);
+ II(a, b, c, d, cx->u.w[R4B4 ], S4_0, T4_4);
+ II(d, a, b, c, cx->u.w[R4B5 ], S4_1, T4_5);
+ II(c, d, a, b, cx->u.w[R4B6 ], S4_2, T4_6);
+ II(b, c, d, a, cx->u.w[R4B7 ], S4_3, T4_7);
+ II(a, b, c, d, cx->u.w[R4B8 ], S4_0, T4_8);
+ II(d, a, b, c, cx->u.w[R4B9 ], S4_1, T4_9);
+ II(c, d, a, b, cx->u.w[R4B10], S4_2, T4_10);
+ II(b, c, d, a, cx->u.w[R4B11], S4_3, T4_11);
+ II(a, b, c, d, cx->u.w[R4B12], S4_0, T4_12);
+ II(d, a, b, c, cx->u.w[R4B13], S4_1, T4_13);
+ II(c, d, a, b, cx->u.w[R4B14], S4_2, T4_14);
+ II(b, c, d, a, cx->u.w[R4B15], S4_3, T4_15);
+ cx->cv[0] += a;
+ cx->cv[1] += b;
+ cx->cv[2] += c;
+ cx->cv[3] += d;
+ cx->inBufIndex = 0;
+}
+
+void
+MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
+{
+ PRUint32 bytesToConsume;
+
+ /* Add the number of input bytes to the 64-bit input counter. */
+ addto64(cx->msbInput, cx->lsbInput, inputLen);
+ if (cx->inBufIndex) {
+ /* There is already data in the buffer. Fill with input. */
+ bytesToConsume = PR_MIN(inputLen, MD5_BUFFER_SIZE - cx->inBufIndex);
+ memcpy(&cx->inBuf[cx->inBufIndex], input, bytesToConsume);
+ if (cx->inBufIndex + bytesToConsume >= MD5_BUFFER_SIZE)
+ /* The buffer is filled. Run the compression function. */
+ md5_compress(cx);
+ /* Remaining input. */
+ inputLen -= bytesToConsume;
+ input += bytesToConsume;
+ }
+
+ /* Iterate over 64-byte chunks of the message. */
+ while (inputLen >= MD5_BUFFER_SIZE) {
+ memcpy(cx->inBuf, input, MD5_BUFFER_SIZE);
+ md5_compress(cx);
+ inputLen -= MD5_BUFFER_SIZE;
+ input += MD5_BUFFER_SIZE;
+ }
+
+ /* Tail of message (message bytes mod 64). */
+ if (inputLen)
+ memcpy(cx->inBuf, input, inputLen);
+ cx->inBufIndex = inputLen;
+}
+
+static const unsigned char padbytes[] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+void
+MD5_End(MD5Context *cx, unsigned char *digest,
+ unsigned int *digestLen, unsigned int maxDigestLen)
+{
+ PRUint32 tmp;
+ PRUint32 lowInput, highInput;
+ int i;
+
+ if (maxDigestLen < MD5_HASH_LEN) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return;
+ }
+
+ /* Copy out the length of bits input before padding. */
+ lowInput = cx->lsbInput;
+ highInput = (cx->msbInput << 3) | (lowInput >> 29);
+ lowInput <<= 3;
+
+ if (cx->inBufIndex < MD5_END_BUFFER) {
+ MD5_Update(cx, padbytes, MD5_END_BUFFER - cx->inBufIndex);
+ } else {
+ MD5_Update(cx, padbytes,
+ MD5_END_BUFFER + MD5_BUFFER_SIZE - cx->inBufIndex);
+ }
+
+ /* Store the number of bytes input (before padding) in final 64 bits. */
+ cx->u.w[14] = lendian(lowInput);
+ cx->u.w[15] = lendian(highInput);
+
+ /* Final call to compress. */
+ md5_compress(cx);
+
+ /* Copy the resulting values out of the chain variables into return buf. */
+ *digestLen = MD5_HASH_LEN;
+#ifndef IS_LITTLE_ENDIAN
+ cx->cv[0] = lendian(cx->cv[0]);
+ cx->cv[1] = lendian(cx->cv[1]);
+ cx->cv[2] = lendian(cx->cv[2]);
+ cx->cv[3] = lendian(cx->cv[3]);
+#endif
+ memcpy(digest, cx->cv, MD5_HASH_LEN);
+}
+
+unsigned int
+MD5_FlattenSize(MD5Context *cx)
+{
+ return sizeof(*cx);
+}
+
+SECStatus
+MD5_Flatten(MD5Context *cx, unsigned char *space)
+{
+ memcpy(space, cx, sizeof(*cx));
+ return SECSuccess;
+}
+
+MD5Context *
+MD5_Resurrect(unsigned char *space, void *arg)
+{
+ MD5Context *cx = MD5_NewContext();
+ if (cx)
+ memcpy(cx, space, sizeof(*cx));
+ return cx;
+}
+
+void
+MD5_TraceState(MD5Context *cx)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+}