Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java
41159 views
1
/*
2
* Copyright (c) 2000, 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. 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
/*
27
* (C) Copyright IBM Corp. 1999 All Rights Reserved.
28
* Copyright 1997 The Open Group Research Institute. All rights reserved.
29
*/
30
31
package sun.security.krb5;
32
33
import java.util.Arrays;
34
import sun.security.util.*;
35
import sun.security.krb5.internal.*;
36
import sun.security.krb5.internal.crypto.*;
37
import java.io.IOException;
38
import java.math.BigInteger;
39
40
/**
41
* This class encapsulates the concept of a Kerberos checksum.
42
*/
43
public class Checksum {
44
45
private int cksumType;
46
private byte[] checksum;
47
48
// ----------------------------------------------+-------------+-----------
49
// Checksum type |sumtype |checksum
50
// |value | size
51
// ----------------------------------------------+-------------+-----------
52
public static final int CKSUMTYPE_NULL = 0; // 0
53
public static final int CKSUMTYPE_CRC32 = 1; // 4
54
public static final int CKSUMTYPE_RSA_MD4 = 2; // 16
55
public static final int CKSUMTYPE_RSA_MD4_DES = 3; // 24
56
public static final int CKSUMTYPE_DES_MAC = 4; // 16
57
public static final int CKSUMTYPE_DES_MAC_K = 5; // 8
58
public static final int CKSUMTYPE_RSA_MD4_DES_K = 6; // 16
59
public static final int CKSUMTYPE_RSA_MD5 = 7; // 16
60
public static final int CKSUMTYPE_RSA_MD5_DES = 8; // 24
61
62
// draft-ietf-krb-wg-crypto-07.txt
63
public static final int CKSUMTYPE_HMAC_SHA1_DES3_KD = 12; // 20
64
65
// draft-raeburn-krb-rijndael-krb-07.txt
66
public static final int CKSUMTYPE_HMAC_SHA1_96_AES128 = 15; // 96
67
public static final int CKSUMTYPE_HMAC_SHA1_96_AES256 = 16; // 96
68
69
// rfc8009
70
public static final int CKSUMTYPE_HMAC_SHA256_128_AES128 = 19; // 96
71
public static final int CKSUMTYPE_HMAC_SHA384_192_AES256 = 20; // 96
72
73
// draft-brezak-win2k-krb-rc4-hmac-04.txt
74
public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;
75
76
// default checksum type, -1 if not set
77
static int CKSUMTYPE_DEFAULT;
78
static int SAFECKSUMTYPE_DEFAULT;
79
80
private static boolean DEBUG = Krb5.DEBUG;
81
static {
82
initStatic();
83
}
84
85
public static void initStatic() {
86
String temp = null;
87
Config cfg = null;
88
try {
89
cfg = Config.getInstance();
90
temp = cfg.get("libdefaults", "default_checksum");
91
if (temp != null) {
92
CKSUMTYPE_DEFAULT = Config.getType(temp);
93
} else {
94
CKSUMTYPE_DEFAULT = -1;
95
}
96
} catch (Exception exc) {
97
if (DEBUG) {
98
System.out.println("Exception in getting default checksum "+
99
"value from the configuration. " +
100
"No default checksum set.");
101
exc.printStackTrace();
102
}
103
CKSUMTYPE_DEFAULT = -1;
104
}
105
106
107
try {
108
temp = cfg.get("libdefaults", "safe_checksum_type");
109
if (temp != null)
110
{
111
SAFECKSUMTYPE_DEFAULT = Config.getType(temp);
112
} else {
113
SAFECKSUMTYPE_DEFAULT = -1;
114
}
115
} catch (Exception exc) {
116
if (DEBUG) {
117
System.out.println("Exception in getting safe default " +
118
"checksum value " +
119
"from the configuration. " +
120
"No safe default checksum set.");
121
exc.printStackTrace();
122
}
123
SAFECKSUMTYPE_DEFAULT = -1;
124
}
125
}
126
127
/**
128
* Constructs a new Checksum using the raw data and type.
129
*
130
* This constructor is only used by Authenticator Checksum
131
* {@link sun.security.jgss.krb5.InitialToken.OverloadedChecksum}
132
* where the checksum type must be 0x8003
133
* (see https://tools.ietf.org/html/rfc4121#section-4.1.1)
134
* and checksum field/value is used to convey service flags,
135
* channel bindings, and optional delegation information.
136
* This special type does NOT have a {@link CksumType} and has its
137
* own calculating and verification rules. It does has the same
138
* ASN.1 encoding though.
139
*
140
* @param data the byte array of checksum.
141
* @param new_cksumType the type of checksum.
142
*/
143
public Checksum(byte[] data, int new_cksumType) {
144
cksumType = new_cksumType;
145
checksum = data;
146
}
147
148
/**
149
* Constructs a new Checksum by calculating over the data using
150
* the specified checksum type. If the checksum is unkeyed, key
151
* and usage are ignored.
152
*
153
* @param new_cksumType the type of checksum. If set to -1, the
154
* {@linkplain EType#checksumType() mandatory checksum type}
155
* for the encryption type of {@code key} will be used
156
* @param data the data that needs to be performed a checksum calculation on
157
* @param key the key used by a keyed checksum
158
* @param usage the usage used by a keyed checksum
159
*/
160
public Checksum(int new_cksumType, byte[] data,
161
EncryptionKey key, int usage)
162
throws KdcErrException, KrbApErrException, KrbCryptoException {
163
if (new_cksumType == -1) {
164
cksumType = EType.getInstance(key.getEType()).checksumType();
165
} else {
166
cksumType = new_cksumType;
167
}
168
checksum = CksumType.getInstance(cksumType).calculateChecksum(
169
data, data.length, key.getBytes(), usage);
170
}
171
172
/**
173
* Verifies the keyed checksum over the data passed in.
174
*/
175
public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key, int usage)
176
throws KdcErrException, KrbApErrException, KrbCryptoException {
177
CksumType cksumEngine = CksumType.getInstance(cksumType);
178
if (!cksumEngine.isKeyed()) {
179
throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
180
} else {
181
return cksumEngine.verifyChecksum(
182
data, data.length, key.getBytes(), checksum, usage);
183
}
184
}
185
186
187
/**
188
* Verifies the checksum over the data passed in. The checksum might
189
* be a keyed or not.
190
*
191
* =============== ATTENTION! Use with care ==================
192
* According to https://tools.ietf.org/html/rfc3961#section-6.1,
193
* An unkeyed checksum should only be used "in limited circumstances
194
* where the lack of a key does not provide a window for an attack,
195
* preferably as part of an encrypted message".
196
*/
197
public boolean verifyAnyChecksum(byte[] data, EncryptionKey key, int usage)
198
throws KdcErrException, KrbCryptoException {
199
return CksumType.getInstance(cksumType).verifyChecksum(
200
data, data.length, key.getBytes(), checksum, usage);
201
}
202
203
boolean isEqual(Checksum cksum) throws KdcErrException {
204
if (cksumType != cksum.cksumType) {
205
return false;
206
}
207
return CksumType.isChecksumEqual(checksum, cksum.checksum);
208
}
209
210
/**
211
* Constructs an instance of Checksum from an ASN.1 encoded representation.
212
* @param encoding a single DER-encoded value.
213
* @exception Asn1Exception if an error occurs while decoding an ASN1
214
* encoded data.
215
* @exception IOException if an I/O error occurs while reading encoded data.
216
*
217
*/
218
public Checksum(DerValue encoding) throws Asn1Exception, IOException {
219
DerValue der;
220
if (encoding.getTag() != DerValue.tag_Sequence) {
221
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
222
}
223
der = encoding.getData().getDerValue();
224
if ((der.getTag() & (byte)0x1F) == (byte)0x00) {
225
cksumType = der.getData().getBigInteger().intValue();
226
}
227
else
228
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
229
der = encoding.getData().getDerValue();
230
if ((der.getTag() & (byte)0x1F) == (byte)0x01) {
231
checksum = der.getData().getOctetString();
232
}
233
else
234
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
235
if (encoding.getData().available() > 0) {
236
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
237
}
238
}
239
240
/**
241
* Encodes a Checksum object.
242
* <pre>{@code
243
* Checksum ::= SEQUENCE {
244
* cksumtype [0] Int32,
245
* checksum [1] OCTET STRING
246
* }
247
* }</pre>
248
*
249
* <p>
250
* This definition reflects the Network Working Group RFC 4120
251
* specification available at
252
* <a href="http://www.ietf.org/rfc/rfc4120.txt">
253
* http://www.ietf.org/rfc/rfc4120.txt</a>.
254
* @return byte array of enocded Checksum.
255
* @exception Asn1Exception if an error occurs while decoding an
256
* ASN1 encoded data.
257
* @exception IOException if an I/O error occurs while reading
258
* encoded data.
259
*
260
*/
261
public byte[] asn1Encode() throws Asn1Exception, IOException {
262
DerOutputStream bytes = new DerOutputStream();
263
DerOutputStream temp = new DerOutputStream();
264
temp.putInteger(BigInteger.valueOf(cksumType));
265
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
266
true, (byte)0x00), temp);
267
temp = new DerOutputStream();
268
temp.putOctetString(checksum);
269
bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT,
270
true, (byte)0x01), temp);
271
temp = new DerOutputStream();
272
temp.write(DerValue.tag_Sequence, bytes);
273
return temp.toByteArray();
274
}
275
276
277
/**
278
* Parse (unmarshal) a checksum object from a DER input stream. This form
279
* parsing might be used when expanding a value which is part of
280
* a constructed sequence and uses explicitly tagged type.
281
*
282
* @exception Asn1Exception if an error occurs while decoding an
283
* ASN1 encoded data.
284
* @exception IOException if an I/O error occurs while reading
285
* encoded data.
286
* @param data the Der input stream value, which contains one or more
287
* marshaled value.
288
* @param explicitTag tag number.
289
* @param optional indicates if this data field is optional
290
* @return an instance of Checksum.
291
*
292
*/
293
public static Checksum parse(DerInputStream data,
294
byte explicitTag, boolean optional)
295
throws Asn1Exception, IOException {
296
297
if ((optional) &&
298
(((byte)data.peekByte() & (byte)0x1F) != explicitTag)) {
299
return null;
300
}
301
DerValue der = data.getDerValue();
302
if (explicitTag != (der.getTag() & (byte)0x1F)) {
303
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
304
} else {
305
DerValue subDer = der.getData().getDerValue();
306
return new Checksum(subDer);
307
}
308
}
309
310
/**
311
* Returns the raw bytes of the checksum, not in ASN.1 encoded form.
312
*/
313
public final byte[] getBytes() {
314
return checksum;
315
}
316
317
public final int getType() {
318
return cksumType;
319
}
320
321
@Override public boolean equals(Object obj) {
322
if (this == obj) {
323
return true;
324
}
325
if (!(obj instanceof Checksum)) {
326
return false;
327
}
328
329
try {
330
return isEqual((Checksum)obj);
331
} catch (KdcErrException kee) {
332
return false;
333
}
334
}
335
336
@Override public int hashCode() {
337
int result = 17;
338
result = 37 * result + cksumType;
339
if (checksum != null) {
340
result = 37 * result + Arrays.hashCode(checksum);
341
}
342
return result;
343
}
344
}
345
346