/* * 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, total)); */ byte[] answer = Des3.calculateChecksum(keybytes, KG_USAGE_SIGN, buf, offset, total); // Krb5Token.debug("\nanswer: " + // Krb5Token.getHexBytes(answer)); return answer; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use HMAC-SHA1-DES3-KD signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR: byte[] buffer; int off, tot; if (header == null && trailer == null) { buffer = data; tot = len; off = start; } else { tot = ((header != null ? header.length : 0) + len + (trailer != null ? trailer.length : 0)); buffer = new byte[tot]; int pos = 0; if (header != null) { System.arraycopy(header, 0, buffer, 0, header.length); pos = header.length; } System.arraycopy(data, start, buffer, pos, len); pos += len; if (trailer != null) { System.arraycopy(trailer, 0, buffer, pos, trailer.length); } off = 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("\nbuffer: " + Krb5Token.getHexBytes(buffer, off, tot)); */ // for MIC tokens, key derivation salt is 15 // NOTE: Required for interoperability. The RC4-HMAC spec // defines key_usage of 23, however all Kerberos impl. // MS/Solaris/MIT all use key_usage of 15 for MIC tokens int key_usage = KG_USAGE_SIGN; if (tokenId == Krb5Token.MIC_ID) { key_usage = KG_USAGE_SIGN_MS; } byte[] answer = ArcFourHmac.calculateChecksum(keybytes, key_usage, buffer, off, tot); // Krb5Token.debug("\nanswer: " + // Krb5Token.getHexBytes(answer)); // Save first 8 octets of HMAC Sgn_Cksum byte[] output = new byte[getChecksumLength()]; System.arraycopy(answer, 0, output, 0, output.length); // Krb5Token.debug("\nanswer (trimmed): " + // Krb5Token.getHexBytes(output)); return output; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use HMAC_MD5_ARCFOUR signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } default: throw new GSSException(GSSException.FAILURE, -1, "Unsupported signing algorithm: " + sgnAlg); } } // calculate Checksum for the new GSS tokens byte[] calculateChecksum(byte[] header, byte[] data, int start, int len, int key_usage) throws GSSException { // total length int total = ((header != null ? header.length : 0) + len); // get_mic("plaintext-data" | "header") byte[] buf = new byte[total]; // data System.arraycopy(data, start, buf, 0, len); // token header if (header != null) { System.arraycopy(header, 0, buf, len, header.length); } // Krb5Token.debug("\nAES calculate checksum on: " + // Krb5Token.getHexBytes(buf)); switch (etype) { case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96: try { byte[] answer = Aes128.calculateChecksum(keybytes, key_usage, buf, 0, total); // Krb5Token.debug("\nAES128 checksum: " + // Krb5Token.getHexBytes(answer)); return answer; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use AES128 signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96: try { byte[] answer = Aes256.calculateChecksum(keybytes, key_usage, buf, 0, total); // Krb5Token.debug("\nAES256 checksum: " + // Krb5Token.getHexBytes(answer)); return answer; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use AES256 signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } default: throw new GSSException(GSSException.FAILURE, -1, "Unsupported encryption type: " + etype); } } byte[] encryptSeq(byte[] ivec, byte[] plaintext, int start, int len) throws GSSException { switch (sgnAlg) { case MessageToken.SGN_ALG_DES_MAC_MD5: case MessageToken.SGN_ALG_DES_MAC: try { Cipher des = getInitializedDes(true, keybytes, ivec); return des.doFinal(plaintext, start, len); } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not encrypt sequence number using DES - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD: byte[] iv; if (ivec.length == DES_IV_SIZE) { iv = ivec; } else { iv = new byte[DES_IV_SIZE]; System.arraycopy(ivec, 0, iv, 0, DES_IV_SIZE); } try { return Des3.encryptRaw(keybytes, KG_USAGE_SEQ, iv, plaintext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not encrypt sequence number using DES3-KD - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR: // ivec passed is the checksum byte[] checksum; if (ivec.length == HMAC_CHECKSUM_SIZE) { checksum = ivec; } else { checksum = new byte[HMAC_CHECKSUM_SIZE]; System.arraycopy(ivec, 0, checksum, 0, HMAC_CHECKSUM_SIZE); } try { return ArcFourHmac.encryptSeq(keybytes, KG_USAGE_SEQ, checksum, plaintext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not encrypt sequence number using RC4-HMAC - " + e.getMessage()); ge.initCause(e); throw ge; } default: throw new GSSException(GSSException.FAILURE, -1, "Unsupported signing algorithm: " + sgnAlg); } } byte[] decryptSeq(byte[] ivec, byte[] ciphertext, int start, int len) throws GSSException { switch (sgnAlg) { case MessageToken.SGN_ALG_DES_MAC_MD5: case MessageToken.SGN_ALG_DES_MAC: try { Cipher des = getInitializedDes(false, keybytes, ivec); return des.doFinal(ciphertext, start, len); } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not decrypt sequence number using DES - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD: byte[] iv; if (ivec.length == DES_IV_SIZE) { iv = ivec; } else { iv = new byte[8]; System.arraycopy(ivec, 0, iv, 0, DES_IV_SIZE); } try { return Des3.decryptRaw(keybytes, KG_USAGE_SEQ, iv, ciphertext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not decrypt sequence number using DES3-KD - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR: // ivec passed is the checksum byte[] checksum; if (ivec.length == HMAC_CHECKSUM_SIZE) { checksum = ivec; } else { checksum = new byte[HMAC_CHECKSUM_SIZE]; System.arraycopy(ivec, 0, checksum, 0, HMAC_CHECKSUM_SIZE); } try { return ArcFourHmac.decryptSeq(keybytes, KG_USAGE_SEQ, checksum, ciphertext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not decrypt sequence number using RC4-HMAC - " + e.getMessage()); ge.initCause(e); throw ge; } Lines 1–500 of 1503. Load more
/* * 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, total)); */ byte[] answer = Des3.calculateChecksum(keybytes, KG_USAGE_SIGN, buf, offset, total); // Krb5Token.debug("\nanswer: " + // Krb5Token.getHexBytes(answer)); return answer; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use HMAC-SHA1-DES3-KD signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR: byte[] buffer; int off, tot; if (header == null && trailer == null) { buffer = data; tot = len; off = start; } else { tot = ((header != null ? header.length : 0) + len + (trailer != null ? trailer.length : 0)); buffer = new byte[tot]; int pos = 0; if (header != null) { System.arraycopy(header, 0, buffer, 0, header.length); pos = header.length; } System.arraycopy(data, start, buffer, pos, len); pos += len; if (trailer != null) { System.arraycopy(trailer, 0, buffer, pos, trailer.length); } off = 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("\nbuffer: " + Krb5Token.getHexBytes(buffer, off, tot)); */ // for MIC tokens, key derivation salt is 15 // NOTE: Required for interoperability. The RC4-HMAC spec // defines key_usage of 23, however all Kerberos impl. // MS/Solaris/MIT all use key_usage of 15 for MIC tokens int key_usage = KG_USAGE_SIGN; if (tokenId == Krb5Token.MIC_ID) { key_usage = KG_USAGE_SIGN_MS; } byte[] answer = ArcFourHmac.calculateChecksum(keybytes, key_usage, buffer, off, tot); // Krb5Token.debug("\nanswer: " + // Krb5Token.getHexBytes(answer)); // Save first 8 octets of HMAC Sgn_Cksum byte[] output = new byte[getChecksumLength()]; System.arraycopy(answer, 0, output, 0, output.length); // Krb5Token.debug("\nanswer (trimmed): " + // Krb5Token.getHexBytes(output)); return output; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use HMAC_MD5_ARCFOUR signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } default: throw new GSSException(GSSException.FAILURE, -1, "Unsupported signing algorithm: " + sgnAlg); } } // calculate Checksum for the new GSS tokens byte[] calculateChecksum(byte[] header, byte[] data, int start, int len, int key_usage) throws GSSException { // total length int total = ((header != null ? header.length : 0) + len); // get_mic("plaintext-data" | "header") byte[] buf = new byte[total]; // data System.arraycopy(data, start, buf, 0, len); // token header if (header != null) { System.arraycopy(header, 0, buf, len, header.length); } // Krb5Token.debug("\nAES calculate checksum on: " + // Krb5Token.getHexBytes(buf)); switch (etype) { case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96: try { byte[] answer = Aes128.calculateChecksum(keybytes, key_usage, buf, 0, total); // Krb5Token.debug("\nAES128 checksum: " + // Krb5Token.getHexBytes(answer)); return answer; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use AES128 signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96: try { byte[] answer = Aes256.calculateChecksum(keybytes, key_usage, buf, 0, total); // Krb5Token.debug("\nAES256 checksum: " + // Krb5Token.getHexBytes(answer)); return answer; } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not use AES256 signing algorithm - " + e.getMessage()); ge.initCause(e); throw ge; } default: throw new GSSException(GSSException.FAILURE, -1, "Unsupported encryption type: " + etype); } } byte[] encryptSeq(byte[] ivec, byte[] plaintext, int start, int len) throws GSSException { switch (sgnAlg) { case MessageToken.SGN_ALG_DES_MAC_MD5: case MessageToken.SGN_ALG_DES_MAC: try { Cipher des = getInitializedDes(true, keybytes, ivec); return des.doFinal(plaintext, start, len); } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not encrypt sequence number using DES - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD: byte[] iv; if (ivec.length == DES_IV_SIZE) { iv = ivec; } else { iv = new byte[DES_IV_SIZE]; System.arraycopy(ivec, 0, iv, 0, DES_IV_SIZE); } try { return Des3.encryptRaw(keybytes, KG_USAGE_SEQ, iv, plaintext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not encrypt sequence number using DES3-KD - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR: // ivec passed is the checksum byte[] checksum; if (ivec.length == HMAC_CHECKSUM_SIZE) { checksum = ivec; } else { checksum = new byte[HMAC_CHECKSUM_SIZE]; System.arraycopy(ivec, 0, checksum, 0, HMAC_CHECKSUM_SIZE); } try { return ArcFourHmac.encryptSeq(keybytes, KG_USAGE_SEQ, checksum, plaintext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not encrypt sequence number using RC4-HMAC - " + e.getMessage()); ge.initCause(e); throw ge; } default: throw new GSSException(GSSException.FAILURE, -1, "Unsupported signing algorithm: " + sgnAlg); } } byte[] decryptSeq(byte[] ivec, byte[] ciphertext, int start, int len) throws GSSException { switch (sgnAlg) { case MessageToken.SGN_ALG_DES_MAC_MD5: case MessageToken.SGN_ALG_DES_MAC: try { Cipher des = getInitializedDes(false, keybytes, ivec); return des.doFinal(ciphertext, start, len); } catch (GeneralSecurityException e) { GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not decrypt sequence number using DES - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_SHA1_DES3_KD: byte[] iv; if (ivec.length == DES_IV_SIZE) { iv = ivec; } else { iv = new byte[8]; System.arraycopy(ivec, 0, iv, 0, DES_IV_SIZE); } try { return Des3.decryptRaw(keybytes, KG_USAGE_SEQ, iv, ciphertext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not decrypt sequence number using DES3-KD - " + e.getMessage()); ge.initCause(e); throw ge; } case MessageToken.SGN_ALG_HMAC_MD5_ARCFOUR: // ivec passed is the checksum byte[] checksum; if (ivec.length == HMAC_CHECKSUM_SIZE) { checksum = ivec; } else { checksum = new byte[HMAC_CHECKSUM_SIZE]; System.arraycopy(ivec, 0, checksum, 0, HMAC_CHECKSUM_SIZE); } try { return ArcFourHmac.decryptSeq(keybytes, KG_USAGE_SEQ, checksum, ciphertext, start, len); } catch (Exception e) { // GeneralSecurityException, KrbCryptoException GSSException ge = new GSSException(GSSException.FAILURE, -1, "Could not decrypt sequence number using RC4-HMAC - " + e.getMessage()); ge.initCause(e); throw ge; }