001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.crypto;
028:
029: /**
030: * Implements the MD2 hashing algorithm as described in IETF RFC 1321
031: * (see http://www.ietf.org/rfc/rfc1321.txt)
032: */
033: final class MD2 extends MessageDigest {
034: /*
035: * The compute intensive operations are implemented in C
036: * based on the OpenSSL MD2 code (from pilotSSLeay). Here we
037: * replicate the state the C code needs.
038: */
039:
040: /** State needed for MD2 hash. */
041: private int[] num = new int[1];
042: /** State needed for MD2 hash. */
043: private byte[] data = new byte[16];
044: /** State needed for MD2 hash. */
045: private int[] cksm = new int[16];
046: /** State needed for MD2 hash. */
047: private int[] state = new int[16];
048:
049: /** Create an MD2 digest object. */
050: MD2() {
051: reset();
052: }
053:
054: /**
055: * Gets the message digest algorithm.
056: * @return algorithm implemented by this MessageDigest object
057: */
058: public String getAlgorithm() {
059: return "MD2";
060: }
061:
062: /**
063: * Gets the length (in bytes) of the hash.
064: * @return byte-length of the hash produced by this object
065: */
066: public int getDigestLength() {
067: return 16;
068: }
069:
070: /**
071: * Resets the MessageDigest to the initial state for further use.
072: */
073: public void reset() {
074: num[0] = 0;
075:
076: for (int i = 0; i < 16; i++) {
077: data[i] = (byte) 0;
078: cksm[i] = 0;
079: state[i] = 0;
080: }
081: }
082:
083: /**
084: * Accumulates a hash of the input data. Continues an MD2
085: * message-digest operation, processing another message
086: * block, and updating the internal context.
087: * @param inBuf input buffer of data to be hashed
088: * @param inOff offset within inBuf where input data begins
089: * @param inLen length (in bytes) of data to be hashed
090: * @see #doFinal(byte[], int, int, byte[], int)
091: */
092: public void update(byte[] inBuf, int inOff, int inLen) {
093: if (inLen == 0) {
094: return;
095: }
096:
097: // check parameters to prevent VM from crashing
098: int test = inBuf[inOff] + inBuf[inLen - 1]
099: + inBuf[inOff + inLen - 1];
100:
101: nativeUpdate(inBuf, inOff, inLen, state, num, cksm, data);
102: }
103:
104: /**
105: * Accumulates a hash of the input data. Continues an MD2
106: * message-digest operation, processing another message
107: * block, and updating the internal context.
108: * @param inBuf input buffer of data to be hashed
109: * @param inOff offset within inBuf where input data begins
110: * @param inLen length (in bytes) of data to be hashed
111: * @param state internal hash state
112: * @param num internal hash state
113: * @param cksm internal hash state
114: * @param data internal hash state
115: */
116: private static native void nativeUpdate(byte[] inBuf, int inOff,
117: int inLen, int[] state, int[] num, int[] cksm, byte[] data);
118:
119: /**
120: * Completes the hash computation by performing final operations
121: * such as padding. The digest is reset after this call is made.
122: *
123: * @param buf output buffer for the computed digest
124: *
125: * @param offset offset into the output buffer to begin storing the digest
126: *
127: * @param len number of bytes within buf allotted for the digest
128: *
129: * @return the number of bytes placed into <code>buf</code>
130: *
131: * @exception DigestException if an error occurs.
132: */
133: public int digest(byte[] buf, int offset, int len)
134: throws DigestException {
135: if (len < getDigestLength()) {
136: throw new DigestException("Buffer too short.");
137: }
138:
139: // check the parameters to prevent a VM crash
140: int test = buf[offset] + buf[offset + getDigestLength() - 1];
141:
142: nativeFinal(null, 0, 0, buf, offset, state, num, cksm, data);
143: return getDigestLength();
144: }
145:
146: /**
147: * Generates a hash of all/last input data. Completes and returns the
148: * hash compuatation after performing final operations such as padding.
149: * The MessageDigest object is reset after this call.
150: * @param inBuf input buffer of data to be hashed
151: * @param inOff offset within inBuf where input data begins
152: * @param inLen length (in bytes) of data to be hashed
153: * @param outBuf output buffer where the hash should be placed
154: * @param outOff offset within outBuf where the resulting hash begins
155: * @param state internal hash state
156: * @param num internal hash state
157: * @param cksm internal hash state
158: * @param data internal hash state
159: */
160: private static native void nativeFinal(byte[] inBuf, int inOff,
161: int inLen, byte[] outBuf, int outOff, int[] state,
162: int[] num, int[] cksm, byte[] data);
163:
164: /**
165: * Clones the MessageDigest object.
166: * @return a clone of this object
167: */
168: public Object clone() {
169: MD2 cpy = new MD2();
170:
171: System.arraycopy(this .state, 0, cpy.state, 0, 16);
172: System.arraycopy(this .num, 0, cpy.num, 0, 1);
173: System.arraycopy(this .cksm, 0, cpy.cksm, 0, 16);
174: System.arraycopy(this .data, 0, cpy.data, 0, 16);
175: return cpy;
176: }
177: }
|