3321N/A * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A // From draft-raeburn-cat-gssapi-krb5-3des-00 0N/A // Key usage values when deriving keys 0N/A // Save first 8 octets of HMAC Sgn_Cksum 0N/A // key usage for MIC tokens used by MS 0N/A * A zero initial vector to be used for checksum calculation and for 0N/A // new token format from draft-ietf-krb-wg-gssapi-cfx-07 0N/A // proto is used to determine new GSS token format for "newer" etypes 0N/A "Unsupported encryption type: " +
etype);
0N/A * With this sign algorithm, first an MD5 hash is computed on the 0N/A * application data. The 16 byte hash is then DesCbc encrypted. 0N/A // debug("\t\tdata=["); 0N/A // debug(getHexBytes(checksumDataHeader, 0N/A // checksumDataHeader.length) + " "); 0N/A // debug(getHexBytes(data, start, len)); 0N/A // getHexBytes(trailer, 0N/A // optionalTrailer.length)); 0N/A // System.out.println("\tMD5 Checksum is [" + 0N/A // getHexBytes(data) + "]\n"); 0N/A // fall through to encrypt checksum 0N/A Krb5Token.debug("\nkeybytes: " + 0N/A Krb5Token.getHexBytes(keybytes)); 0N/A Krb5Token.debug("\nheader: " + (header == null ? "NONE" : 0N/A Krb5Token.getHexBytes(header))); 0N/A Krb5Token.debug("\ntrailer: " + (trailer == null ? "NONE" : 0N/A Krb5Token.getHexBytes(trailer))); 0N/A Krb5Token.debug("\ndata: " + 0N/A Krb5Token.getHexBytes(data, start, len)); 0N/A Krb5Token.debug("\nbuf: " + Krb5Token.getHexBytes(buf, offset, 0N/A // Krb5Token.debug("\nanswer: " + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A "Could not use HMAC-SHA1-DES3-KD signing algorithm - " +
0N/A Krb5Token.debug("\nkeybytes: " + 0N/A Krb5Token.getHexBytes(keybytes)); 0N/A Krb5Token.debug("\nheader: " + (header == null ? "NONE" : 0N/A Krb5Token.getHexBytes(header))); 0N/A Krb5Token.debug("\ntrailer: " + (trailer == null ? "NONE" : 0N/A Krb5Token.getHexBytes(trailer))); 0N/A Krb5Token.debug("\ndata: " + 0N/A Krb5Token.getHexBytes(data, start, len)); 0N/A Krb5Token.debug("\nbuffer: " + 0N/A Krb5Token.getHexBytes(buffer, off, tot)); 0N/A // for MIC tokens, key derivation salt is 15 0N/A // NOTE: Required for interoperability. The RC4-HMAC spec 0N/A // defines key_usage of 23, however all Kerberos impl. 0N/A // Krb5Token.debug("\nanswer: " + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A // Save first 8 octets of HMAC Sgn_Cksum 0N/A // Krb5Token.debug("\nanswer (trimmed): " + 0N/A // Krb5Token.getHexBytes(output)); 0N/A "Could not use HMAC_MD5_ARCFOUR signing algorithm - " +
0N/A // calculate Checksum for the new GSS tokens 0N/A // get_mic("plaintext-data" | "header") 0N/A // Krb5Token.debug("\nAES calculate checksum on: " + 0N/A // Krb5Token.getHexBytes(buf)); 0N/A // Krb5Token.debug("\nAES128 checksum: " + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A "Could not use AES128 signing algorithm - " +
0N/A // Krb5Token.debug("\nAES256 checksum: " + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A "Could not use AES256 signing algorithm - " +
0N/A "Unsupported encryption type: " +
etype);
0N/A "Could not encrypt sequence number using DES - " +
0N/A // GeneralSecurityException, KrbCryptoException 0N/A "Could not encrypt sequence number using DES3-KD - " +
0N/A // ivec passed is the checksum 0N/A // GeneralSecurityException, KrbCryptoException 0N/A "Could not encrypt sequence number using RC4-HMAC - " +
0N/A "Could not decrypt sequence number using DES - " +
0N/A // GeneralSecurityException, KrbCryptoException 0N/A "Could not decrypt sequence number using DES3-KD - " +
0N/A // ivec passed is the checksum 0N/A // GeneralSecurityException, KrbCryptoException 0N/A "Could not decrypt sequence number using RC4-HMAC - " +
0N/A // only first 8 octets of HMAC Sgn_Cksum are used 0N/A "Unsupported encryption type: " +
etype);
0N/A Krb5Token.debug("decryptData : ciphertext = " + 0N/A Krb5Token.getHexBytes(ciphertext)); 0N/A // decrypt data in the new GSS tokens 0N/A Krb5Token.debug("decryptData : ciphertext = " + 0N/A Krb5Token.getHexBytes(ciphertext)); 0N/A // Read encrypted data from stream 0N/A "Cannot read complete token");
0N/A // Read encrypted data from stream 0N/A "Cannot read complete token");
0N/A // Read encrypted data from stream 0N/A "Cannot read complete token");
0N/A // Encrypt on the fly and write 0N/A // debug(getHexBytes(confounder, confounder.length)); 0N/A // debug(" " + getHexBytes(plaintext, start, len)); 0N/A // debug(" " + getHexBytes(padding, padding.length)); 0N/A * Encrypt data in the new GSS tokens 0N/A * Wrap Tokens (with confidentiality) 0N/A * { Encrypt(16-byte confounder | plaintext | 16-byte token_header) | 0N/A * where HMAC is on {16-byte confounder | plaintext | 16-byte token_header} 0N/A * HMAC is not encrypted; it is appended at the end. 0N/A // Encrypt and write 0N/A // debug(getHexBytes(confounder, confounder.length)); 0N/A // debug(" " + getHexBytes(dataBytes, dataOffset, dataLen)); 0N/A // debug(" " + getHexBytes(padding, padding.length)); 0N/A * Encrypt data in the new GSS tokens 0N/A * Wrap Tokens (with confidentiality) 0N/A * { Encrypt(16-byte confounder | plaintext | 16-byte token_header) | 0N/A * where HMAC is on {16-byte confounder | plaintext | 16-byte token_header} 0N/A * HMAC is not encrypted; it is appended at the end. 0N/A // --------------------- DES methods 0N/A * Computes the DesCbc checksum based on the algorithm published in FIPS 0N/A * Publication 113. This involves applying padding to the data passed 0N/A * in, then performing DesCbc encryption on the data with a zero initial 0N/A * vector, and finally returning the last 8 bytes of the encryption 0N/A * @param key the bytes for the DES key 0N/A * @param header a header to process first before the data is. 0N/A * @param data the data to checksum 0N/A * @param offset the offset where the data begins 0N/A * @param len the length of the data 0N/A * @throws GSSException when an error occuse in the encryption 0N/A * Here the data need not be a multiple of the blocksize 0N/A * (8). Encrypt and throw away results for all blocks except for 0N/A * the very last block. 0N/A // No need for padding. Save last block from application data 0N/A // Zero padding automatically done 0N/A // header will be null when doing DES-MD5 Checksum 0N/A // Iterate over all but the last block 0N/A // Now process the final block 0N/A * Obtains an initialized DES cipher. 0N/A * @param encryptMode true if encryption is desired, false is decryption 0N/A * @param key the bytes for the DES key 0N/A * @param ivBytes the initial vector bytes 0N/A * Helper routine to decrypt fromm a byte array and write the 0N/A * application data straight to an output array with minimal 0N/A * buffer copies. The confounder and the padding are stored 0N/A * separately and not copied into this output array. 0N/A * @param key the DES key to use 0N/A * @param cipherText the encrypted data 0N/A * @param offset the offset for the encrypted data 0N/A * @param len the length of the encrypted data 0N/A * @param dataOutBuf the output buffer where the application data 0N/A * @param dataOffset the offser where the application data should 0N/A * @throws GSSException is an error occurs while decrypting the 0N/A * Remove the counfounder first. 0N/A * CONFOUNDER_SIZE is one DES block ie 8 bytes. 0N/A // temp should be CONFOUNDER_SIZE 0N/A // debug("\n\ttemp is " + temp + " and CONFOUNDER_SIZE is " 0N/A // + CONFOUNDER_SIZE); 0N/A * len is a multiple of 8 due to padding. 0N/A * Decrypt all blocks directly into the output buffer except for 0N/A * the very last block. Remove the trailing padding bytes from the 0N/A * very last block and copy that into the output buffer. 0N/A // Iterate over all but the last block 0N/A // temp should be blockSize 0N/A // debug("\n\ttemp is " + temp + " and blockSize is " 0N/A // Now process the last block 0N/A * There is always at least one padding byte. The padding bytes 0N/A * are all the value of the number of padding bytes. 0N/A "Invalid padding on Wrap Token");
0N/A // Copy this last block into the output buffer 0N/A * Helper routine to decrypt from an InputStream and write the 0N/A * application data straight to an output array with minimal 0N/A * buffer copies. The confounder and the padding are stored 0N/A * separately and not copied into this output array. 0N/A * @param key the DES key to use 0N/A * @param is the InputStream from which the cipher text should be 0N/A * @param len the length of the ciphertext data 0N/A * @param dataOutBuf the output buffer where the application data 0N/A * @param dataOffset the offser where the application data should 0N/A * @throws GSSException is an error occurs while decrypting the 0N/A * Remove the counfounder first. 0N/A * CONFOUNDER_SIZE is one DES block ie 8 bytes. 0N/A // temp should be CONFOUNDER_SIZE 0N/A // debug("Got " + temp + " bytes; CONFOUNDER_SIZE is " 0N/A // + CONFOUNDER_SIZE + "\n"); 0N/A // debug("Confounder is " + getHexBytes(confounder) + "\n"); 0N/A * len is a multiple of 8 due to padding. 0N/A * Decrypt all blocks directly into the output buffer except for 0N/A * the very last block. Remove the trailing padding bytes from the 0N/A * very last block and copy that into the output buffer. 0N/A // Iterate over all but the last block 0N/A // debug("dataOffset is " + dataOffset + "\n"); 0N/A // temp should be blockSize 0N/A // debug("Got " + temp + " bytes and blockSize is " 0N/A // + blockSize + "\n"); 0N/A // debug("Bytes are: " 0N/A // + getHexBytes(dataOutBuf, dataOffset, temp) + "\n"); 0N/A // Now process the last block 0N/A // debug("Will call read on finalBlock" + "\n"); 0N/A // temp should be blockSize 0N/A debug("Got " + temp + " bytes and blockSize is " 0N/A + blockSize + "\n"); 0N/A + getHexBytes(finalBlock, 0, temp) + "\n"); 0N/A debug("Will call doFinal" + "\n"); 0N/A * There is always at least one padding byte. The padding bytes 0N/A * are all the value of the number of padding bytes. 0N/A "Invalid padding on Wrap Token");
0N/A // Copy this last block into the output buffer 0N/A * To meet export control requirements, double check that the 0N/A * key being used is no longer than 64 bits. 0N/A * Note that from a protocol point of view, an 0N/A * algorithm that is not DES will be rejected before this 0N/A * point. Also, a DES key that is not 64 bits will be 0N/A * rejected by a good JCE provider. 0N/A "Invalid DES Key!");
0N/A retVal[i] = (
byte)(
key[i] ^
0xf0);
// RFC 1964, Section 1.2.2 0N/A // ---- DES3-KD methods 0N/A Krb5Token.debug("\ndes3KdDecrypt in: " + 0N/A Krb5Token.getHexBytes(ciphertext, cStart, cLen)); 0N/A Krb5Token.debug("\ndes3KdDecrypt plain: " + 0N/A Krb5Token.getHexBytes(ptext)); 0N/A // Strip out confounder and padding 0N/A * There is always at least one padding byte. The padding bytes 0N/A * are all the value of the number of padding bytes. 0N/A "Invalid padding on Wrap Token");
0N/A // Needed to calculate checksum 0N/A // [confounder | plaintext | padding] 0N/A // Krb5Token.debug("\ndes3KdEncrypt:" + Krb5Token.getHexBytes(all)); 0N/A // Krb5Token.debug("\ndes3KdEncrypt encrypted:" + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A // GeneralSecurityException, KrbCryptoException 0N/A // ---- RC4-HMAC methods 0N/A // obtain Sequence number needed for decryption 0N/A // first decrypt the Sequence Number using checksum 0N/A Krb5Token.debug("\narcFourDecrypt in: " + 0N/A Krb5Token.getHexBytes(ciphertext, cStart, cLen)); 0N/A Krb5Token.debug("\narcFourDecrypt plain: " + 0N/A Krb5Token.getHexBytes(ptext)); 0N/A // Strip out confounder and padding 0N/A * There is always at least one padding byte. The padding bytes 0N/A * are all the value of the number of padding bytes. 0N/A "Invalid padding on Wrap Token");
0N/A // Krb5Token.debug("\narcFourDecrypt plaintext: " + 0N/A // Krb5Token.getHexBytes(plaintext)); 0N/A // Needed to calculate checksum 0N/A // [confounder | plaintext | padding] 0N/A // get the token Sequence Number required for encryption 0N/A // Note: When using this RC4 based encryption type, the sequence number 0N/A // is always sent in big-endian rather than little-endian order. 0N/A // Krb5Token.debug("\narcFourEncrypt:" + Krb5Token.getHexBytes(all)); 0N/A // Krb5Token.debug("\narcFourEncrypt encrypted:" + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A // GeneralSecurityException, KrbCryptoException 0N/A // encrypt { AES-plaintext-data | filler | header } 0N/A // AES-plaintext-data { confounder | plaintext } 0N/A // WrapToken = { tokenHeader | 0N/A // Encrypt (confounder | plaintext | tokenHeader ) | HMAC } 0N/A // Krb5Token.debug("\naes128Encrypt:" + Krb5Token.getHexBytes(all)); 0N/A // Krb5Token.debug("\naes128Encrypt encrypted:" + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A // GeneralSecurityException, KrbCryptoException 0N/A Krb5Token.debug("\naes128Decrypt in: " + 0N/A Krb5Token.getHexBytes(ciphertext, cStart, cLen)); 0N/A Krb5Token.debug("\naes128Decrypt plain: " + 0N/A Krb5Token.getHexBytes(ptext)); 0N/A Krb5Token.debug("\naes128Decrypt ptext: " + 0N/A Krb5Token.getHexBytes(ptext)); 0N/A // Strip out confounder and token header 0N/A Krb5Token.debug("\naes128Decrypt plaintext: " + 0N/A Krb5Token.getHexBytes(plaintext, pStart, len)); 0N/A // encrypt { AES-plaintext-data | filler | header } 0N/A // AES-plaintext-data { confounder | plaintext } 0N/A // WrapToken = { tokenHeader | 0N/A // Encrypt (confounder | plaintext | tokenHeader ) | HMAC } 0N/A // Krb5Token.debug("\naes256Encrypt:" + Krb5Token.getHexBytes(all)); 0N/A // Krb5Token.debug("\naes256Encrypt encrypted:" + 0N/A // Krb5Token.getHexBytes(answer)); 0N/A // GeneralSecurityException, KrbCryptoException 0N/A Krb5Token.debug("\naes256Decrypt in: " + 0N/A Krb5Token.getHexBytes(ciphertext, cStart, cLen)); 0N/A Krb5Token.debug("\naes256Decrypt plain: " + 0N/A Krb5Token.getHexBytes(ptext)); 0N/A Krb5Token.debug("\naes256Decrypt ptext: " + 0N/A Krb5Token.getHexBytes(ptext)); 0N/A // Strip out confounder and token header 0N/A Krb5Token.debug("\naes128Decrypt plaintext: " + 0N/A Krb5Token.getHexBytes(plaintext, pStart, len)); 0N/A * This class provides a truncated inputstream needed by WrapToken. The 0N/A * truncated inputstream is passed to CipherInputStream. It prevents 0N/A * the CipherInputStream from treating the bytes of the following token 0N/A * as part fo the ciphertext for this token.