Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jgss/krb5/CipherHelper.java
38922 views
1
/*
2
* Copyright (c) 2004, 2017, 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.jgss.krb5;
27
28
import javax.crypto.Cipher;
29
import javax.crypto.SecretKey;
30
import javax.crypto.spec.IvParameterSpec;
31
import javax.crypto.spec.SecretKeySpec;
32
import javax.crypto.CipherInputStream;
33
import javax.crypto.CipherOutputStream;
34
import java.io.InputStream;
35
import java.io.OutputStream;
36
import java.io.IOException;
37
import org.ietf.jgss.*;
38
39
import java.security.MessageDigest;
40
import java.security.GeneralSecurityException;
41
import java.security.NoSuchAlgorithmException;
42
import sun.security.krb5.*;
43
import sun.security.krb5.internal.crypto.Des3;
44
import sun.security.krb5.internal.crypto.Aes128;
45
import sun.security.krb5.internal.crypto.Aes256;
46
import sun.security.krb5.internal.crypto.ArcFourHmac;
47
import sun.security.krb5.internal.crypto.EType;
48
49
class CipherHelper {
50
51
// From draft-raeburn-cat-gssapi-krb5-3des-00
52
// Key usage values when deriving keys
53
private static final int KG_USAGE_SEAL = 22;
54
private static final int KG_USAGE_SIGN = 23;
55
private static final int KG_USAGE_SEQ = 24;
56
57
private static final int DES_CHECKSUM_SIZE = 8;
58
private static final int DES_IV_SIZE = 8;
59
private static final int AES_IV_SIZE = 16;
60
61
// ARCFOUR-HMAC
62
// Save first 8 octets of HMAC Sgn_Cksum
63
private static final int HMAC_CHECKSUM_SIZE = 8;
64
// key usage for MIC tokens used by MS
65
private static final int KG_USAGE_SIGN_MS = 15;
66
67
// debug flag
68
private static final boolean DEBUG = Krb5Util.DEBUG;
69
70
/**
71
* A zero initial vector to be used for checksum calculation and for
72
* DesCbc application data encryption/decryption.
73
*/
74
private static final byte[] ZERO_IV = new byte[DES_IV_SIZE];
75
private static final byte[] ZERO_IV_AES = new byte[AES_IV_SIZE];
76
77
private int etype;
78
private int sgnAlg, sealAlg;
79
private byte[] keybytes;
80
81
CipherHelper(EncryptionKey key) throws GSSException {
82
etype = key.getEType();
83
keybytes = key.getBytes();
84
85
switch (etype) {
86
case EncryptedData.ETYPE_DES_CBC_CRC:
87
case EncryptedData.ETYPE_DES_CBC_MD5:
88
sgnAlg = MessageToken.SGN_ALG_DES_MAC_MD5;
89
sealAlg = MessageToken.SEAL_ALG_DES;
90
break;
91
92
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
93
sgnAlg = MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD;
94
sealAlg = MessageToken.SEAL_ALG_DES3_KD;
95
break;
96
97
case EncryptedData.ETYPE_ARCFOUR_HMAC:
98
sgnAlg = MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR;
99
sealAlg = MessageToken.SEAL_ALG_ARCFOUR_HMAC;
100
break;
101
102
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
103
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
104
sgnAlg = -1;
105
sealAlg = -1;
106
break;
107
108
default:
109
throw new GSSException(GSSException.FAILURE, -1,
110
"Unsupported encryption type: " + etype);
111
}
112
}
113
114
int getSgnAlg() {
115
return sgnAlg;
116
}
117
118
int getSealAlg() {
119
return sealAlg;
120
}
121
122
// new token format from draft-ietf-krb-wg-gssapi-cfx-07
123
// proto is used to determine new GSS token format for "newer" etypes
124
int getProto() {
125
return EType.isNewer(etype) ? 1 : 0;
126
}
127
128
int getEType() {
129
return etype;
130
}
131
132
boolean isArcFour() {
133
boolean flag = false;
134
if (etype == EncryptedData.ETYPE_ARCFOUR_HMAC) {
135
flag = true;
136
}
137
return flag;
138
}
139
140
@SuppressWarnings("fallthrough")
141
byte[] calculateChecksum(int alg, byte[] header, byte[] trailer,
142
byte[] data, int start, int len, int tokenId) throws GSSException {
143
144
switch (alg) {
145
case MessageToken.SGN_ALG_DES_MAC_MD5:
146
/*
147
* With this sign algorithm, first an MD5 hash is computed on the
148
* application data. The 16 byte hash is then DesCbc encrypted.
149
*/
150
try {
151
MessageDigest md5 = MessageDigest.getInstance("MD5");
152
153
// debug("\t\tdata=[");
154
155
// debug(getHexBytes(checksumDataHeader,
156
// checksumDataHeader.length) + " ");
157
md5.update(header);
158
159
// debug(getHexBytes(data, start, len));
160
md5.update(data, start, len);
161
162
if (trailer != null) {
163
// debug(" " +
164
// getHexBytes(trailer,
165
// optionalTrailer.length));
166
md5.update(trailer);
167
}
168
// debug("]\n");
169
170
data = md5.digest();
171
start = 0;
172
len = data.length;
173
// System.out.println("\tMD5 Checksum is [" +
174
// getHexBytes(data) + "]\n");
175
header = null;
176
trailer = null;
177
} catch (NoSuchAlgorithmException e) {
178
GSSException ge = new GSSException(GSSException.FAILURE, -1,
179
"Could not get MD5 Message Digest - " + e.getMessage());
180
ge.initCause(e);
181
throw ge;
182
}
183
// fall through to encrypt checksum
184
185
case MessageToken.SGN_ALG_DES_MAC:
186
return getDesCbcChecksum(keybytes, header, data, start, len);
187
188
case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD:
189
byte[] buf;
190
int offset, total;
191
if (header == null && trailer == null) {
192
buf = data;
193
total = len;
194
offset = start;
195
} else {
196
total = ((header != null ? header.length : 0) + len +
197
(trailer != null ? trailer.length : 0));
198
199
buf = new byte[total];
200
int pos = 0;
201
if (header != null) {
202
System.arraycopy(header, 0, buf, 0, header.length);
203
pos = header.length;
204
}
205
System.arraycopy(data, start, buf, pos, len);
206
pos += len;
207
if (trailer != null) {
208
System.arraycopy(trailer, 0, buf, pos, trailer.length);
209
}
210
211
offset = 0;
212
}
213
214
try {
215
216
/*
217
Krb5Token.debug("\nkeybytes: " +
218
Krb5Token.getHexBytes(keybytes));
219
Krb5Token.debug("\nheader: " + (header == null ? "NONE" :
220
Krb5Token.getHexBytes(header)));
221
Krb5Token.debug("\ntrailer: " + (trailer == null ? "NONE" :
222
Krb5Token.getHexBytes(trailer)));
223
Krb5Token.debug("\ndata: " +
224
Krb5Token.getHexBytes(data, start, len));
225
Krb5Token.debug("\nbuf: " + Krb5Token.getHexBytes(buf, offset,
226
total));
227
*/
228
229
byte[] answer = Des3.calculateChecksum(keybytes,
230
KG_USAGE_SIGN, buf, offset, total);
231
// Krb5Token.debug("\nanswer: " +
232
// Krb5Token.getHexBytes(answer));
233
return answer;
234
} catch (GeneralSecurityException e) {
235
GSSException ge = new GSSException(GSSException.FAILURE, -1,
236
"Could not use HMAC-SHA1-DES3-KD signing algorithm - " +
237
e.getMessage());
238
ge.initCause(e);
239
throw ge;
240
}
241
242
case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR:
243
byte[] buffer;
244
int off, tot;
245
if (header == null && trailer == null) {
246
buffer = data;
247
tot = len;
248
off = start;
249
} else {
250
tot = ((header != null ? header.length : 0) + len +
251
(trailer != null ? trailer.length : 0));
252
253
buffer = new byte[tot];
254
int pos = 0;
255
256
if (header != null) {
257
System.arraycopy(header, 0, buffer, 0, header.length);
258
pos = header.length;
259
}
260
System.arraycopy(data, start, buffer, pos, len);
261
pos += len;
262
if (trailer != null) {
263
System.arraycopy(trailer, 0, buffer, pos, trailer.length);
264
}
265
266
off = 0;
267
}
268
269
try {
270
271
/*
272
Krb5Token.debug("\nkeybytes: " +
273
Krb5Token.getHexBytes(keybytes));
274
Krb5Token.debug("\nheader: " + (header == null ? "NONE" :
275
Krb5Token.getHexBytes(header)));
276
Krb5Token.debug("\ntrailer: " + (trailer == null ? "NONE" :
277
Krb5Token.getHexBytes(trailer)));
278
Krb5Token.debug("\ndata: " +
279
Krb5Token.getHexBytes(data, start, len));
280
Krb5Token.debug("\nbuffer: " +
281
Krb5Token.getHexBytes(buffer, off, tot));
282
*/
283
284
// for MIC tokens, key derivation salt is 15
285
// NOTE: Required for interoperability. The RC4-HMAC spec
286
// defines key_usage of 23, however all Kerberos impl.
287
// MS/Solaris/MIT all use key_usage of 15 for MIC tokens
288
int key_usage = KG_USAGE_SIGN;
289
if (tokenId == Krb5Token.MIC_ID) {
290
key_usage = KG_USAGE_SIGN_MS;
291
}
292
byte[] answer = ArcFourHmac.calculateChecksum(keybytes,
293
key_usage, buffer, off, tot);
294
// Krb5Token.debug("\nanswer: " +
295
// Krb5Token.getHexBytes(answer));
296
297
// Save first 8 octets of HMAC Sgn_Cksum
298
byte[] output = new byte[getChecksumLength()];
299
System.arraycopy(answer, 0, output, 0, output.length);
300
// Krb5Token.debug("\nanswer (trimmed): " +
301
// Krb5Token.getHexBytes(output));
302
return output;
303
} catch (GeneralSecurityException e) {
304
GSSException ge = new GSSException(GSSException.FAILURE, -1,
305
"Could not use HMAC_MD5_ARCFOUR signing algorithm - " +
306
e.getMessage());
307
ge.initCause(e);
308
throw ge;
309
}
310
311
default:
312
throw new GSSException(GSSException.FAILURE, -1,
313
"Unsupported signing algorithm: " + sgnAlg);
314
}
315
}
316
317
// calculate Checksum for the new GSS tokens
318
byte[] calculateChecksum(byte[] header, byte[] data, int start, int len,
319
int key_usage) throws GSSException {
320
321
// total length
322
int total = ((header != null ? header.length : 0) + len);
323
324
// get_mic("plaintext-data" | "header")
325
byte[] buf = new byte[total];
326
327
// data
328
System.arraycopy(data, start, buf, 0, len);
329
330
// token header
331
if (header != null) {
332
System.arraycopy(header, 0, buf, len, header.length);
333
}
334
335
// Krb5Token.debug("\nAES calculate checksum on: " +
336
// Krb5Token.getHexBytes(buf));
337
switch (etype) {
338
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
339
try {
340
byte[] answer = Aes128.calculateChecksum(keybytes, key_usage,
341
buf, 0, total);
342
// Krb5Token.debug("\nAES128 checksum: " +
343
// Krb5Token.getHexBytes(answer));
344
return answer;
345
} catch (GeneralSecurityException e) {
346
GSSException ge = new GSSException(GSSException.FAILURE, -1,
347
"Could not use AES128 signing algorithm - " +
348
e.getMessage());
349
ge.initCause(e);
350
throw ge;
351
}
352
353
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
354
try {
355
byte[] answer = Aes256.calculateChecksum(keybytes, key_usage,
356
buf, 0, total);
357
// Krb5Token.debug("\nAES256 checksum: " +
358
// Krb5Token.getHexBytes(answer));
359
return answer;
360
} catch (GeneralSecurityException e) {
361
GSSException ge = new GSSException(GSSException.FAILURE, -1,
362
"Could not use AES256 signing algorithm - " +
363
e.getMessage());
364
ge.initCause(e);
365
throw ge;
366
}
367
368
default:
369
throw new GSSException(GSSException.FAILURE, -1,
370
"Unsupported encryption type: " + etype);
371
}
372
}
373
374
byte[] encryptSeq(byte[] ivec, byte[] plaintext, int start, int len)
375
throws GSSException {
376
377
switch (sgnAlg) {
378
case MessageToken.SGN_ALG_DES_MAC_MD5:
379
case MessageToken.SGN_ALG_DES_MAC:
380
try {
381
Cipher des = getInitializedDes(true, keybytes, ivec);
382
return des.doFinal(plaintext, start, len);
383
384
} catch (GeneralSecurityException e) {
385
GSSException ge = new GSSException(GSSException.FAILURE, -1,
386
"Could not encrypt sequence number using DES - " +
387
e.getMessage());
388
ge.initCause(e);
389
throw ge;
390
}
391
392
case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD:
393
byte[] iv;
394
if (ivec.length == DES_IV_SIZE) {
395
iv = ivec;
396
} else {
397
iv = new byte[DES_IV_SIZE];
398
System.arraycopy(ivec, 0, iv, 0, DES_IV_SIZE);
399
}
400
try {
401
return Des3.encryptRaw(keybytes, KG_USAGE_SEQ, iv,
402
plaintext, start, len);
403
} catch (Exception e) {
404
// GeneralSecurityException, KrbCryptoException
405
GSSException ge = new GSSException(GSSException.FAILURE, -1,
406
"Could not encrypt sequence number using DES3-KD - " +
407
e.getMessage());
408
ge.initCause(e);
409
throw ge;
410
}
411
412
case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR:
413
// ivec passed is the checksum
414
byte[] checksum;
415
if (ivec.length == HMAC_CHECKSUM_SIZE) {
416
checksum = ivec;
417
} else {
418
checksum = new byte[HMAC_CHECKSUM_SIZE];
419
System.arraycopy(ivec, 0, checksum, 0, HMAC_CHECKSUM_SIZE);
420
}
421
422
try {
423
return ArcFourHmac.encryptSeq(keybytes, KG_USAGE_SEQ, checksum,
424
plaintext, start, len);
425
} catch (Exception e) {
426
// GeneralSecurityException, KrbCryptoException
427
GSSException ge = new GSSException(GSSException.FAILURE, -1,
428
"Could not encrypt sequence number using RC4-HMAC - " +
429
e.getMessage());
430
ge.initCause(e);
431
throw ge;
432
}
433
434
default:
435
throw new GSSException(GSSException.FAILURE, -1,
436
"Unsupported signing algorithm: " + sgnAlg);
437
}
438
}
439
440
byte[] decryptSeq(byte[] ivec, byte[] ciphertext, int start, int len)
441
throws GSSException {
442
443
switch (sgnAlg) {
444
case MessageToken.SGN_ALG_DES_MAC_MD5:
445
case MessageToken.SGN_ALG_DES_MAC:
446
try {
447
Cipher des = getInitializedDes(false, keybytes, ivec);
448
return des.doFinal(ciphertext, start, len);
449
} catch (GeneralSecurityException e) {
450
GSSException ge = new GSSException(GSSException.FAILURE, -1,
451
"Could not decrypt sequence number using DES - " +
452
e.getMessage());
453
ge.initCause(e);
454
throw ge;
455
}
456
457
case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD:
458
byte[] iv;
459
if (ivec.length == DES_IV_SIZE) {
460
iv = ivec;
461
} else {
462
iv = new byte[8];
463
System.arraycopy(ivec, 0, iv, 0, DES_IV_SIZE);
464
}
465
466
try {
467
return Des3.decryptRaw(keybytes, KG_USAGE_SEQ, iv,
468
ciphertext, start, len);
469
} catch (Exception e) {
470
// GeneralSecurityException, KrbCryptoException
471
GSSException ge = new GSSException(GSSException.FAILURE, -1,
472
"Could not decrypt sequence number using DES3-KD - " +
473
e.getMessage());
474
ge.initCause(e);
475
throw ge;
476
}
477
478
case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR:
479
// ivec passed is the checksum
480
byte[] checksum;
481
if (ivec.length == HMAC_CHECKSUM_SIZE) {
482
checksum = ivec;
483
} else {
484
checksum = new byte[HMAC_CHECKSUM_SIZE];
485
System.arraycopy(ivec, 0, checksum, 0, HMAC_CHECKSUM_SIZE);
486
}
487
488
try {
489
return ArcFourHmac.decryptSeq(keybytes, KG_USAGE_SEQ, checksum,
490
ciphertext, start, len);
491
} catch (Exception e) {
492
// GeneralSecurityException, KrbCryptoException
493
GSSException ge = new GSSException(GSSException.FAILURE, -1,
494
"Could not decrypt sequence number using RC4-HMAC - " +
495
e.getMessage());
496
ge.initCause(e);
497
throw ge;
498
}
499
500
default:
501
throw new GSSException(GSSException.FAILURE, -1,
502
"Unsupported signing algorithm: " + sgnAlg);
503
}
504
}
505
506
int getChecksumLength() throws GSSException {
507
switch (etype) {
508
case EncryptedData.ETYPE_DES_CBC_CRC:
509
case EncryptedData.ETYPE_DES_CBC_MD5:
510
return DES_CHECKSUM_SIZE;
511
512
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
513
return Des3.getChecksumLength();
514
515
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
516
return Aes128.getChecksumLength();
517
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
518
return Aes256.getChecksumLength();
519
520
case EncryptedData.ETYPE_ARCFOUR_HMAC:
521
// only first 8 octets of HMAC Sgn_Cksum are used
522
return HMAC_CHECKSUM_SIZE;
523
524
default:
525
throw new GSSException(GSSException.FAILURE, -1,
526
"Unsupported encryption type: " + etype);
527
}
528
}
529
530
void decryptData(WrapToken token, byte[] ciphertext, int cStart, int cLen,
531
byte[] plaintext, int pStart) throws GSSException {
532
533
/*
534
Krb5Token.debug("decryptData : ciphertext = " +
535
Krb5Token.getHexBytes(ciphertext));
536
*/
537
538
switch (sealAlg) {
539
case MessageToken.SEAL_ALG_DES:
540
desCbcDecrypt(token, getDesEncryptionKey(keybytes),
541
ciphertext, cStart, cLen, plaintext, pStart);
542
break;
543
544
case MessageToken.SEAL_ALG_DES3_KD:
545
des3KdDecrypt(token, ciphertext, cStart, cLen, plaintext, pStart);
546
break;
547
548
case MessageToken.SEAL_ALG_ARCFOUR_HMAC:
549
arcFourDecrypt(token, ciphertext, cStart, cLen, plaintext, pStart);
550
break;
551
552
default:
553
throw new GSSException(GSSException.FAILURE, -1,
554
"Unsupported seal algorithm: " + sealAlg);
555
}
556
}
557
558
// decrypt data in the new GSS tokens
559
void decryptData(WrapToken_v2 token, byte[] ciphertext, int cStart,
560
int cLen, byte[] plaintext, int pStart, int key_usage)
561
throws GSSException {
562
563
/*
564
Krb5Token.debug("decryptData : ciphertext = " +
565
Krb5Token.getHexBytes(ciphertext));
566
*/
567
568
switch (etype) {
569
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
570
aes128Decrypt(token, ciphertext, cStart, cLen,
571
plaintext, pStart, key_usage);
572
break;
573
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
574
aes256Decrypt(token, ciphertext, cStart, cLen,
575
plaintext, pStart, key_usage);
576
break;
577
default:
578
throw new GSSException(GSSException.FAILURE, -1,
579
"Unsupported etype: " + etype);
580
}
581
}
582
583
void decryptData(WrapToken token, InputStream cipherStream, int cLen,
584
byte[] plaintext, int pStart)
585
throws GSSException, IOException {
586
587
switch (sealAlg) {
588
case MessageToken.SEAL_ALG_DES:
589
desCbcDecrypt(token, getDesEncryptionKey(keybytes),
590
cipherStream, cLen, plaintext, pStart);
591
break;
592
593
case MessageToken.SEAL_ALG_DES3_KD:
594
595
// Read encrypted data from stream
596
byte[] ciphertext = new byte[cLen];
597
try {
598
Krb5Token.readFully(cipherStream, ciphertext, 0, cLen);
599
} catch (IOException e) {
600
GSSException ge = new GSSException(
601
GSSException.DEFECTIVE_TOKEN, -1,
602
"Cannot read complete token");
603
ge.initCause(e);
604
throw ge;
605
}
606
607
des3KdDecrypt(token, ciphertext, 0, cLen, plaintext, pStart);
608
break;
609
610
case MessageToken.SEAL_ALG_ARCFOUR_HMAC:
611
612
// Read encrypted data from stream
613
byte[] ctext = new byte[cLen];
614
try {
615
Krb5Token.readFully(cipherStream, ctext, 0, cLen);
616
} catch (IOException e) {
617
GSSException ge = new GSSException(
618
GSSException.DEFECTIVE_TOKEN, -1,
619
"Cannot read complete token");
620
ge.initCause(e);
621
throw ge;
622
}
623
624
arcFourDecrypt(token, ctext, 0, cLen, plaintext, pStart);
625
break;
626
627
default:
628
throw new GSSException(GSSException.FAILURE, -1,
629
"Unsupported seal algorithm: " + sealAlg);
630
}
631
}
632
633
void decryptData(WrapToken_v2 token, InputStream cipherStream, int cLen,
634
byte[] plaintext, int pStart, int key_usage)
635
throws GSSException, IOException {
636
637
// Read encrypted data from stream
638
byte[] ciphertext = new byte[cLen];
639
try {
640
Krb5Token.readFully(cipherStream, ciphertext, 0, cLen);
641
} catch (IOException e) {
642
GSSException ge = new GSSException(
643
GSSException.DEFECTIVE_TOKEN, -1,
644
"Cannot read complete token");
645
ge.initCause(e);
646
throw ge;
647
}
648
switch (etype) {
649
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
650
aes128Decrypt(token, ciphertext, 0, cLen,
651
plaintext, pStart, key_usage);
652
break;
653
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
654
aes256Decrypt(token, ciphertext, 0, cLen,
655
plaintext, pStart, key_usage);
656
break;
657
default:
658
throw new GSSException(GSSException.FAILURE, -1,
659
"Unsupported etype: " + etype);
660
}
661
}
662
663
void encryptData(WrapToken token, byte[] confounder, byte[] plaintext,
664
int start, int len, byte[] padding, OutputStream os)
665
throws GSSException, IOException {
666
667
switch (sealAlg) {
668
case MessageToken.SEAL_ALG_DES:
669
// Encrypt on the fly and write
670
Cipher des = getInitializedDes(true, getDesEncryptionKey(keybytes),
671
ZERO_IV);
672
CipherOutputStream cos = new CipherOutputStream(os, des);
673
// debug(getHexBytes(confounder, confounder.length));
674
cos.write(confounder);
675
// debug(" " + getHexBytes(plaintext, start, len));
676
cos.write(plaintext, start, len);
677
// debug(" " + getHexBytes(padding, padding.length));
678
cos.write(padding);
679
break;
680
681
case MessageToken.SEAL_ALG_DES3_KD:
682
byte[] ctext = des3KdEncrypt(confounder, plaintext, start, len,
683
padding);
684
685
// Write to stream
686
os.write(ctext);
687
break;
688
689
case MessageToken.SEAL_ALG_ARCFOUR_HMAC:
690
byte[] ciphertext = arcFourEncrypt(token, confounder, plaintext,
691
start, len, padding);
692
693
// Write to stream
694
os.write(ciphertext);
695
break;
696
697
default:
698
throw new GSSException(GSSException.FAILURE, -1,
699
"Unsupported seal algorithm: " + sealAlg);
700
}
701
}
702
703
/*
704
* Encrypt data in the new GSS tokens
705
*
706
* Wrap Tokens (with confidentiality)
707
* { Encrypt(16-byte confounder | plaintext | 16-byte token_header) |
708
* 12-byte HMAC }
709
* where HMAC is on {16-byte confounder | plaintext | 16-byte token_header}
710
* HMAC is not encrypted; it is appended at the end.
711
*/
712
byte[] encryptData(WrapToken_v2 token, byte[] confounder, byte[] tokenHeader,
713
byte[] plaintext, int start, int len, int key_usage)
714
throws GSSException {
715
716
switch (etype) {
717
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
718
return aes128Encrypt(confounder, tokenHeader,
719
plaintext, start, len, key_usage);
720
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
721
return aes256Encrypt(confounder, tokenHeader,
722
plaintext, start, len, key_usage);
723
default:
724
throw new GSSException(GSSException.FAILURE, -1,
725
"Unsupported etype: " + etype);
726
}
727
}
728
729
void encryptData(WrapToken token, byte[] confounder, byte[] plaintext,
730
int pStart, int pLen, byte[] padding, byte[] ciphertext, int cStart)
731
throws GSSException {
732
733
switch (sealAlg) {
734
case MessageToken.SEAL_ALG_DES:
735
int pos = cStart;
736
// Encrypt and write
737
Cipher des = getInitializedDes(true, getDesEncryptionKey(keybytes),
738
ZERO_IV);
739
try {
740
// debug(getHexBytes(confounder, confounder.length));
741
pos += des.update(confounder, 0, confounder.length,
742
ciphertext, pos);
743
// debug(" " + getHexBytes(dataBytes, dataOffset, dataLen));
744
pos += des.update(plaintext, pStart, pLen,
745
ciphertext, pos);
746
// debug(" " + getHexBytes(padding, padding.length));
747
des.update(padding, 0, padding.length,
748
ciphertext, pos);
749
des.doFinal();
750
} catch (GeneralSecurityException e) {
751
GSSException ge = new GSSException(GSSException.FAILURE, -1,
752
"Could not use DES Cipher - " + e.getMessage());
753
ge.initCause(e);
754
throw ge;
755
}
756
break;
757
758
case MessageToken.SEAL_ALG_DES3_KD:
759
byte[] ctext = des3KdEncrypt(confounder, plaintext, pStart, pLen,
760
padding);
761
System.arraycopy(ctext, 0, ciphertext, cStart, ctext.length);
762
break;
763
764
case MessageToken.SEAL_ALG_ARCFOUR_HMAC:
765
byte[] ctext2 = arcFourEncrypt(token, confounder, plaintext, pStart,
766
pLen, padding);
767
System.arraycopy(ctext2, 0, ciphertext, cStart, ctext2.length);
768
break;
769
770
default:
771
throw new GSSException(GSSException.FAILURE, -1,
772
"Unsupported seal algorithm: " + sealAlg);
773
}
774
}
775
776
/*
777
* Encrypt data in the new GSS tokens
778
*
779
* Wrap Tokens (with confidentiality)
780
* { Encrypt(16-byte confounder | plaintext | 16-byte token_header) |
781
* 12-byte HMAC }
782
* where HMAC is on {16-byte confounder | plaintext | 16-byte token_header}
783
* HMAC is not encrypted; it is appended at the end.
784
*/
785
int encryptData(WrapToken_v2 token, byte[] confounder, byte[] tokenHeader,
786
byte[] plaintext, int pStart, int pLen, byte[] ciphertext, int cStart,
787
int key_usage) throws GSSException {
788
789
byte[] ctext = null;
790
switch (etype) {
791
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
792
ctext = aes128Encrypt(confounder, tokenHeader,
793
plaintext, pStart, pLen, key_usage);
794
break;
795
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
796
ctext = aes256Encrypt(confounder, tokenHeader,
797
plaintext, pStart, pLen, key_usage);
798
break;
799
default:
800
throw new GSSException(GSSException.FAILURE, -1,
801
"Unsupported etype: " + etype);
802
}
803
System.arraycopy(ctext, 0, ciphertext, cStart, ctext.length);
804
return ctext.length;
805
}
806
807
// --------------------- DES methods
808
809
/**
810
* Computes the DesCbc checksum based on the algorithm published in FIPS
811
* Publication 113. This involves applying padding to the data passed
812
* in, then performing DesCbc encryption on the data with a zero initial
813
* vector, and finally returning the last 8 bytes of the encryption
814
* result.
815
*
816
* @param key the bytes for the DES key
817
* @param header a header to process first before the data is.
818
* @param data the data to checksum
819
* @param offset the offset where the data begins
820
* @param len the length of the data
821
* @throws GSSException when an error occuse in the encryption
822
*/
823
private byte[] getDesCbcChecksum(byte key[],
824
byte[] header,
825
byte[] data, int offset, int len)
826
throws GSSException {
827
828
Cipher des = getInitializedDes(true, key, ZERO_IV);
829
830
int blockSize = des.getBlockSize();
831
832
/*
833
* Here the data need not be a multiple of the blocksize
834
* (8). Encrypt and throw away results for all blocks except for
835
* the very last block.
836
*/
837
838
byte[] finalBlock = new byte[blockSize];
839
840
int numBlocks = len / blockSize;
841
int lastBytes = len % blockSize;
842
if (lastBytes == 0) {
843
// No need for padding. Save last block from application data
844
numBlocks -= 1;
845
System.arraycopy(data, offset + numBlocks*blockSize,
846
finalBlock, 0, blockSize);
847
} else {
848
System.arraycopy(data, offset + numBlocks*blockSize,
849
finalBlock, 0, lastBytes);
850
// Zero padding automatically done
851
}
852
853
try {
854
byte[] temp = new byte[Math.max(blockSize,
855
(header == null? blockSize : header.length))];
856
857
if (header != null) {
858
// header will be null when doing DES-MD5 Checksum
859
des.update(header, 0, header.length, temp, 0);
860
}
861
862
// Iterate over all but the last block
863
for (int i = 0; i < numBlocks; i++) {
864
des.update(data, offset, blockSize,
865
temp, 0);
866
offset += blockSize;
867
}
868
869
// Now process the final block
870
byte[] retVal = new byte[blockSize];
871
des.update(finalBlock, 0, blockSize, retVal, 0);
872
des.doFinal();
873
874
return retVal;
875
} catch (GeneralSecurityException e) {
876
GSSException ge = new GSSException(GSSException.FAILURE, -1,
877
"Could not use DES Cipher - " + e.getMessage());
878
ge.initCause(e);
879
throw ge;
880
}
881
}
882
883
/**
884
* Obtains an initialized DES cipher.
885
*
886
* @param encryptMode true if encryption is desired, false is decryption
887
* is desired.
888
* @param key the bytes for the DES key
889
* @param ivBytes the initial vector bytes
890
*/
891
private final Cipher getInitializedDes(boolean encryptMode, byte[] key,
892
byte[] ivBytes)
893
throws GSSException {
894
895
896
try {
897
IvParameterSpec iv = new IvParameterSpec(ivBytes);
898
SecretKey jceKey = (SecretKey) (new SecretKeySpec(key, "DES"));
899
900
Cipher desCipher = Cipher.getInstance("DES/CBC/NoPadding");
901
desCipher.init(
902
(encryptMode ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE),
903
jceKey, iv);
904
return desCipher;
905
} catch (GeneralSecurityException e) {
906
GSSException ge = new GSSException(GSSException.FAILURE, -1,
907
e.getMessage());
908
ge.initCause(e);
909
throw ge;
910
}
911
}
912
913
/**
914
* Helper routine to decrypt fromm a byte array and write the
915
* application data straight to an output array with minimal
916
* buffer copies. The confounder and the padding are stored
917
* separately and not copied into this output array.
918
* @param key the DES key to use
919
* @param cipherText the encrypted data
920
* @param offset the offset for the encrypted data
921
* @param len the length of the encrypted data
922
* @param dataOutBuf the output buffer where the application data
923
* should be writte
924
* @param dataOffset the offser where the application data should
925
* be written.
926
* @throws GSSException is an error occurs while decrypting the
927
* data
928
*/
929
private void desCbcDecrypt(WrapToken token, byte[] key, byte[] cipherText,
930
int offset, int len, byte[] dataOutBuf, int dataOffset)
931
throws GSSException {
932
933
try {
934
935
int temp = 0;
936
937
Cipher des = getInitializedDes(false, key, ZERO_IV);
938
939
/*
940
* Remove the counfounder first.
941
* CONFOUNDER_SIZE is one DES block ie 8 bytes.
942
*/
943
temp = des.update(cipherText, offset, WrapToken.CONFOUNDER_SIZE,
944
token.confounder);
945
// temp should be CONFOUNDER_SIZE
946
// debug("\n\ttemp is " + temp + " and CONFOUNDER_SIZE is "
947
// + CONFOUNDER_SIZE);
948
949
offset += WrapToken.CONFOUNDER_SIZE;
950
len -= WrapToken.CONFOUNDER_SIZE;
951
952
/*
953
* len is a multiple of 8 due to padding.
954
* Decrypt all blocks directly into the output buffer except for
955
* the very last block. Remove the trailing padding bytes from the
956
* very last block and copy that into the output buffer.
957
*/
958
959
int blockSize = des.getBlockSize();
960
int numBlocks = len / blockSize - 1;
961
962
// Iterate over all but the last block
963
for (int i = 0; i < numBlocks; i++) {
964
temp = des.update(cipherText, offset, blockSize,
965
dataOutBuf, dataOffset);
966
// temp should be blockSize
967
// debug("\n\ttemp is " + temp + " and blockSize is "
968
// + blockSize);
969
970
offset += blockSize;
971
dataOffset += blockSize;
972
}
973
974
// Now process the last block
975
byte[] finalBlock = new byte[blockSize];
976
des.update(cipherText, offset, blockSize, finalBlock);
977
978
des.doFinal();
979
980
/*
981
* There is always at least one padding byte. The padding bytes
982
* are all the value of the number of padding bytes.
983
*/
984
985
int padSize = finalBlock[blockSize - 1];
986
if (padSize < 1 || padSize > 8)
987
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
988
"Invalid padding on Wrap Token");
989
token.padding = WrapToken.pads[padSize];
990
blockSize -= padSize;
991
992
// Copy this last block into the output buffer
993
System.arraycopy(finalBlock, 0, dataOutBuf, dataOffset,
994
blockSize);
995
996
} catch (GeneralSecurityException e) {
997
GSSException ge = new GSSException(GSSException.FAILURE, -1,
998
"Could not use DES cipher - " + e.getMessage());
999
ge.initCause(e);
1000
throw ge;
1001
}
1002
}
1003
1004
/**
1005
* Helper routine to decrypt from an InputStream and write the
1006
* application data straight to an output array with minimal
1007
* buffer copies. The confounder and the padding are stored
1008
* separately and not copied into this output array.
1009
* @param key the DES key to use
1010
* @param is the InputStream from which the cipher text should be
1011
* read
1012
* @param len the length of the ciphertext data
1013
* @param dataOutBuf the output buffer where the application data
1014
* should be writte
1015
* @param dataOffset the offser where the application data should
1016
* be written.
1017
* @throws GSSException is an error occurs while decrypting the
1018
* data
1019
*/
1020
private void desCbcDecrypt(WrapToken token, byte[] key,
1021
InputStream is, int len, byte[] dataOutBuf, int dataOffset)
1022
throws GSSException, IOException {
1023
1024
int temp = 0;
1025
1026
Cipher des = getInitializedDes(false, key, ZERO_IV);
1027
1028
WrapTokenInputStream truncatedInputStream =
1029
new WrapTokenInputStream(is, len);
1030
CipherInputStream cis = new CipherInputStream(truncatedInputStream,
1031
des);
1032
/*
1033
* Remove the counfounder first.
1034
* CONFOUNDER_SIZE is one DES block ie 8 bytes.
1035
*/
1036
temp = cis.read(token.confounder);
1037
1038
len -= temp;
1039
// temp should be CONFOUNDER_SIZE
1040
// debug("Got " + temp + " bytes; CONFOUNDER_SIZE is "
1041
// + CONFOUNDER_SIZE + "\n");
1042
// debug("Confounder is " + getHexBytes(confounder) + "\n");
1043
1044
1045
/*
1046
* len is a multiple of 8 due to padding.
1047
* Decrypt all blocks directly into the output buffer except for
1048
* the very last block. Remove the trailing padding bytes from the
1049
* very last block and copy that into the output buffer.
1050
*/
1051
1052
int blockSize = des.getBlockSize();
1053
int numBlocks = len / blockSize - 1;
1054
1055
// Iterate over all but the last block
1056
for (int i = 0; i < numBlocks; i++) {
1057
// debug("dataOffset is " + dataOffset + "\n");
1058
temp = cis.read(dataOutBuf, dataOffset, blockSize);
1059
1060
// temp should be blockSize
1061
// debug("Got " + temp + " bytes and blockSize is "
1062
// + blockSize + "\n");
1063
// debug("Bytes are: "
1064
// + getHexBytes(dataOutBuf, dataOffset, temp) + "\n");
1065
dataOffset += blockSize;
1066
}
1067
1068
// Now process the last block
1069
byte[] finalBlock = new byte[blockSize];
1070
// debug("Will call read on finalBlock" + "\n");
1071
temp = cis.read(finalBlock);
1072
// temp should be blockSize
1073
/*
1074
debug("Got " + temp + " bytes and blockSize is "
1075
+ blockSize + "\n");
1076
debug("Bytes are: "
1077
+ getHexBytes(finalBlock, 0, temp) + "\n");
1078
debug("Will call doFinal" + "\n");
1079
*/
1080
try {
1081
des.doFinal();
1082
} catch (GeneralSecurityException e) {
1083
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1084
"Could not use DES cipher - " + e.getMessage());
1085
ge.initCause(e);
1086
throw ge;
1087
}
1088
1089
/*
1090
* There is always at least one padding byte. The padding bytes
1091
* are all the value of the number of padding bytes.
1092
*/
1093
1094
int padSize = finalBlock[blockSize - 1];
1095
if (padSize < 1 || padSize > 8)
1096
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
1097
"Invalid padding on Wrap Token");
1098
token.padding = WrapToken.pads[padSize];
1099
blockSize -= padSize;
1100
1101
// Copy this last block into the output buffer
1102
System.arraycopy(finalBlock, 0, dataOutBuf, dataOffset,
1103
blockSize);
1104
}
1105
1106
private static byte[] getDesEncryptionKey(byte[] key)
1107
throws GSSException {
1108
1109
/*
1110
* To meet export control requirements, double check that the
1111
* key being used is no longer than 64 bits.
1112
*
1113
* Note that from a protocol point of view, an
1114
* algorithm that is not DES will be rejected before this
1115
* point. Also, a DES key that is not 64 bits will be
1116
* rejected by a good JCE provider.
1117
*/
1118
if (key.length > 8)
1119
throw new GSSException(GSSException.FAILURE, -100,
1120
"Invalid DES Key!");
1121
1122
byte[] retVal = new byte[key.length];
1123
for (int i = 0; i < key.length; i++)
1124
retVal[i] = (byte)(key[i] ^ 0xf0); // RFC 1964, Section 1.2.2
1125
return retVal;
1126
}
1127
1128
// ---- DES3-KD methods
1129
private void des3KdDecrypt(WrapToken token, byte[] ciphertext,
1130
int cStart, int cLen, byte[] plaintext, int pStart)
1131
throws GSSException {
1132
byte[] ptext;
1133
try {
1134
ptext = Des3.decryptRaw(keybytes, KG_USAGE_SEAL, ZERO_IV,
1135
ciphertext, cStart, cLen);
1136
} catch (GeneralSecurityException e) {
1137
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1138
"Could not use DES3-KD Cipher - " + e.getMessage());
1139
ge.initCause(e);
1140
throw ge;
1141
}
1142
1143
/*
1144
Krb5Token.debug("\ndes3KdDecrypt in: " +
1145
Krb5Token.getHexBytes(ciphertext, cStart, cLen));
1146
Krb5Token.debug("\ndes3KdDecrypt plain: " +
1147
Krb5Token.getHexBytes(ptext));
1148
*/
1149
1150
// Strip out confounder and padding
1151
/*
1152
* There is always at least one padding byte. The padding bytes
1153
* are all the value of the number of padding bytes.
1154
*/
1155
int padSize = ptext[ptext.length - 1];
1156
if (padSize < 1 || padSize > 8)
1157
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
1158
"Invalid padding on Wrap Token");
1159
1160
token.padding = WrapToken.pads[padSize];
1161
int len = ptext.length - WrapToken.CONFOUNDER_SIZE - padSize;
1162
1163
System.arraycopy(ptext, WrapToken.CONFOUNDER_SIZE,
1164
plaintext, pStart, len);
1165
1166
// Needed to calculate checksum
1167
System.arraycopy(ptext, 0, token.confounder,
1168
0, WrapToken.CONFOUNDER_SIZE);
1169
}
1170
1171
private byte[] des3KdEncrypt(byte[] confounder, byte[] plaintext,
1172
int start, int len, byte[] padding) throws GSSException {
1173
1174
1175
// [confounder | plaintext | padding]
1176
byte[] all = new byte[confounder.length + len + padding.length];
1177
System.arraycopy(confounder, 0, all, 0, confounder.length);
1178
System.arraycopy(plaintext, start, all, confounder.length, len);
1179
System.arraycopy(padding, 0, all, confounder.length + len,
1180
padding.length);
1181
1182
// Krb5Token.debug("\ndes3KdEncrypt:" + Krb5Token.getHexBytes(all));
1183
1184
// Encrypt
1185
try {
1186
byte[] answer = Des3.encryptRaw(keybytes, KG_USAGE_SEAL, ZERO_IV,
1187
all, 0, all.length);
1188
// Krb5Token.debug("\ndes3KdEncrypt encrypted:" +
1189
// Krb5Token.getHexBytes(answer));
1190
return answer;
1191
} catch (Exception e) {
1192
// GeneralSecurityException, KrbCryptoException
1193
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1194
"Could not use DES3-KD Cipher - " + e.getMessage());
1195
ge.initCause(e);
1196
throw ge;
1197
}
1198
}
1199
1200
// ---- RC4-HMAC methods
1201
private void arcFourDecrypt(WrapToken token, byte[] ciphertext,
1202
int cStart, int cLen, byte[] plaintext, int pStart)
1203
throws GSSException {
1204
1205
// obtain Sequence number needed for decryption
1206
// first decrypt the Sequence Number using checksum
1207
byte[] seqNum = decryptSeq(token.getChecksum(),
1208
token.getEncSeqNumber(), 0, 8);
1209
1210
byte[] ptext;
1211
try {
1212
ptext = ArcFourHmac.decryptRaw(keybytes, KG_USAGE_SEAL, ZERO_IV,
1213
ciphertext, cStart, cLen, seqNum);
1214
} catch (GeneralSecurityException e) {
1215
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1216
"Could not use ArcFour Cipher - " + e.getMessage());
1217
ge.initCause(e);
1218
throw ge;
1219
}
1220
1221
/*
1222
Krb5Token.debug("\narcFourDecrypt in: " +
1223
Krb5Token.getHexBytes(ciphertext, cStart, cLen));
1224
Krb5Token.debug("\narcFourDecrypt plain: " +
1225
Krb5Token.getHexBytes(ptext));
1226
*/
1227
1228
// Strip out confounder and padding
1229
/*
1230
* There is always at least one padding byte. The padding bytes
1231
* are all the value of the number of padding bytes.
1232
*/
1233
int padSize = ptext[ptext.length - 1];
1234
if (padSize < 1)
1235
throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
1236
"Invalid padding on Wrap Token");
1237
1238
token.padding = WrapToken.pads[padSize];
1239
int len = ptext.length - WrapToken.CONFOUNDER_SIZE - padSize;
1240
1241
System.arraycopy(ptext, WrapToken.CONFOUNDER_SIZE,
1242
plaintext, pStart, len);
1243
1244
// Krb5Token.debug("\narcFourDecrypt plaintext: " +
1245
// Krb5Token.getHexBytes(plaintext));
1246
1247
// Needed to calculate checksum
1248
System.arraycopy(ptext, 0, token.confounder,
1249
0, WrapToken.CONFOUNDER_SIZE);
1250
}
1251
1252
private byte[] arcFourEncrypt(WrapToken token, byte[] confounder,
1253
byte[] plaintext, int start, int len, byte[] padding)
1254
throws GSSException {
1255
1256
// [confounder | plaintext | padding]
1257
byte[] all = new byte[confounder.length + len + padding.length];
1258
System.arraycopy(confounder, 0, all, 0, confounder.length);
1259
System.arraycopy(plaintext, start, all, confounder.length, len);
1260
System.arraycopy(padding, 0, all, confounder.length + len,
1261
padding.length);
1262
1263
// get the token Sequence Number required for encryption
1264
// Note: When using this RC4 based encryption type, the sequence number
1265
// is always sent in big-endian rather than little-endian order.
1266
byte[] seqNum = new byte[4];
1267
WrapToken.writeBigEndian(token.getSequenceNumber(), seqNum);
1268
1269
// Krb5Token.debug("\narcFourEncrypt:" + Krb5Token.getHexBytes(all));
1270
1271
// Encrypt
1272
try {
1273
byte[] answer = ArcFourHmac.encryptRaw(keybytes, KG_USAGE_SEAL,
1274
seqNum, all, 0, all.length);
1275
// Krb5Token.debug("\narcFourEncrypt encrypted:" +
1276
// Krb5Token.getHexBytes(answer));
1277
return answer;
1278
} catch (Exception e) {
1279
// GeneralSecurityException, KrbCryptoException
1280
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1281
"Could not use ArcFour Cipher - " + e.getMessage());
1282
ge.initCause(e);
1283
throw ge;
1284
}
1285
}
1286
1287
// ---- AES methods
1288
private byte[] aes128Encrypt(byte[] confounder, byte[] tokenHeader,
1289
byte[] plaintext, int start, int len, int key_usage)
1290
throws GSSException {
1291
1292
// encrypt { AES-plaintext-data | filler | header }
1293
// AES-plaintext-data { confounder | plaintext }
1294
// WrapToken = { tokenHeader |
1295
// Encrypt (confounder | plaintext | tokenHeader ) | HMAC }
1296
1297
byte[] all = new byte[confounder.length + len + tokenHeader.length];
1298
System.arraycopy(confounder, 0, all, 0, confounder.length);
1299
System.arraycopy(plaintext, start, all, confounder.length, len);
1300
System.arraycopy(tokenHeader, 0, all, confounder.length+len,
1301
tokenHeader.length);
1302
1303
// Krb5Token.debug("\naes128Encrypt:" + Krb5Token.getHexBytes(all));
1304
try {
1305
byte[] answer = Aes128.encryptRaw(keybytes, key_usage,
1306
ZERO_IV_AES,
1307
all, 0, all.length);
1308
// Krb5Token.debug("\naes128Encrypt encrypted:" +
1309
// Krb5Token.getHexBytes(answer));
1310
return answer;
1311
} catch (Exception e) {
1312
// GeneralSecurityException, KrbCryptoException
1313
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1314
"Could not use AES128 Cipher - " + e.getMessage());
1315
ge.initCause(e);
1316
throw ge;
1317
}
1318
}
1319
1320
private void aes128Decrypt(WrapToken_v2 token, byte[] ciphertext,
1321
int cStart, int cLen, byte[] plaintext, int pStart, int key_usage)
1322
throws GSSException {
1323
1324
byte[] ptext = null;
1325
1326
try {
1327
ptext = Aes128.decryptRaw(keybytes, key_usage,
1328
ZERO_IV_AES, ciphertext, cStart, cLen);
1329
} catch (GeneralSecurityException e) {
1330
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1331
"Could not use AES128 Cipher - " + e.getMessage());
1332
ge.initCause(e);
1333
throw ge;
1334
}
1335
1336
/*
1337
Krb5Token.debug("\naes128Decrypt in: " +
1338
Krb5Token.getHexBytes(ciphertext, cStart, cLen));
1339
Krb5Token.debug("\naes128Decrypt plain: " +
1340
Krb5Token.getHexBytes(ptext));
1341
Krb5Token.debug("\naes128Decrypt ptext: " +
1342
Krb5Token.getHexBytes(ptext));
1343
*/
1344
1345
// Strip out confounder and token header
1346
int len = ptext.length - WrapToken_v2.CONFOUNDER_SIZE -
1347
WrapToken_v2.TOKEN_HEADER_SIZE;
1348
System.arraycopy(ptext, WrapToken_v2.CONFOUNDER_SIZE,
1349
plaintext, pStart, len);
1350
1351
/*
1352
Krb5Token.debug("\naes128Decrypt plaintext: " +
1353
Krb5Token.getHexBytes(plaintext, pStart, len));
1354
*/
1355
}
1356
1357
private byte[] aes256Encrypt(byte[] confounder, byte[] tokenHeader,
1358
byte[] plaintext, int start, int len, int key_usage)
1359
throws GSSException {
1360
1361
// encrypt { AES-plaintext-data | filler | header }
1362
// AES-plaintext-data { confounder | plaintext }
1363
// WrapToken = { tokenHeader |
1364
// Encrypt (confounder | plaintext | tokenHeader ) | HMAC }
1365
1366
byte[] all = new byte[confounder.length + len + tokenHeader.length];
1367
System.arraycopy(confounder, 0, all, 0, confounder.length);
1368
System.arraycopy(plaintext, start, all, confounder.length, len);
1369
System.arraycopy(tokenHeader, 0, all, confounder.length+len,
1370
tokenHeader.length);
1371
1372
// Krb5Token.debug("\naes256Encrypt:" + Krb5Token.getHexBytes(all));
1373
1374
try {
1375
byte[] answer = Aes256.encryptRaw(keybytes, key_usage,
1376
ZERO_IV_AES, all, 0, all.length);
1377
// Krb5Token.debug("\naes256Encrypt encrypted:" +
1378
// Krb5Token.getHexBytes(answer));
1379
return answer;
1380
} catch (Exception e) {
1381
// GeneralSecurityException, KrbCryptoException
1382
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1383
"Could not use AES256 Cipher - " + e.getMessage());
1384
ge.initCause(e);
1385
throw ge;
1386
}
1387
}
1388
1389
private void aes256Decrypt(WrapToken_v2 token, byte[] ciphertext,
1390
int cStart, int cLen, byte[] plaintext, int pStart, int key_usage)
1391
throws GSSException {
1392
1393
byte[] ptext;
1394
try {
1395
ptext = Aes256.decryptRaw(keybytes, key_usage,
1396
ZERO_IV_AES, ciphertext, cStart, cLen);
1397
} catch (GeneralSecurityException e) {
1398
GSSException ge = new GSSException(GSSException.FAILURE, -1,
1399
"Could not use AES128 Cipher - " + e.getMessage());
1400
ge.initCause(e);
1401
throw ge;
1402
}
1403
1404
/*
1405
Krb5Token.debug("\naes256Decrypt in: " +
1406
Krb5Token.getHexBytes(ciphertext, cStart, cLen));
1407
Krb5Token.debug("\naes256Decrypt plain: " +
1408
Krb5Token.getHexBytes(ptext));
1409
Krb5Token.debug("\naes256Decrypt ptext: " +
1410
Krb5Token.getHexBytes(ptext));
1411
*/
1412
1413
// Strip out confounder and token header
1414
int len = ptext.length - WrapToken_v2.CONFOUNDER_SIZE -
1415
WrapToken_v2.TOKEN_HEADER_SIZE;
1416
System.arraycopy(ptext, WrapToken_v2.CONFOUNDER_SIZE,
1417
plaintext, pStart, len);
1418
1419
/*
1420
Krb5Token.debug("\naes128Decrypt plaintext: " +
1421
Krb5Token.getHexBytes(plaintext, pStart, len));
1422
*/
1423
1424
}
1425
1426
/**
1427
* This class provides a truncated inputstream needed by WrapToken. The
1428
* truncated inputstream is passed to CipherInputStream. It prevents
1429
* the CipherInputStream from treating the bytes of the following token
1430
* as part fo the ciphertext for this token.
1431
*/
1432
class WrapTokenInputStream extends InputStream {
1433
1434
private InputStream is;
1435
private int length;
1436
private int remaining;
1437
1438
private int temp;
1439
1440
public WrapTokenInputStream(InputStream is, int length) {
1441
this.is = is;
1442
this.length = length;
1443
remaining = length;
1444
}
1445
1446
public final int read() throws IOException {
1447
if (remaining == 0)
1448
return -1;
1449
else {
1450
temp = is.read();
1451
if (temp != -1)
1452
remaining -= temp;
1453
return temp;
1454
}
1455
}
1456
1457
public final int read(byte[] b) throws IOException {
1458
if (remaining == 0)
1459
return -1;
1460
else {
1461
temp = Math.min(remaining, b.length);
1462
temp = is.read(b, 0, temp);
1463
if (temp != -1)
1464
remaining -= temp;
1465
return temp;
1466
}
1467
}
1468
1469
public final int read(byte[] b,
1470
int off,
1471
int len) throws IOException {
1472
if (remaining == 0)
1473
return -1;
1474
else {
1475
temp = Math.min(remaining, len);
1476
temp = is.read(b, off, temp);
1477
if (temp != -1)
1478
remaining -= temp;
1479
return temp;
1480
}
1481
}
1482
1483
public final long skip(long n) throws IOException {
1484
if (remaining == 0)
1485
return 0;
1486
else {
1487
temp = (int) Math.min(remaining, n);
1488
temp = (int) is.skip(temp);
1489
remaining -= temp;
1490
return temp;
1491
}
1492
}
1493
1494
public final int available() throws IOException {
1495
return Math.min(remaining, is.available());
1496
}
1497
1498
public final void close() throws IOException {
1499
remaining = 0;
1500
}
1501
}
1502
}
1503
1504