Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/AEAD/GCMLargeDataKAT.java
41161 views
1
/*
2
* Copyright (c) 2019, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import javax.crypto.Cipher;
25
import javax.crypto.SecretKey;
26
import javax.crypto.spec.GCMParameterSpec;
27
import javax.crypto.spec.SecretKeySpec;
28
import java.security.MessageDigest;
29
import java.util.HashMap;
30
31
/*
32
* @test
33
* @bug 8220165
34
* @summary Verify correctness of large data sizes for GCM.
35
*/
36
37
/**
38
* This test stores the MD5 hash of correctly encrypted AES/GCM data for
39
* particular data lengths. Those lengths are run on SunJCE to verify returns
40
* the same MD5 hash of the encrypted data. These are not NIST data sets or
41
* provided by any other organization. The data sets are known good values,
42
* verified with two different JCE providers (solaris-sparcv9 ucrypto and
43
* linux SunJCE).
44
*
45
* Lengths around 64k are chosen because 64k is the point where
46
* com.sun.crypto.provider.GaloisCounterMode#doLastBlock() starts it's
47
* intrinsic warmup
48
*
49
* Plaintext is all zeros. Preset key and IV.
50
*
51
* The choice of MD5 is for speed. Shortcoming of the algorithm are
52
* not relevant for this test.
53
*/
54
55
public class GCMLargeDataKAT {
56
57
// Hash of encrypted results of AES/GCM for particular lengths.
58
// <data size, hash>
59
static final HashMap<Integer, String> results = new HashMap<>() {{
60
put(65534, "1397b91c31ce793895edace4e175bfee"); //64k-2
61
put(65535, "4ad101c9f450e686668b3f8f05db96f0"); //64k-1
62
put(65536, "fbfaee3451acd3f603200d6be0f39b24"); //64k
63
put(65537, "e7dfca4a71495c65d20982c3c9b9813f"); //64k+1
64
put(67583, "c8ebdcb3532ec6c165de961341af7635"); //66k-1
65
put(67584, "36559d108dfd25dd29da3fec3455b9e5"); //66k
66
put(67585, "1d21b42d80ea179810744fc23dc228b6"); //66k+1
67
put(102400, "0d1544fcab20bbd4c8103b9d273f2c82"); //100k
68
put(102401, "f2d53ef65fd12d0a861368659b23ea2e"); //100k+1
69
put(102402, "97f0f524cf63d2d9d23d81e64d416ee0"); //100k+2
70
put(102403, "4a6b4af55b7d9016b64114d6813d639c"); //100k+3
71
put(102404, "ba63cc131fcde2f12ddf2ac634201be8"); //100k+4
72
put(102405, "673d05c7fe5e283e42e5c0d049fdcea6"); //100k+5
73
put(102406, "76cc99a7850ce857eb3cb43049cf9877"); //100k+6
74
put(102407, "65863f99072cf2eb7fce18bd78b33f4e"); //100k+7
75
put(102408, "b9184f0f272682cc1f791fa7070eddd4"); //100k+8
76
put(102409, "45fe36afef43cc665bf22a9ca200c3c2"); //100k+9
77
put(102410, "67249e41646edcb37a78a61b0743cf11"); //100k+0
78
put(102411, "ffdc611e29c8849842e81ec78f32c415"); //100k+11
79
put(102412, "b7fde7fd52221057dccc1c181a140125"); //100k+12
80
put(102413, "4b1d6c64d56448105e5613157e69c0ae"); //100k+13
81
put(102414, "6d2c0b26c0c8785c8eec3298a5f0080c"); //100k+14
82
put(102415, "1df2061b114fbe56bdf3717e3ee61ef9"); //100k+15
83
put(102416, "a691742692c683ac9d1254df5fc5f768"); //100k+16
84
}};
85
static final int HIGHLEN = 102416;
86
87
static final int GCM_TAG_LENGTH = 16;
88
static final byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
89
static final byte[] key_code = {
90
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
91
};
92
static final GCMParameterSpec spec =
93
new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
94
static final SecretKey key = new SecretKeySpec(key_code, "AES");
95
static boolean testresult = true;
96
static byte[] plaintext = new byte[HIGHLEN];
97
static MessageDigest md5;
98
Cipher cipher;
99
100
GCMLargeDataKAT() {
101
}
102
103
byte[] encrypt(int inLen) {
104
try {
105
cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
106
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
107
return cipher.doFinal(plaintext, 0, inLen);
108
} catch (Exception e) {
109
System.err.println("Encrypt Failure (length = " + inLen + ") : " +
110
e.getMessage());
111
e.printStackTrace();
112
}
113
return new byte[0];
114
}
115
116
static byte[] hash(byte[] data) {
117
return md5.digest(data);
118
}
119
120
// Decrypt the data and return a boolean if the plaintext is all 0's.
121
boolean decrypt(byte[] data) {
122
byte[] result = null;
123
int len = data.length - GCM_TAG_LENGTH;
124
if (data.length == 0) {
125
return false;
126
}
127
try {
128
cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
129
cipher.init(Cipher.DECRYPT_MODE, key, spec);
130
result = cipher.doFinal(data);
131
} catch (Exception e) {
132
System.err.println("Decrypt Failure (length = " + len + ") : " +
133
e.getMessage());
134
e.printStackTrace();
135
return false;
136
}
137
138
if (result.length != len) {
139
System.err.println("Decrypt Failure (length = " + len +
140
") : plaintext length invalid = " + result.length);
141
}
142
// Return false if we find a non zero.
143
int i = 0;
144
while (result.length > i) {
145
if (result[i++] != 0) {
146
System.err.println("Decrypt Failure (length = " + len +
147
") : plaintext invalid, char index " + i);
148
return false;
149
}
150
}
151
return true;
152
}
153
154
void test() throws Exception {
155
156
// results order is not important
157
for (int l : results.keySet()) {
158
byte[] enc = new GCMLargeDataKAT().encrypt(l);
159
160
// verify hash with stored hash of that length
161
String hashstr = toHex(hash(enc));
162
boolean r = (hashstr.compareTo(results.get(l)) == 0);
163
164
System.out.println("---------------------------------------------");
165
166
// Encrypted test & results
167
System.out.println("Encrypt data size " + l + " \tResult: " +
168
(r ? "Pass" : "Fail"));
169
if (!r) {
170
if (enc.length != 0) {
171
System.out.println("\tExpected: " + results.get(l));
172
System.out.println("\tReturned: " + hashstr);
173
}
174
testresult = false;
175
continue;
176
}
177
178
// Decrypted test & results
179
r = decrypt(enc);
180
System.out.println("Decrypt data size " + l + " \tResult: " +
181
(r ? "Pass" : "Fail"));
182
if (!r) {
183
testresult = false;
184
}
185
}
186
187
// After test complete, throw an error if there was a failure
188
if (!testresult) {
189
throw new Exception("Tests failed");
190
}
191
}
192
193
/**
194
* With no argument, the test will run the predefined data lengths
195
*
196
* With an integer argument, this test will print the hash of the encrypted
197
* data of that integer length.
198
*
199
*/
200
public static void main(String args[]) throws Exception {
201
md5 = MessageDigest.getInstance("MD5");
202
203
if (args.length > 0) {
204
int len = Integer.parseInt(args[0]);
205
byte[] e = new GCMLargeDataKAT().encrypt(len);
206
System.out.println(toHex(hash(e)));
207
return;
208
}
209
210
new GCMLargeDataKAT().test();
211
}
212
213
// bytes to hex string
214
static String toHex(byte[] bytes) {
215
StringBuffer hexStringBuffer = new StringBuffer(32);
216
for (int i = 0; i < bytes.length; i++) {
217
hexStringBuffer.append(byteToHex(bytes[i]));
218
}
219
return hexStringBuffer.toString();
220
}
221
// byte to hex
222
static String byteToHex(byte num) {
223
char[] hexDigits = new char[2];
224
hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
225
hexDigits[1] = Character.forDigit((num & 0xF), 16);
226
return new String(hexDigits);
227
}
228
}
229
230