1 /*
2  * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.security.provider;
27 
28 import java.security.*;
29 import java.util.Arrays;
30 
31 import static sun.security.provider.ByteArrayAccess.*;
32 import static sun.security.util.SecurityConstants.PROVIDER_VER;
33 
34 /**
35  * The MD4 class is used to compute an MD4 message digest over a given
36  * buffer of bytes. It is an implementation of the RSA Data Security Inc
37  * MD4 algorithim as described in internet RFC 1320.
38  *
39  * <p>The MD4 algorithm is very weak and should not be used unless it is
40  * unavoidable. Therefore, it is not registered in our standard providers. To
41  * obtain an implementation, call the static getInstance() method in this
42  * class.
43  *
44  * @author      Andreas Sterbenz
45  */
46 public final class MD4 extends DigestBase {
47 
48     // state of this object
49     private int[] state;
50 
51     // rotation constants
52     private static final int S11 = 3;
53     private static final int S12 = 7;
54     private static final int S13 = 11;
55     private static final int S14 = 19;
56     private static final int S21 = 3;
57     private static final int S22 = 5;
58     private static final int S23 = 9;
59     private static final int S24 = 13;
60     private static final int S31 = 3;
61     private static final int S32 = 9;
62     private static final int S33 = 11;
63     private static final int S34 = 15;
64 
65     private static final Provider md4Provider;
66 
67     static {
68         md4Provider = new Provider("MD4Provider", PROVIDER_VER,
69             "MD4 MessageDigest") {
70             @java.io.Serial
71             private static final long serialVersionUID = -8850464997518327965L;
72         };
73         @SuppressWarnings("removal")
74         var dummy = AccessController.doPrivileged(new PrivilegedAction<Void>() {
75             public Void run() {
76                 md4Provider.put("MessageDigest.MD4", "sun.security.provider.MD4");
77                 return null;
78             }
79         });
80     }
81 
getInstance()82     public static MessageDigest getInstance() {
83         try {
84             return MessageDigest.getInstance("MD4", md4Provider);
85         } catch (NoSuchAlgorithmException e) {
86             // should never occur
87             throw new ProviderException(e);
88         }
89     }
90 
91     // Standard constructor, creates a new MD4 instance.
MD4()92     public MD4() {
93         super("MD4", 16, 64);
94         state = new int[4];
95         resetHashes();
96     }
97 
98     // clone this object
clone()99     public Object clone() throws CloneNotSupportedException {
100         MD4 copy = (MD4) super.clone();
101         copy.state = copy.state.clone();
102         return copy;
103     }
104 
105     /**
106      * Reset the state of this object.
107      */
implReset()108     void implReset() {
109         // Load magic initialization constants.
110         resetHashes();
111     }
112 
resetHashes()113     private void resetHashes() {
114         state[0] = 0x67452301;
115         state[1] = 0xefcdab89;
116         state[2] = 0x98badcfe;
117         state[3] = 0x10325476;
118     }
119 
120     /**
121      * Perform the final computations, any buffered bytes are added
122      * to the digest, the count is added to the digest, and the resulting
123      * digest is stored.
124      */
implDigest(byte[] out, int ofs)125     void implDigest(byte[] out, int ofs) {
126         long bitsProcessed = bytesProcessed << 3;
127 
128         int index = (int)bytesProcessed & 0x3f;
129         int padLen = (index < 56) ? (56 - index) : (120 - index);
130         engineUpdate(padding, 0, padLen);
131 
132         i2bLittle4((int)bitsProcessed, buffer, 56);
133         i2bLittle4((int)(bitsProcessed >>> 32), buffer, 60);
134         implCompress(buffer, 0);
135 
136         i2bLittle(state, 0, out, ofs, 16);
137     }
138 
FF(int a, int b, int c, int d, int x, int s)139     private static int FF(int a, int b, int c, int d, int x, int s) {
140         a += ((b & c) | ((~b) & d)) + x;
141         return ((a << s) | (a >>> (32 - s)));
142     }
143 
GG(int a, int b, int c, int d, int x, int s)144     private static int GG(int a, int b, int c, int d, int x, int s) {
145         a += ((b & c) | (b & d) | (c & d)) + x + 0x5a827999;
146         return ((a << s) | (a >>> (32 - s)));
147     }
148 
HH(int a, int b, int c, int d, int x, int s)149     private static int HH(int a, int b, int c, int d, int x, int s) {
150         a += ((b ^ c) ^ d) + x + 0x6ed9eba1;
151         return ((a << s) | (a >>> (32 - s)));
152     }
153 
154     /**
155      * This is where the functions come together as the generic MD4
156      * transformation operation. It consumes sixteen
157      * bytes from the buffer, beginning at the specified offset.
158      */
implCompress(byte[] buf, int ofs)159     void implCompress(byte[] buf, int ofs) {
160         int x0 = (int) LE.INT_ARRAY.get(buf, ofs);
161         int x1 = (int) LE.INT_ARRAY.get(buf, ofs + 4);
162         int x2 = (int) LE.INT_ARRAY.get(buf, ofs + 8);
163         int x3 = (int) LE.INT_ARRAY.get(buf, ofs + 12);
164         int x4 = (int) LE.INT_ARRAY.get(buf, ofs + 16);
165         int x5 = (int) LE.INT_ARRAY.get(buf, ofs + 20);
166         int x6 = (int) LE.INT_ARRAY.get(buf, ofs + 24);
167         int x7 = (int) LE.INT_ARRAY.get(buf, ofs + 28);
168         int x8 = (int) LE.INT_ARRAY.get(buf, ofs + 32);
169         int x9 = (int) LE.INT_ARRAY.get(buf, ofs + 36);
170         int x10 = (int) LE.INT_ARRAY.get(buf, ofs + 40);
171         int x11 = (int) LE.INT_ARRAY.get(buf, ofs + 44);
172         int x12 = (int) LE.INT_ARRAY.get(buf, ofs + 48);
173         int x13 = (int) LE.INT_ARRAY.get(buf, ofs + 52);
174         int x14 = (int) LE.INT_ARRAY.get(buf, ofs + 56);
175         int x15 = (int) LE.INT_ARRAY.get(buf, ofs + 60);
176 
177         int a = state[0];
178         int b = state[1];
179         int c = state[2];
180         int d = state[3];
181 
182         /* Round 1 */
183         a = FF (a, b, c, d, x0,  S11); /* 1 */
184         d = FF (d, a, b, c, x1,  S12); /* 2 */
185         c = FF (c, d, a, b, x2,  S13); /* 3 */
186         b = FF (b, c, d, a, x3,  S14); /* 4 */
187         a = FF (a, b, c, d, x4,  S11); /* 5 */
188         d = FF (d, a, b, c, x5,  S12); /* 6 */
189         c = FF (c, d, a, b, x6,  S13); /* 7 */
190         b = FF (b, c, d, a, x7,  S14); /* 8 */
191         a = FF (a, b, c, d, x8,  S11); /* 9 */
192         d = FF (d, a, b, c, x9,  S12); /* 10 */
193         c = FF (c, d, a, b, x10, S13); /* 11 */
194         b = FF (b, c, d, a, x11, S14); /* 12 */
195         a = FF (a, b, c, d, x12, S11); /* 13 */
196         d = FF (d, a, b, c, x13, S12); /* 14 */
197         c = FF (c, d, a, b, x14, S13); /* 15 */
198         b = FF (b, c, d, a, x15, S14); /* 16 */
199 
200         /* Round 2 */
201         a = GG (a, b, c, d, x0,  S21); /* 17 */
202         d = GG (d, a, b, c, x4,  S22); /* 18 */
203         c = GG (c, d, a, b, x8,  S23); /* 19 */
204         b = GG (b, c, d, a, x12, S24); /* 20 */
205         a = GG (a, b, c, d, x1,  S21); /* 21 */
206         d = GG (d, a, b, c, x5,  S22); /* 22 */
207         c = GG (c, d, a, b, x9,  S23); /* 23 */
208         b = GG (b, c, d, a, x13, S24); /* 24 */
209         a = GG (a, b, c, d, x2,  S21); /* 25 */
210         d = GG (d, a, b, c, x6,  S22); /* 26 */
211         c = GG (c, d, a, b, x10, S23); /* 27 */
212         b = GG (b, c, d, a, x14, S24); /* 28 */
213         a = GG (a, b, c, d, x3,  S21); /* 29 */
214         d = GG (d, a, b, c, x7,  S22); /* 30 */
215         c = GG (c, d, a, b, x11, S23); /* 31 */
216         b = GG (b, c, d, a, x15, S24); /* 32 */
217 
218         /* Round 3 */
219         a = HH (a, b, c, d, x0,  S31); /* 33 */
220         d = HH (d, a, b, c, x8,  S32); /* 34 */
221         c = HH (c, d, a, b, x4,  S33); /* 35 */
222         b = HH (b, c, d, a, x12, S34); /* 36 */
223         a = HH (a, b, c, d, x2,  S31); /* 37 */
224         d = HH (d, a, b, c, x10, S32); /* 38 */
225         c = HH (c, d, a, b, x6,  S33); /* 39 */
226         b = HH (b, c, d, a, x14, S34); /* 40 */
227         a = HH (a, b, c, d, x1,  S31); /* 41 */
228         d = HH (d, a, b, c, x9,  S32); /* 42 */
229         c = HH (c, d, a, b, x5,  S33); /* 43 */
230         b = HH (b, c, d, a, x13, S34); /* 44 */
231         a = HH (a, b, c, d, x3,  S31); /* 45 */
232         d = HH (d, a, b, c, x11, S32); /* 46 */
233         c = HH (c, d, a, b, x7,  S33); /* 47 */
234         b = HH (b, c, d, a, x15, S34); /* 48 */
235 
236         state[0] += a;
237         state[1] += b;
238         state[2] += c;
239         state[3] += d;
240     }
241 
242 }
243