3321N/A * Copyright (c) 2000, 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 * This class represents a token emitted by the GSSContext.wrap() 0N/A * call. It is a MessageToken except that it also contains plaintext 0N/A * or encrypted data at the end. A wrapToken has certain other rules 0N/A * that are peculiar to it and different from a MICToken, which is 0N/A * another type of MessageToken. All data in a WrapToken is prepended 0N/A * by a random counfounder of 8 bytes. All data in a WrapToken is 0N/A * also padded with one to eight bytes where all bytes are equal in 0N/A * value to the number of bytes being padded. Thus, all application 0N/A * data is replaced by (confounder || data || padding). 0N/A * @author Mayank Upadhyay 0N/A * The size of the random confounder used in a WrapToken. 0N/A * The padding used with a WrapToken. All data is padded to the 0N/A * next multiple of 8 bytes, even if its length is already 0N/A * Use this table as a quick way to obtain padding bytes by 0N/A * indexing it with the number of padding bytes required. 0N/A null,
// No, no one escapes padding 0N/A {
0x04,
0x04,
0x04,
0x04},
0N/A {
0x05,
0x05,
0x05,
0x05,
0x05},
0N/A {
0x06,
0x06,
0x06,
0x06,
0x06,
0x06},
0N/A {
0x07,
0x07,
0x07,
0x07,
0x07,
0x07,
0x07},
0N/A {
0x08,
0x08,
0x08,
0x08,
0x08,
0x08,
0x08,
0x08}
0N/A * A token may come in either in an InputStream or as a 0N/A * byte[]. Store a reference to it in either case and process 0N/A * it's data only later when getData() is called and 0N/A * decrypt both from a byte[] and from an InputStream. 0N/A * Application data may come from an InputStream or from a 0N/A * byte[]. However, it will always be stored and processed as a 0N/A * (a) the MessageDigest class only accepts a byte[] as input and 0N/A * (b) It allows writing to an OuputStream via a CipherOutputStream. 0N/A // the len of the token data: (confounder || data || padding) 0N/A // Accessed by CipherHelper 0N/A * Constructs a WrapToken from token bytes obtained from the 0N/A * @param context the mechanism context associated with this 0N/A * @param tokenBytes the bytes of the token 0N/A * @param tokenOffset the offset of the token 0N/A * @param tokenLen the length of the token 0N/A * @param prop the MessageProp into which characteristics of the 0N/A * parsed token will be stored. 0N/A * @throws GSSException if the token is defective 0N/A // Just parse the MessageToken part first 0N/A // Will need the token bytes again when extracting data 0N/A * Constructs a WrapToken from token bytes read on the fly from 0N/A * @param context the mechanism context associated with this 0N/A * @param is the InputStream containing the token bytes 0N/A * @param prop the MessageProp into which characteristics of the 0N/A * parsed token will be stored. 0N/A * @throws GSSException if the token is defective or if there is 0N/A * a problem reading from the InputStream 0N/A // Just parse the MessageToken part first 0N/A // Will need the token bytes again when extracting data 0N/A debug("WrapToken Cons: gssHeader.getMechTokenLength=" + 0N/A getGSSHeader().getMechTokenLength()); 0N/A debug("\n token size=" 0N/A // debug("\n dataSize=" + dataSize); 0N/A * Obtains the application data that was transmitted in this 0N/A * @return a byte array containing the application data 0N/A * @throws GSSException if an error occurs while decrypting any 0N/A * cipher text and checking for validity 0N/A // Remove the confounder and the padding 0N/A * Obtains the application data that was transmitted in this 0N/A * WrapToken, writing it into an application provided output 0N/A * @param dataBuf the output buffer into which the data must be 0N/A * @param dataBufOffset the offset at which to write the data 0N/A * @return the size of the data written 0N/A * @throws GSSException if an error occurs while decrypting any 0N/A * cipher text and checking for validity 0N/A * Helper routine to obtain the application data transmitted in 0N/A * this WrapToken. It is called if the WrapToken was constructed 0N/A * with a byte array as input. 0N/A * @param dataBuf the output buffer into which the data must be 0N/A * @param dataBufOffset the offset at which to write the data 0N/A * @throws GSSException if an error occurs while decrypting any 0N/A * cipher text and checking for validity 0N/A "Insufficient data in " 0N/A // debug("WrapToken cons: data is token is [" + 0N/A // getHexBytes(tokenBytes, tokenOffset, tokenLen) + "]\n"); 0N/A // Do decryption if this token was privacy protected. 0N/A debug("\t\tDecrypted data is [" + 0N/A getHexBytes(confounder) + " " + 0N/A getHexBytes(dataBuf, dataBufOffset, 0N/A dataSize - CONFOUNDER_SIZE - padding.length) + 0N/A getHexBytes(padding) + 0N/A // Token data is in cleartext 0N/A // debug("\t\tNo encryption was performed by peer.\n"); 0N/A // debug("\t\tPadding applied was: " + padSize + "\n"); 0N/A // byte[] debugbuf = new byte[dataSize - CONFOUNDER_SIZE - padSize]; 0N/A // System.arraycopy(tokenBytes, dataPos + CONFOUNDER_SIZE, 0N/A // debugbuf, 0, debugbuf.length); 0N/A // debug("\t\tData is: " + getHexBytes(debugbuf, debugbuf.length)); 0N/A * Make sure sign and sequence number are not corrupt 0N/A "Corrupt checksum or sequence number in Wrap token");
0N/A * Helper routine to obtain the application data transmitted in 0N/A * this WrapToken. It is called if the WrapToken was constructed 0N/A * with an Inputstream. 0N/A * @param dataBuf the output buffer into which the data must be 0N/A * @param dataBufOffset the offset at which to write the data 0N/A * @throws GSSException if an error occurs while decrypting any 0N/A * cipher text and checking for validity 0N/A // Don't check the token length. Data will be read on demand from 0N/A // debug("WrapToken cons: data will be read from InputStream.\n"); 0N/A // Do decryption if this token was privacy protected. 0N/A // debug("\t\tDecrypted data is [" + 0N/A // getHexBytes(confounder) + " " + 0N/A // getHexBytes(dataBuf, dataBufOffset, 0N/A // dataSize - CONFOUNDER_SIZE - padding.length) + 0N/A // getHexBytes(padding) + 0N/A // Token data is in cleartext 0N/A // debug("\t\tNo encryption was performed by peer.\n"); 3321N/A // Data is always a multiple of 8 with this GSS Mech 3321N/A // Copy all but last block as they are 3321N/A // debug("\t\tPadding applied was: " + padSize + "\n"); 0N/A * Make sure sign and sequence number are not corrupt 0N/A "Corrupt checksum or sequence number in Wrap token");
0N/A * Helper routine to pick the right padding for a certain length 0N/A * of application data. Every application message has some 0N/A * padding between 1 and 8 bytes. 0N/A * @param len the length of the application data 0N/A * @return the padding to be applied 0N/A // For RC4-HMAC, all padding is rounded up to 1 byte. 0N/A // One byte is needed to say that there is 1 byte of padding. 0N/A debug("\nWrapToken cons: data to wrap is [" + 0N/A getHexBytes(confounder) + " " + 0N/A getHexBytes(dataBytes, dataOffset, dataLen) + " " + 0N/A // padding is never null for Wrap 0N/A getHexBytes(padding) + "]\n"); 0N/A * If the application decides to ask for privacy when the context 0N/A * did not negotiate for it, do not provide it. The peer might not 0N/A * have support for it. The app will realize this with a call to 0N/A * pop.getPrivacy() after wrap(). 0N/A // debug("Writing data: ["); 0N/A // debug(getHexBytes(confounder, confounder.length)); 0N/A // debug(" " + getHexBytes(dataBytes, dataOffset, dataLen)); 0N/A // debug(" " + getHexBytes(padding, padding.length)); 0N/A // XXX Fine tune this initial size 0N/A // Token header is small 0N/A // debug("WrapToken.encode: Writing data: ["); 0N/A // debug(getHexBytes(confounder, confounder.length)); 0N/A // debug(" " + getHexBytes(dataBytes, dataOffset, dataLen)); 0N/A // debug(" " + getHexBytes(padding, padding.length)); 0N/A // debug(getHexBytes(outToken, offset, dataSize)); 0N/A // %%% assume that plaintext length == ciphertext len 0N/A // This implementation is way too conservative. And it certainly 0N/A // doesn't return the maximum limit.