--- old/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java 2020-05-20 18:10:44.326445140 -0700 +++ /dev/null 2020-03-09 18:57:19.455001459 -0700 @@ -1,468 +0,0 @@ -/* - * Copyright (c) 2014, 2016, 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 com.oracle.security.ucrypto; - -import java.nio.ByteBuffer; -import java.util.Set; -import java.util.Arrays; -import java.util.Locale; -import java.util.concurrent.ConcurrentSkipListSet; -import java.lang.ref.*; - -import java.security.AlgorithmParameters; -import java.security.GeneralSecurityException; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - - -import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.InvalidParameterSpecException; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.CipherSpi; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.ShortBufferException; - -import javax.crypto.spec.IvParameterSpec; - -/** - * Wrapper class which uses NativeCipher class and Java impls of padding scheme. - * This class currently supports - * - AES/ECB/PKCS5PADDING - * - AES/CBC/PKCS5PADDING - * - AES/CFB128/PKCS5PADDING - * - * @since 9 - */ -public class NativeCipherWithJavaPadding extends CipherSpi { - - private static interface Padding { - // ENC: generate and return the necessary padding bytes - int getPadLen(int dataLen); - - // ENC: generate and return the necessary padding bytes - byte[] getPaddingBytes(int dataLen); - - // DEC: process the decrypted data and buffer up the potential padding - // bytes - byte[] bufferBytes(byte[] intermediateData); - - // DEC: return the length of internally buffered pad bytes - int getBufferedLength(); - - // DEC: unpad and place the output in 'out', starting from outOfs - // and return the number of bytes unpadded into 'out'. - int unpad(byte[] paddedData, byte[] out, int outOfs) - throws BadPaddingException, IllegalBlockSizeException, - ShortBufferException; - - // DEC: Clears the padding object to the initial state - void clear(); - } - - private static class PKCS5Padding implements Padding { - private final int blockSize; - // buffer for storing the potential padding bytes - private ByteBuffer trailingBytes = null; - - PKCS5Padding(int blockSize) - throws NoSuchPaddingException { - if (blockSize == 0) { - throw new NoSuchPaddingException - ("PKCS#5 padding not supported with stream ciphers"); - } - this.blockSize = blockSize; - } - - public int getPadLen(int dataLen) { - return (blockSize - (dataLen & (blockSize - 1))); - } - - public byte[] getPaddingBytes(int dataLen) { - byte padValue = (byte) getPadLen(dataLen); - byte[] paddingBytes = new byte[padValue]; - Arrays.fill(paddingBytes, padValue); - return paddingBytes; - } - - public byte[] bufferBytes(byte[] dataFromUpdate) { - if (dataFromUpdate == null || dataFromUpdate.length == 0) { - return null; - } - byte[] result = null; - if (trailingBytes == null) { - trailingBytes = ByteBuffer.wrap(new byte[blockSize]); - } - int tbSize = trailingBytes.position(); - if (dataFromUpdate.length > trailingBytes.remaining()) { - int totalLen = dataFromUpdate.length + tbSize; - int newTBSize = totalLen % blockSize; - if (newTBSize == 0) { - newTBSize = blockSize; - } - if (tbSize == 0) { - result = Arrays.copyOf(dataFromUpdate, totalLen - newTBSize); - } else { - // combine 'trailingBytes' and 'dataFromUpdate' - result = Arrays.copyOf(trailingBytes.array(), - totalLen - newTBSize); - if (result.length != tbSize) { - System.arraycopy(dataFromUpdate, 0, result, tbSize, - result.length - tbSize); - } - } - // update 'trailingBytes' w/ remaining bytes in 'dataFromUpdate' - trailingBytes.clear(); - trailingBytes.put(dataFromUpdate, - dataFromUpdate.length - newTBSize, newTBSize); - } else { - trailingBytes.put(dataFromUpdate); - } - return result; - } - - public int getBufferedLength() { - if (trailingBytes != null) { - return trailingBytes.position(); - } - return 0; - } - - public int unpad(byte[] lastData, byte[] out, int outOfs) - throws BadPaddingException, IllegalBlockSizeException, - ShortBufferException { - int tbSize = (trailingBytes == null? 0:trailingBytes.position()); - int dataLen = tbSize + lastData.length; - - // Special handling to match SunJCE provider behavior - if (dataLen <= 0) { - return 0; - } else if (dataLen % blockSize != 0) { - UcryptoProvider.debug("PKCS5Padding: unpad, buffered " + tbSize + - " bytes, last block " + lastData.length + " bytes"); - - throw new IllegalBlockSizeException - ("Input length must be multiples of " + blockSize); - } - - // check padding bytes - if (lastData.length == 0) { - if (tbSize != 0) { - // work on 'trailingBytes' directly - lastData = Arrays.copyOf(trailingBytes.array(), tbSize); - trailingBytes.clear(); - tbSize = 0; - } else { - throw new BadPaddingException("No pad bytes found!"); - } - } - byte padValue = lastData[lastData.length - 1]; - if (padValue < 1 || padValue > blockSize) { - UcryptoProvider.debug("PKCS5Padding: unpad, lastData: " + Arrays.toString(lastData)); - UcryptoProvider.debug("PKCS5Padding: unpad, padValue=" + padValue); - throw new BadPaddingException("Invalid pad value: " + padValue); - } - - // sanity check padding bytes - int padStartIndex = lastData.length - padValue; - for (int i = padStartIndex; i < lastData.length; i++) { - if (lastData[i] != padValue) { - UcryptoProvider.debug("PKCS5Padding: unpad, lastData: " + Arrays.toString(lastData)); - UcryptoProvider.debug("PKCS5Padding: unpad, padValue=" + padValue); - throw new BadPaddingException("Invalid padding bytes!"); - } - } - - int actualOutLen = dataLen - padValue; - // check output buffer capacity - if (out.length - outOfs < actualOutLen) { - throw new ShortBufferException("Output buffer too small, need " + actualOutLen + - ", got " + (out.length - outOfs)); - } - try { - if (tbSize != 0) { - trailingBytes.rewind(); - if (tbSize < actualOutLen) { - trailingBytes.get(out, outOfs, tbSize); - outOfs += tbSize; - } else { - // copy from trailingBytes and we are done - trailingBytes.get(out, outOfs, actualOutLen); - return actualOutLen; - } - } - if (lastData.length > padValue) { - System.arraycopy(lastData, 0, out, outOfs, - lastData.length - padValue); - } - return actualOutLen; - } finally { - clear(); - } - } - - public void clear() { - if (trailingBytes != null) trailingBytes.clear(); - } - } - - public static final class AesEcbPKCS5 extends NativeCipherWithJavaPadding { - public AesEcbPKCS5() throws NoSuchAlgorithmException, NoSuchPaddingException { - super(new NativeCipher.AesEcbNoPadding(), "PKCS5Padding"); - } - } - - public static final class AesCbcPKCS5 extends NativeCipherWithJavaPadding { - public AesCbcPKCS5() throws NoSuchAlgorithmException, NoSuchPaddingException { - super(new NativeCipher.AesCbcNoPadding(), "PKCS5Padding"); - } - } - - public static final class AesCfb128PKCS5 extends NativeCipherWithJavaPadding { - public AesCfb128PKCS5() throws NoSuchAlgorithmException, NoSuchPaddingException { - super(new NativeCipher.AesCfb128NoPadding(), "PKCS5Padding"); - } - } - - // fields (re)set in every init() - private final NativeCipher nc; - private final Padding padding; - private final int blockSize; - private int lastBlockLen = 0; - - // Only ECB, CBC, CTR, and CFB128 modes w/ NOPADDING for now - NativeCipherWithJavaPadding(NativeCipher nc, String paddingScheme) - throws NoSuchAlgorithmException, NoSuchPaddingException { - this.nc = nc; - this.blockSize = nc.engineGetBlockSize(); - if (paddingScheme.toUpperCase(Locale.ROOT).equals("PKCS5PADDING")) { - padding = new PKCS5Padding(blockSize); - } else { - throw new NoSuchAlgorithmException("Unsupported padding scheme: " + paddingScheme); - } - } - - void reset() { - padding.clear(); - lastBlockLen = 0; - } - - @Override - protected synchronized void engineSetMode(String mode) throws NoSuchAlgorithmException { - nc.engineSetMode(mode); - } - - // see JCE spec - @Override - protected void engineSetPadding(String padding) - throws NoSuchPaddingException { - // Disallow change of padding for now since currently it's explicitly - // defined in transformation strings - throw new NoSuchPaddingException("Unsupported padding " + padding); - } - - // see JCE spec - @Override - protected int engineGetBlockSize() { - return blockSize; - } - - // see JCE spec - @Override - protected synchronized int engineGetOutputSize(int inputLen) { - int result = nc.engineGetOutputSize(inputLen); - if (nc.encrypt) { - result += padding.getPadLen(result); - } else { - result += padding.getBufferedLength(); - } - return result; - } - - // see JCE spec - @Override - protected synchronized byte[] engineGetIV() { - return nc.engineGetIV(); - } - - // see JCE spec - @Override - protected synchronized AlgorithmParameters engineGetParameters() { - return nc.engineGetParameters(); - } - - @Override - protected int engineGetKeySize(Key key) throws InvalidKeyException { - return nc.engineGetKeySize(key); - } - - // see JCE spec - @Override - protected synchronized void engineInit(int opmode, Key key, SecureRandom random) - throws InvalidKeyException { - reset(); - nc.engineInit(opmode, key, random); - } - - // see JCE spec - @Override - protected synchronized void engineInit(int opmode, Key key, - AlgorithmParameterSpec params, SecureRandom random) - throws InvalidKeyException, InvalidAlgorithmParameterException { - reset(); - nc.engineInit(opmode, key, params, random); - } - - // see JCE spec - @Override - protected synchronized void engineInit(int opmode, Key key, AlgorithmParameters params, - SecureRandom random) - throws InvalidKeyException, InvalidAlgorithmParameterException { - reset(); - nc.engineInit(opmode, key, params, random); - } - - // see JCE spec - @Override - protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) { - if (nc.encrypt) { - lastBlockLen += inLen; - lastBlockLen &= (blockSize - 1); - return nc.engineUpdate(in, inOfs, inLen); - } else { - return padding.bufferBytes(nc.engineUpdate(in, inOfs, inLen)); - } - } - - // see JCE spec - @Override - protected synchronized int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out, - int outOfs) throws ShortBufferException { - if (nc.encrypt) { - lastBlockLen += inLen; - lastBlockLen &= (blockSize - 1); - return nc.engineUpdate(in, inOfs, inLen, out, outOfs); - } else { - byte[] result = padding.bufferBytes(nc.engineUpdate(in, inOfs, inLen)); - if (result != null) { - System.arraycopy(result, 0, out, outOfs, result.length); - return result.length; - } else return 0; - } - } - - // see JCE spec - @Override - protected synchronized byte[] engineDoFinal(byte[] in, int inOfs, int inLen) - throws IllegalBlockSizeException, BadPaddingException { - int estimatedOutLen = engineGetOutputSize(inLen); - byte[] out = new byte[estimatedOutLen]; - try { - int actualOut = this.engineDoFinal(in, inOfs, inLen, out, 0); - // truncate off extra bytes - if (actualOut != out.length) { - out = Arrays.copyOf(out, actualOut); - } - } catch (ShortBufferException sbe) { - throw new UcryptoException("Internal Error", sbe); - } finally { - reset(); - } - return out; - } - - // see JCE spec - @Override - protected synchronized int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out, - int outOfs) - throws ShortBufferException, IllegalBlockSizeException, - BadPaddingException { - int estimatedOutLen = engineGetOutputSize(inLen); - if (out.length - outOfs < estimatedOutLen) { - throw new ShortBufferException("Actual: " + (out.length - outOfs) + - ". Estimated Out Length: " + estimatedOutLen); - } - try { - if (nc.encrypt) { - int k = nc.engineUpdate(in, inOfs, inLen, out, outOfs); - lastBlockLen += inLen; - lastBlockLen &= (blockSize - 1); - byte[] padBytes = padding.getPaddingBytes(lastBlockLen); - k += nc.engineDoFinal(padBytes, 0, padBytes.length, out, (outOfs + k)); - return k; - } else { - byte[] tempOut = nc.engineDoFinal(in, inOfs, inLen); - int len = padding.unpad(tempOut, out, outOfs); - return len; - } - } finally { - reset(); - } - } - - // see JCE spec - @Override - protected synchronized byte[] engineWrap(Key key) throws IllegalBlockSizeException, - InvalidKeyException { - byte[] result = null; - try { - byte[] encodedKey = key.getEncoded(); - if ((encodedKey == null) || (encodedKey.length == 0)) { - throw new InvalidKeyException("Cannot get an encoding of " + - "the key to be wrapped"); - } - result = engineDoFinal(encodedKey, 0, encodedKey.length); - } catch (BadPaddingException e) { - // Should never happen for key wrapping - throw new UcryptoException("Internal Error", e); - } - return result; - } - - // see JCE spec - @Override - protected synchronized Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, - int wrappedKeyType) - throws InvalidKeyException, NoSuchAlgorithmException { - - byte[] encodedKey; - try { - encodedKey = engineDoFinal(wrappedKey, 0, - wrappedKey.length); - } catch (Exception e) { - throw (InvalidKeyException) - (new InvalidKeyException()).initCause(e); - } - - return NativeCipher.constructKey(wrappedKeyType, encodedKey, - wrappedKeyAlgorithm); - } -}