/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.security.jgss.krb5;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import org.ietf.jgss.*;
import java.security.MessageDigest;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import sun.security.krb5.*;
import sun.security.krb5.internal.crypto.Des3;
import sun.security.krb5.internal.crypto.Aes128;
import sun.security.krb5.internal.crypto.Aes256;
import sun.security.krb5.internal.crypto.ArcFourHmac;
class CipherHelper {
// From draft-raeburn-cat-gssapi-krb5-3des-00
// Key usage values when deriving keys
private static final int KG_USAGE_SEAL = 22;
private static final int KG_USAGE_SIGN = 23;
private static final int KG_USAGE_SEQ = 24;
private static final int DES_CHECKSUM_SIZE = 8;
private static final int DES_IV_SIZE = 8;
private static final int AES_IV_SIZE = 16;
// ARCFOUR-HMAC
// Save first 8 octets of HMAC Sgn_Cksum
private static final int HMAC_CHECKSUM_SIZE = 8;
// key usage for MIC tokens used by MS
private static final int KG_USAGE_SIGN_MS = 15;
// debug flag
private static final boolean DEBUG = Krb5Util.DEBUG;
/**
* A zero initial vector to be used for checksum calculation and for
* DesCbc application data encryption/decryption.
*/
private static final byte[] ZERO_IV = new byte[DES_IV_SIZE];
private static final byte[] ZERO_IV_AES = new byte[AES_IV_SIZE];
private int etype;
private int sgnAlg, sealAlg;
private byte[] keybytes;
// new token format from draft-ietf-krb-wg-gssapi-cfx-07
// proto is used to determine new GSS token format for "newer" etypes
private int proto = 0;
CipherHelper(EncryptionKey key) throws GSSException {
etype = key.getEType();
keybytes = key.getBytes();
switch (etype) {
case EncryptedData.ETYPE_DES_CBC_CRC:
case EncryptedData.ETYPE_DES_CBC_MD5:
sgnAlg = MessageToken.SGN_ALG_DES_MAC_MD5;
sealAlg = MessageToken.SEAL_ALG_DES;
break;
case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:
sgnAlg = MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD;
sealAlg = MessageToken.SEAL_ALG_DES3_KD;
break;
case EncryptedData.ETYPE_ARCFOUR_HMAC:
sgnAlg = MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR;
sealAlg = MessageToken.SEAL_ALG_ARCFOUR_HMAC;
break;
case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
sgnAlg = -1;
sealAlg = -1;
proto = 1;
break;
default:
throw new GSSException(GSSException.FAILURE, -1,
"Unsupported encryption type: " + etype);
}
}
int getSgnAlg() {
return sgnAlg;
}
int getSealAlg() {
return sealAlg;
}
int getProto() {
return proto;
}
int getEType() {
return etype;
}
boolean isArcFour() {
boolean flag = false;
if (etype == EncryptedData.ETYPE_ARCFOUR_HMAC) {
flag = true;
}
return flag;
}
byte[] calculateChecksum(int alg, byte[] header, byte[] trailer,
byte[] data, int start, int len, int tokenId) throws GSSException {
switch (alg) {
case MessageToken.SGN_ALG_DES_MAC_MD5:
/*
* With this sign algorithm, first an MD5 hash is computed on the
* application data. The 16 byte hash is then DesCbc encrypted.
*/
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
// debug("\t\tdata=[");
// debug(getHexBytes(checksumDataHeader,
// checksumDataHeader.length) + " ");
md5.update(header);
// debug(getHexBytes(data, start, len));
md5.update(data, start, len);
if (trailer != null) {
// debug(" " +
// getHexBytes(trailer,
// optionalTrailer.length));
md5.update(trailer);
}
// debug("]\n");
data = md5.digest();
start = 0;
len = data.length;
// System.out.println("\tMD5 Checksum is [" +
// getHexBytes(data) + "]\n");
header = null;
trailer = null;
} catch (NoSuchAlgorithmException e) {
GSSException ge = new GSSException(GSSException.FAILURE, -1,
"Could not get MD5 Message Digest - " + e.getMessage());
ge.initCause(e);
throw ge;
}
// fall through to encrypt checksum
case MessageToken.SGN_ALG_DES_MAC:
return getDesCbcChecksum(keybytes, header, data, start, len);
case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD:
byte[] buf;
int offset, total;
if (header == null && trailer == null) {
buf = data;
total = len;
offset = start;
} else {
total = ((header != null ? header.length : 0) + len +
(trailer != null ? trailer.length : 0));
buf = new byte[total];
int pos = 0;
if (header != null) {
System.arraycopy(header, 0, buf, 0, header.length);
pos = header.length;
}
System.arraycopy(data, start, buf, pos, len);
pos += len;
if (trailer != null) {
System.arraycopy(trailer, 0, buf, pos, trailer.length);
}
offset = 0;
}
try {
/*
Krb5Token.debug("\nkeybytes: " +
Krb5Token.getHexBytes(keybytes));
Krb5Token.debug("\nheader: " + (header == null ? "NONE" :
Krb5Token.getHexBytes(header)));
Krb5Token.debug("\ntrailer: " + (trailer == null ? "NONE" :
Krb5Token.getHexBytes(trailer)));
Krb5Token.debug("\ndata: " +
Krb5Token.getHexBytes(data, start, len));
Krb5Token.debug("\nbuf: " + Krb5Token.getHexBytes(buf, offset,
评论0