Back to index

lightning-sunbird  0.9+nobinonly
md2.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "prerr.h"
00038 #include "secerr.h"
00039 
00040 #include "prtypes.h"
00041 
00042 #include "blapi.h"
00043 
00044 #define MD2_DIGEST_LEN    16
00045 #define MD2_BUFSIZE       16
00046 #define MD2_X_SIZE        48  /* The X array, [CV | INPUT | TMP VARS] */
00047 #define MD2_CV             0  /* index into X for chaining variables */
00048 #define MD2_INPUT         16  /* index into X for input */
00049 #define MD2_TMPVARS       32  /* index into X for temporary variables */
00050 #define MD2_CHECKSUM_SIZE 16
00051 
00052 struct MD2ContextStr {
00053        unsigned char checksum[MD2_BUFSIZE];
00054        unsigned char X[MD2_X_SIZE];
00055        PRUint8 unusedBuffer;
00056 };
00057 
00058 static const PRUint8 MD2S[256] = {
00059  0051, 0056, 0103, 0311, 0242, 0330, 0174, 0001,
00060  0075, 0066, 0124, 0241, 0354, 0360, 0006, 0023,
00061  0142, 0247, 0005, 0363, 0300, 0307, 0163, 0214,
00062  0230, 0223, 0053, 0331, 0274, 0114, 0202, 0312,
00063  0036, 0233, 0127, 0074, 0375, 0324, 0340, 0026,
00064  0147, 0102, 0157, 0030, 0212, 0027, 0345, 0022,
00065  0276, 0116, 0304, 0326, 0332, 0236, 0336, 0111,
00066  0240, 0373, 0365, 0216, 0273, 0057, 0356, 0172,
00067  0251, 0150, 0171, 0221, 0025, 0262, 0007, 0077,
00068  0224, 0302, 0020, 0211, 0013, 0042, 0137, 0041,
00069  0200, 0177, 0135, 0232, 0132, 0220, 0062, 0047,
00070  0065, 0076, 0314, 0347, 0277, 0367, 0227, 0003,
00071  0377, 0031, 0060, 0263, 0110, 0245, 0265, 0321,
00072  0327, 0136, 0222, 0052, 0254, 0126, 0252, 0306,
00073  0117, 0270, 0070, 0322, 0226, 0244, 0175, 0266,
00074  0166, 0374, 0153, 0342, 0234, 0164, 0004, 0361,
00075  0105, 0235, 0160, 0131, 0144, 0161, 0207, 0040,
00076  0206, 0133, 0317, 0145, 0346, 0055, 0250, 0002,
00077  0033, 0140, 0045, 0255, 0256, 0260, 0271, 0366,
00078  0034, 0106, 0141, 0151, 0064, 0100, 0176, 0017,
00079  0125, 0107, 0243, 0043, 0335, 0121, 0257, 0072,
00080  0303, 0134, 0371, 0316, 0272, 0305, 0352, 0046,
00081  0054, 0123, 0015, 0156, 0205, 0050, 0204, 0011,
00082  0323, 0337, 0315, 0364, 0101, 0201, 0115, 0122,
00083  0152, 0334, 0067, 0310, 0154, 0301, 0253, 0372,
00084  0044, 0341, 0173, 0010, 0014, 0275, 0261, 0112,
00085  0170, 0210, 0225, 0213, 0343, 0143, 0350, 0155,
00086  0351, 0313, 0325, 0376, 0073, 0000, 0035, 0071,
00087  0362, 0357, 0267, 0016, 0146, 0130, 0320, 0344,
00088  0246, 0167, 0162, 0370, 0353, 0165, 0113, 0012,
00089  0061, 0104, 0120, 0264, 0217, 0355, 0037, 0032,
00090  0333, 0231, 0215, 0063, 0237, 0021, 0203, 0024
00091 };
00092 
00093 SECStatus 
00094 MD2_Hash(unsigned char *dest, const char *src)
00095 {
00096        unsigned int len;
00097        MD2Context *cx = MD2_NewContext();
00098        if (!cx) {
00099               PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
00100               return SECFailure;
00101        }
00102        MD2_Begin(cx);
00103        MD2_Update(cx, (unsigned char *)src, PL_strlen(src));
00104        MD2_End(cx, dest, &len, MD2_DIGEST_LEN);
00105        MD2_DestroyContext(cx, PR_TRUE);
00106        return SECSuccess;
00107 }
00108 
00109 MD2Context *
00110 MD2_NewContext(void)
00111 {
00112        MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
00113        if (cx == NULL) {
00114               PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
00115               return NULL;
00116        }
00117        return cx;
00118 }
00119 
00120 void 
00121 MD2_DestroyContext(MD2Context *cx, PRBool freeit)
00122 {
00123        if (freeit)
00124               PORT_ZFree(cx, sizeof(*cx));
00125 }
00126 
00127 void 
00128 MD2_Begin(MD2Context *cx)
00129 {
00130        memset(cx, 0, sizeof(*cx));
00131        cx->unusedBuffer = MD2_BUFSIZE;
00132 }
00133 
00134 static void
00135 md2_compress(MD2Context *cx)
00136 {
00137        int j;
00138        unsigned char P;
00139        P = cx->checksum[MD2_CHECKSUM_SIZE-1];
00140        /* Compute the running checksum, and set the tmp variables to be 
00141         * CV[i] XOR input[i] 
00142         */
00143 #define CKSUMFN(n) \
00144        P = cx->checksum[n] ^ MD2S[cx->X[MD2_INPUT+n] ^ P]; \
00145        cx->checksum[n] = P; \
00146        cx->X[MD2_TMPVARS+n] = cx->X[n] ^ cx->X[MD2_INPUT+n];
00147        CKSUMFN(0);
00148        CKSUMFN(1);
00149        CKSUMFN(2);
00150        CKSUMFN(3);
00151        CKSUMFN(4);
00152        CKSUMFN(5);
00153        CKSUMFN(6);
00154        CKSUMFN(7);
00155        CKSUMFN(8);
00156        CKSUMFN(9);
00157        CKSUMFN(10);
00158        CKSUMFN(11);
00159        CKSUMFN(12);
00160        CKSUMFN(13);
00161        CKSUMFN(14);
00162        CKSUMFN(15);
00163        /* The compression function. */
00164 #define COMPRESS(n) \
00165        P = cx->X[n] ^ MD2S[P]; \
00166        cx->X[n] = P;
00167        P = 0x00;
00168        for (j=0; j<18; j++) {
00169               COMPRESS(0);
00170               COMPRESS(1);
00171               COMPRESS(2);
00172               COMPRESS(3);
00173               COMPRESS(4);
00174               COMPRESS(5);
00175               COMPRESS(6);
00176               COMPRESS(7);
00177               COMPRESS(8);
00178               COMPRESS(9);
00179               COMPRESS(10);
00180               COMPRESS(11);
00181               COMPRESS(12);
00182               COMPRESS(13);
00183               COMPRESS(14);
00184               COMPRESS(15);
00185               COMPRESS(16);
00186               COMPRESS(17);
00187               COMPRESS(18);
00188               COMPRESS(19);
00189               COMPRESS(20);
00190               COMPRESS(21);
00191               COMPRESS(22);
00192               COMPRESS(23);
00193               COMPRESS(24);
00194               COMPRESS(25);
00195               COMPRESS(26);
00196               COMPRESS(27);
00197               COMPRESS(28);
00198               COMPRESS(29);
00199               COMPRESS(30);
00200               COMPRESS(31);
00201               COMPRESS(32);
00202               COMPRESS(33);
00203               COMPRESS(34);
00204               COMPRESS(35);
00205               COMPRESS(36);
00206               COMPRESS(37);
00207               COMPRESS(38);
00208               COMPRESS(39);
00209               COMPRESS(40);
00210               COMPRESS(41);
00211               COMPRESS(42);
00212               COMPRESS(43);
00213               COMPRESS(44);
00214               COMPRESS(45);
00215               COMPRESS(46);
00216               COMPRESS(47);
00217               P = (P + j) % 256;
00218        }
00219        cx->unusedBuffer = MD2_BUFSIZE;
00220 }
00221 
00222 void 
00223 MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)
00224 {
00225        PRUint32 bytesToConsume;
00226        
00227        /* Fill the remaining input buffer. */
00228        if (cx->unusedBuffer != MD2_BUFSIZE) {
00229               bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);
00230               memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)],
00231                           input, bytesToConsume);
00232               if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE)
00233                      md2_compress(cx);
00234               inputLen -= bytesToConsume;
00235               input += bytesToConsume;
00236        }
00237 
00238        /* Iterate over 16-byte chunks of the input. */
00239        while (inputLen >= MD2_BUFSIZE) {
00240               memcpy(&cx->X[MD2_INPUT], input, MD2_BUFSIZE);
00241               md2_compress(cx);
00242               inputLen -= MD2_BUFSIZE;
00243               input += MD2_BUFSIZE;
00244        }
00245 
00246        /* Copy any input that remains into the buffer. */
00247        if (inputLen)
00248               memcpy(&cx->X[MD2_INPUT], input, inputLen);
00249        cx->unusedBuffer = MD2_BUFSIZE - inputLen;
00250 }
00251 
00252 void 
00253 MD2_End(MD2Context *cx, unsigned char *digest,
00254         unsigned int *digestLen, unsigned int maxDigestLen)
00255 {
00256        PRUint8 padStart;
00257        if (maxDigestLen < MD2_BUFSIZE) {
00258               PORT_SetError(SEC_ERROR_INVALID_ARGS);
00259               return;
00260        }
00261        padStart = MD2_BUFSIZE - cx->unusedBuffer;
00262        memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer, 
00263                    cx->unusedBuffer);
00264        md2_compress(cx);
00265        memcpy(&cx->X[MD2_INPUT], cx->checksum, MD2_BUFSIZE);
00266        md2_compress(cx);
00267        *digestLen = MD2_DIGEST_LEN;
00268        memcpy(digest, &cx->X[MD2_CV], MD2_DIGEST_LEN);
00269 }
00270 
00271 unsigned int 
00272 MD2_FlattenSize(MD2Context *cx)
00273 {
00274        return sizeof(*cx);
00275 }
00276 
00277 SECStatus 
00278 MD2_Flatten(MD2Context *cx, unsigned char *space)
00279 {
00280        memcpy(space, cx, sizeof(*cx));
00281        return SECSuccess;
00282 }
00283 
00284 MD2Context * 
00285 MD2_Resurrect(unsigned char *space, void *arg)
00286 {
00287        MD2Context *cx = MD2_NewContext();
00288        if (cx)
00289               memcpy(cx, space, sizeof(*cx));
00290        return cx;
00291 }
00292 
00293 void MD2_Clone(MD2Context *dest, MD2Context *src) 
00294 {
00295        memcpy(dest, src, sizeof *dest);
00296 }