11ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root/* 21ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Copyright (C) 2012 The Android Open Source Project 31ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * 41ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 51ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * you may not use this file except in compliance with the License. 61ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * You may obtain a copy of the License at 71ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * 81ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 91ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * 101ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Unless required by applicable law or agreed to in writing, software 111ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 121ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * See the License for the specific language governing permissions and 141ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * limitations under the License. 151ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 161ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 181ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 193974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Rootimport java.io.IOException; 201ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.AlgorithmParameters; 211ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.InvalidAlgorithmParameterException; 221ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.InvalidKeyException; 231ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.InvalidParameterException; 241ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.Key; 251ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.KeyFactory; 261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.NoSuchAlgorithmException; 271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.SecureRandom; 281ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.spec.AlgorithmParameterSpec; 291ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.spec.InvalidKeySpecException; 301ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.spec.InvalidParameterSpecException; 311ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.spec.PKCS8EncodedKeySpec; 321ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.security.spec.X509EncodedKeySpec; 331ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.util.Arrays; 341ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport java.util.Locale; 351ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.BadPaddingException; 361ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.Cipher; 371ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.CipherSpi; 381ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.IllegalBlockSizeException; 391ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.NoSuchPaddingException; 401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.SecretKey; 411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.ShortBufferException; 421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.spec.IvParameterSpec; 431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootimport javax.crypto.spec.SecretKeySpec; 44c875a50c6c5152f31de58d726c69b93835203511Kenny Rootimport org.conscrypt.util.EmptyArray; 451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 461ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Rootpublic abstract class OpenSSLCipher extends CipherSpi { 471ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 481ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 491ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Modes that a block cipher may support. 501ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected static enum Mode { 521ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root CBC, 531ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root CFB, CFB1, CFB8, CFB128, 541ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root CTR, 551ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root CTS, 561ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root ECB, 571ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root OFB, OFB64, OFB128, 581ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root PCBC, 591ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 601ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 611ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 621ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Paddings that a block cipher may support. 631ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 641ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected static enum Padding { 651ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root NOPADDING, 661ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root PKCS5PADDING, 671ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root ISO10126PADDING, 681ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 691ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 701ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 711ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Native pointer for the OpenSSL EVP_CIPHER context. 721ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 731ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private OpenSSLCipherContext cipherCtx = new OpenSSLCipherContext( 741ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root NativeCrypto.EVP_CIPHER_CTX_new()); 751ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 761ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 771ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * The current cipher mode. 781ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 791ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private Mode mode = Mode.ECB; 801ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 811ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 821ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * The current cipher padding. 831ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 841ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private Padding padding = Padding.PKCS5PADDING; 851ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 861ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 87a749c0d351216be38879600ee8ed01c6793aa256Kenny Root * May be used when reseting the cipher instance after calling 88a749c0d351216be38879600ee8ed01c6793aa256Kenny Root * {@code doFinal}. 89a749c0d351216be38879600ee8ed01c6793aa256Kenny Root */ 90a749c0d351216be38879600ee8ed01c6793aa256Kenny Root private byte[] encodedKey; 91a749c0d351216be38879600ee8ed01c6793aa256Kenny Root 92a749c0d351216be38879600ee8ed01c6793aa256Kenny Root /** 931ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * The Initial Vector (IV) used for the current cipher. 941ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 951ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private byte[] iv; 961ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 971ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 981ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Current cipher mode: encrypting or decrypting. 991ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1001ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private boolean encrypting; 1011ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1021ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1031ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * The block size of the current cipher. 1041ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1051ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private int blockSize; 1061ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1071ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1081ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * The block size of the current mode. 1091ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1101ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private int modeBlockSize; 1111ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 112f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root /** 113f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * Whether the cipher has processed any data yet. OpenSSL doesn't like 114f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * calling "doFinal()" in decryption mode without processing any updates. 115f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root */ 116f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root private boolean calledUpdate; 117f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root 1181ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected OpenSSLCipher() { 1191ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1201ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1211ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected OpenSSLCipher(Mode mode, Padding padding) { 1221ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root this.mode = mode; 1231ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root this.padding = padding; 1241ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root blockSize = getCipherBlockSize(); 1251ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1283974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root * Returns the standard name for the particular algorithm. 1293974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root */ 1303974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root protected abstract String getBaseCipherName(); 1313974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root 1323974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root /** 1331ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Returns the OpenSSL cipher name for the particular {@code keySize} and 1341ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * cipher {@code mode}. 1351ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1361ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected abstract String getCipherName(int keySize, Mode mode); 1371ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1381ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1391ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Checks whether the cipher supports this particular {@code keySize} (in 1401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * bytes) and throws {@code InvalidKeyException} if it doesn't. 1411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected abstract void checkSupportedKeySize(int keySize) throws InvalidKeyException; 1431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1441ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Checks whether the cipher supports this particular cipher {@code mode} 1461ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * and throws {@code NoSuchAlgorithmException} if it doesn't. 1471ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1481ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected abstract void checkSupportedMode(Mode mode) throws NoSuchAlgorithmException; 1491ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1501ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * Checks whether the cipher supports this particular cipher {@code padding} 1521ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * and throws {@code NoSuchPaddingException} if it doesn't. 1531ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 1541ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected abstract void checkSupportedPadding(Padding padding) throws NoSuchPaddingException; 1551ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1561ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected abstract int getCipherBlockSize(); 1571ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 158ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected boolean supportsVariableSizeKey() { 159ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root return false; 160ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 161ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 1621ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 1631ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void engineSetMode(String modeStr) throws NoSuchAlgorithmException { 1641ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final Mode mode; 1651ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 1661ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root mode = Mode.valueOf(modeStr.toUpperCase(Locale.US)); 1671ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (IllegalArgumentException e) { 1681ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root NoSuchAlgorithmException newE = new NoSuchAlgorithmException("No such mode: " 1691ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root + modeStr); 1701ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root newE.initCause(e); 1711ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw newE; 1721ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1731ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root checkSupportedMode(mode); 1741ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root this.mode = mode; 1751ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1761ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1771ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 1781ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void engineSetPadding(String paddingStr) throws NoSuchPaddingException { 1791ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final String paddingStrUpper = paddingStr.toUpperCase(Locale.US); 1801ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final Padding padding; 1811ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 1821ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root padding = Padding.valueOf(paddingStrUpper); 1831ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (IllegalArgumentException e) { 1841ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root NoSuchPaddingException newE = new NoSuchPaddingException("No such padding: " 1851ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root + paddingStr); 1861ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root newE.initCause(e); 1871ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw newE; 1881ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1891ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root checkSupportedPadding(padding); 1901ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root this.padding = padding; 1911ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1921ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1931ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 1941ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected int engineGetBlockSize() { 1951ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return blockSize; 1961ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 1971ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 1981ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /** 1991ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * The size of output if {@code doFinal()} is called with this 2001ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * {@code inputLen}. If padding is enabled and the size of the input puts it 2011ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root * right at the block size, it will add another block for the padding. 2021ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root */ 203f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root private int getOutputSize(int inputLen) { 204987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root if (modeBlockSize == 1) { 205f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root return inputLen; 2061ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 207f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final int buffered = NativeCrypto.get_EVP_CIPHER_CTX_buf_len(cipherCtx.getContext()); 208c6e1f2f39cabbcddca3751faba6960359d8b1ed8Kenny Root if (padding == Padding.NOPADDING) { 209f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root return buffered + inputLen; 210f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root } else { 211f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final int totalLen = inputLen + buffered + modeBlockSize; 212f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root return totalLen - (totalLen % modeBlockSize); 213f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root } 2141ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2151ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2161ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2171ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 2181ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected int engineGetOutputSize(int inputLen) { 219f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root return getOutputSize(inputLen); 2201ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2211ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2221ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 2231ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected byte[] engineGetIV() { 2241ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return iv; 2251ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 2281ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected AlgorithmParameters engineGetParameters() { 2293974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root if (iv != null && iv.length > 0) { 2303974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root try { 2313974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root AlgorithmParameters params = AlgorithmParameters.getInstance(getBaseCipherName()); 2323974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root params.init(iv); 2333974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root return params; 2343974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } catch (NoSuchAlgorithmException e) { 2353974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root return null; 2363974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } catch (IOException e) { 2373974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root return null; 2383974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 2393974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 2401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return null; 2411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2433974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root private void engineInitInternal(int opmode, Key key, byte[] iv, SecureRandom random) 2443974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root throws InvalidKeyException, InvalidAlgorithmParameterException { 2451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE) { 2461ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root encrypting = true; 2471ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else if (opmode == Cipher.DECRYPT_MODE || opmode == Cipher.UNWRAP_MODE) { 2481ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root encrypting = false; 2491ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 2501ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidParameterException("Unsupported opmode " + opmode); 2511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2521ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2531ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (!(key instanceof SecretKey)) { 2541ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidKeyException("Only SecretKey is supported"); 2551ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2561ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2571ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final byte[] encodedKey = key.getEncoded(); 2581ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (encodedKey == null) { 2591ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidKeyException("key.getEncoded() == null"); 2601ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2611ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root checkSupportedKeySize(encodedKey.length); 262a749c0d351216be38879600ee8ed01c6793aa256Kenny Root this.encodedKey = encodedKey; 2631ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 26438c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice final long cipherType = NativeCrypto.EVP_get_cipherbyname(getCipherName(encodedKey.length, 2651ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root mode)); 2661ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (cipherType == 0) { 2671ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidAlgorithmParameterException("Cannot find name for key length = " 2681ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root + (encodedKey.length * 8) + " and mode = " + mode); 2691ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2701ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2711ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int ivLength = NativeCrypto.EVP_CIPHER_iv_length(cipherType); 2723974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root if (iv == null && ivLength != 0) { 2731ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root iv = new byte[ivLength]; 2743974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root if (encrypting) { 2753974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root if (random == null) { 2763974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root random = new SecureRandom(); 2773974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 2783974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root random.nextBytes(iv); 2793974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 2803974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } else if (iv != null && iv.length != ivLength) { 2811ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidAlgorithmParameterException("expected IV length of " + ivLength); 2821ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 2831ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2841ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root this.iv = iv; 2851ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 286ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root if (supportsVariableSizeKey()) { 287ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root NativeCrypto.EVP_CipherInit_ex(cipherCtx.getContext(), cipherType, null, null, 288ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root encrypting); 289ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root NativeCrypto.EVP_CIPHER_CTX_set_key_length(cipherCtx.getContext(), encodedKey.length); 290ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root NativeCrypto.EVP_CipherInit_ex(cipherCtx.getContext(), 0, encodedKey, iv, encrypting); 291ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } else { 292ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root NativeCrypto.EVP_CipherInit_ex(cipherCtx.getContext(), cipherType, encodedKey, iv, 293ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root encrypting); 294ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 2951ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 2961ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root // OpenSSL only supports PKCS5 Padding. 2971ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root NativeCrypto.EVP_CIPHER_CTX_set_padding(cipherCtx.getContext(), 2981ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root padding == Padding.PKCS5PADDING); 2991ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root modeBlockSize = NativeCrypto.EVP_CIPHER_CTX_block_size(cipherCtx.getContext()); 300f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root calledUpdate = false; 3011ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3021ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3031ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 3041ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { 3051ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 3063974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root engineInitInternal(opmode, key, null, random); 3071ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (InvalidAlgorithmParameterException e) { 3081ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new RuntimeException(e); 3091ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3101ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3111ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3121ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 3131ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, 3141ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { 3151ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final byte[] iv; 3161ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (params instanceof IvParameterSpec) { 3171ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root IvParameterSpec ivParams = (IvParameterSpec) params; 3181ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root iv = ivParams.getIV(); 3191ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 3201ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root iv = null; 3211ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3221ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3233974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root engineInitInternal(opmode, key, iv, random); 3241ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3251ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 3271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) 3281ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throws InvalidKeyException, InvalidAlgorithmParameterException { 3291ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final AlgorithmParameterSpec spec; 3300ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root if (params != null) { 3310ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root try { 3320ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root spec = params.getParameterSpec(IvParameterSpec.class); 3330ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root } catch (InvalidParameterSpecException e) { 3340ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root throw new InvalidAlgorithmParameterException(e); 3350ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root } 3360ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root } else { 3370ec06644b9846b4a80d62fd1adf46299cdbd6518Kenny Root spec = null; 3381ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3391ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root engineInit(opmode, key, spec, random); 3411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private final int updateInternal(byte[] input, int inputOffset, int inputLen, byte[] output, 344f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root int outputOffset, int maximumLen) throws ShortBufferException { 3451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int intialOutputOffset = outputOffset; 3461ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 347987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root final int bytesLeft = output.length - outputOffset; 348f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root if (bytesLeft < maximumLen) { 349987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root throw new ShortBufferException("output buffer too small during update: " + bytesLeft 35026bbd7b835f8677fb9a2cb67c07e8b659fe9635cKenny Root + " < " + maximumLen); 3511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3521ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 353987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root outputOffset += NativeCrypto.EVP_CipherUpdate(cipherCtx.getContext(), output, outputOffset, 354987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root input, inputOffset, inputLen); 3551ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 356f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root calledUpdate = true; 357f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root 358987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root return outputOffset - intialOutputOffset; 359987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root } 3601ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3611ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 3621ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { 363f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final int maximumLen = getOutputSize(inputLen); 3641ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3651ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /* See how large our output buffer would need to be. */ 3661ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final byte[] output; 367987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root if (maximumLen > 0) { 368987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root output = new byte[maximumLen]; 3691ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 3701ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root output = EmptyArray.BYTE; 3711ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3721ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 373987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root final int bytesWritten; 3741ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 375f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root bytesWritten = updateInternal(input, inputOffset, inputLen, output, 0, maximumLen); 3761ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (ShortBufferException e) { 3771ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /* This shouldn't happen. */ 378987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root throw new RuntimeException("calculated buffer size was wrong: " + maximumLen); 3791ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3801ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 381987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root if (output.length == bytesWritten) { 382987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root return output; 383987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root } else if (bytesWritten == 0) { 384987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root return EmptyArray.BYTE; 385987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root } else { 386987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root return Arrays.copyOfRange(output, 0, bytesWritten); 387987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root } 3881ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3891ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 3901ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 3911ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, 3921ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root int outputOffset) throws ShortBufferException { 393f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final int maximumLen = getOutputSize(inputLen); 394f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root return updateInternal(input, inputOffset, inputLen, output, outputOffset, maximumLen); 3951ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 3961ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 397f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root /** 398f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * Reset this Cipher instance state to process a new chunk of data. 399f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root */ 400f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root private void reset() { 401a749c0d351216be38879600ee8ed01c6793aa256Kenny Root NativeCrypto.EVP_CipherInit_ex(cipherCtx.getContext(), 0, encodedKey, iv, encrypting); 402f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root calledUpdate = false; 403f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root } 404f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root 4051ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private int doFinalInternal(byte[] input, int inputOffset, int inputLen, byte[] output, 406f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root int outputOffset, int maximumLen) throws IllegalBlockSizeException, 407f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root BadPaddingException, ShortBufferException { 4081ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /* Remember this so we can tell how many characters were written. */ 4091ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int initialOutputOffset = outputOffset; 4101ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 4111ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (inputLen > 0) { 4121ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int updateBytesWritten = updateInternal(input, inputOffset, inputLen, output, 413f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root outputOffset, maximumLen); 4141ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root outputOffset += updateBytesWritten; 415f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root maximumLen -= updateBytesWritten; 4161ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4171ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 418f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root /* 419f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * If we're decrypting and haven't had any input, we should return null. 420f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * Otherwise OpenSSL will complain if we call final. 421f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root */ 422f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root if (!encrypting && !calledUpdate) { 423f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root return 0; 424f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root } 425f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root 4261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /* Allow OpenSSL to pad if necessary and clean up state. */ 4271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int bytesLeft = output.length - outputOffset; 4281ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int writtenBytes; 429f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root if (bytesLeft >= maximumLen) { 4301ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root writtenBytes = NativeCrypto.EVP_CipherFinal_ex(cipherCtx.getContext(), output, 4311ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root outputOffset); 4321ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 433f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final byte[] lastBlock = new byte[maximumLen]; 434987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root writtenBytes = NativeCrypto.EVP_CipherFinal_ex(cipherCtx.getContext(), lastBlock, 0); 4351ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (writtenBytes > bytesLeft) { 4361ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new ShortBufferException("buffer is too short: " + writtenBytes + " > " 4371ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root + bytesLeft); 4381ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else if (writtenBytes > 0) { 439987b13e30fa7fe65c2b84a47f181a29484cc89dcKenny Root System.arraycopy(lastBlock, 0, output, outputOffset, writtenBytes); 4401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root outputOffset += writtenBytes; 4431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 444f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root reset(); 4451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 4461ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return outputOffset - initialOutputOffset; 4471ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4481ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 4491ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 4501ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) 4511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throws IllegalBlockSizeException, BadPaddingException { 452f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root /* 453f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * Other implementations return null if we've never called update() 454f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root * while decrypting. 455f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root */ 456f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root if (!encrypting && !calledUpdate && inputLen == 0) { 457f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root reset(); 458f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root return null; 459f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root } 460f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root 461f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final int maximumLen = getOutputSize(inputLen); 4621ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /* Assume that we'll output exactly on a byte boundary. */ 463c6e1f2f39cabbcddca3751faba6960359d8b1ed8Kenny Root final byte[] output = new byte[maximumLen]; 4641ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root final int bytesWritten; 4651ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 466f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root bytesWritten = doFinalInternal(input, inputOffset, inputLen, output, 0, maximumLen); 4671ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (ShortBufferException e) { 4681ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root /* This should not happen since we sized our own buffer. */ 4691ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new RuntimeException("our calculated buffer was too small", e); 4701ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4711ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 4721ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (bytesWritten == output.length) { 4731ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return output; 474f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root } else if (bytesWritten == 0) { 475f57c83839e949081fb3beabece3db4ec5671cc94Kenny Root return EmptyArray.BYTE; 4761ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 4771ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return Arrays.copyOfRange(output, 0, bytesWritten); 4781ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4791ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4801ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 4811ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 4821ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, 4831ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root int outputOffset) throws ShortBufferException, IllegalBlockSizeException, 4841ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root BadPaddingException { 4851ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (output == null) { 4861ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new NullPointerException("output == null"); 4871ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4881ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 489f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root final int maximumLen = getOutputSize(inputLen); 490f1631ffccd050d5d88da3a26dfe4c2293cf1d762Kenny Root return doFinalInternal(input, inputOffset, inputLen, output, outputOffset, maximumLen); 4911ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 4921ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 4931ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 4941ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { 4951ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 4961ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root byte[] encoded = key.getEncoded(); 4971ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return engineDoFinal(encoded, 0, encoded.length); 4981ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (BadPaddingException e) { 4991ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root IllegalBlockSizeException newE = new IllegalBlockSizeException(); 5001ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root newE.initCause(e); 5011ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw newE; 5021ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5031ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5041ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5051ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 5061ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) 5071ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throws InvalidKeyException, NoSuchAlgorithmException { 5081ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root try { 5091ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root byte[] encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length); 5101ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root if (wrappedKeyType == Cipher.PUBLIC_KEY) { 5111ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm); 5121ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return keyFactory.generatePublic(new X509EncodedKeySpec(encoded)); 5131ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else if (wrappedKeyType == Cipher.PRIVATE_KEY) { 5141ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root KeyFactory keyFactory = KeyFactory.getInstance(wrappedKeyAlgorithm); 5151ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encoded)); 5161ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else if (wrappedKeyType == Cipher.SECRET_KEY) { 5171ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return new SecretKeySpec(encoded, wrappedKeyAlgorithm); 5181ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } else { 5191ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new UnsupportedOperationException("wrappedKeyType == " + wrappedKeyType); 5201ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5211ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (IllegalBlockSizeException e) { 5221ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidKeyException(e); 5231ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (BadPaddingException e) { 5241ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidKeyException(e); 5251ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } catch (InvalidKeySpecException e) { 5261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidKeyException(e); 5271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5281ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5291ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5301ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class AES extends OpenSSLCipher { 5311ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root private static final int AES_BLOCK_SIZE = 16; 5321ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5331ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected AES(Mode mode, Padding padding) { 5341ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(mode, padding); 5351ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5361ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5371ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class CBC extends AES { 5381ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public CBC(Padding padding) { 5391ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(Mode.CBC, padding); 5401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class NoPadding extends CBC { 5431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public NoPadding() { 5441ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(Padding.NOPADDING); 5451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5461ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5471ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5481ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class PKCS5Padding extends CBC { 5491ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public PKCS5Padding() { 5501ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(Padding.PKCS5PADDING); 5511ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5521ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5531ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5541ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5551ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class CFB extends AES { 5560a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root public CFB() { 5570a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root super(Mode.CFB, Padding.NOPADDING); 5581ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5591ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5601ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5611ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class CTR extends AES { 5620a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root public CTR() { 5630a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root super(Mode.CTR, Padding.NOPADDING); 5641ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5651ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5661ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5671ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class ECB extends AES { 5681ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public ECB(Padding padding) { 5691ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(Mode.ECB, padding); 5701ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5711ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5721ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class NoPadding extends ECB { 5731ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public NoPadding() { 5741ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(Padding.NOPADDING); 5751ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5761ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5771ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5781ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class PKCS5Padding extends ECB { 5791ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public PKCS5Padding() { 5801ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root super(Padding.PKCS5PADDING); 5811ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5821ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5831ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5841ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5851ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root public static class OFB extends AES { 5860a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root public OFB() { 5870a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root super(Mode.OFB, Padding.NOPADDING); 5881ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5891ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 5901ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 5911ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 5921ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void checkSupportedKeySize(int keyLength) throws InvalidKeyException { 5931ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root switch (keyLength) { 5941ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case 16: // AES 128 5951ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case 24: // AES 192 5961ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case 32: // AES 256 5971ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return; 5981ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root default: 5991ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new InvalidKeyException("Unsupported key size: " + keyLength + " bytes"); 6001ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6011ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6021ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 6031ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 6041ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void checkSupportedMode(Mode mode) throws NoSuchAlgorithmException { 6051ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root switch (mode) { 6061ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case CBC: 6071ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case CFB: 6081ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case CFB1: 6091ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case CFB8: 6101ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case CFB128: 6111ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case CTR: 6121ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case ECB: 6131ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case OFB: 6141ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return; 6151ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root default: 6161ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new NoSuchAlgorithmException("Unsupported mode " + mode.toString()); 6171ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6181ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6191ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 6201ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 6211ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { 6221ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root switch (padding) { 6231ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case NOPADDING: 6241ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root case PKCS5PADDING: 6251ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return; 6261ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root default: 6271ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root throw new NoSuchPaddingException("Unsupported padding " + padding.toString()); 6281ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6291ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6301ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 6311ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 6323974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root protected String getBaseCipherName() { 6333974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root return "AES"; 6343974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 6353974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root 6363974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root @Override 6371ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected String getCipherName(int keyLength, Mode mode) { 6381ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return "aes-" + (keyLength * 8) + "-" + mode.toString().toLowerCase(Locale.US); 6391ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6401ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root 6411ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root @Override 6421ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root protected int getCipherBlockSize() { 6431ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root return AES_BLOCK_SIZE; 6441ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 6451ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root } 646a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 647a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class DESEDE extends OpenSSLCipher { 648a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root private static int DES_BLOCK_SIZE = 8; 649a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 650a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public DESEDE(Mode mode, Padding padding) { 651a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(mode, padding); 652a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 653a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 654a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class CBC extends DESEDE { 655a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public CBC(Padding padding) { 656a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(Mode.CBC, padding); 657a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 658a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 659a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class NoPadding extends CBC { 660a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public NoPadding() { 661a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(Padding.NOPADDING); 662a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 663a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 664a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 665a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class PKCS5Padding extends CBC { 666a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public PKCS5Padding() { 667a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(Padding.PKCS5PADDING); 668a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 669a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 670a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 671a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 672a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class CFB extends DESEDE { 6730a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root public CFB() { 6740a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root super(Mode.CFB, Padding.NOPADDING); 675a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 676a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 677a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 678a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class ECB extends DESEDE { 679a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public ECB(Padding padding) { 680a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(Mode.ECB, padding); 681a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 682a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 683a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class NoPadding extends ECB { 684a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public NoPadding() { 685a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(Padding.NOPADDING); 686a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 687a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 688a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 689a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class PKCS5Padding extends ECB { 690a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public PKCS5Padding() { 691a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root super(Padding.PKCS5PADDING); 692a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 693a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 694a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 695a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 696a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root public static class OFB extends DESEDE { 6970a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root public OFB() { 6980a47f2ba654ef74f98a4aa263ac091979e88d6f5Kenny Root super(Mode.OFB, Padding.NOPADDING); 699a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 700a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 701a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 702a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root @Override 7033974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root protected String getBaseCipherName() { 7043974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root return "DESede"; 7053974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 7063974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root 7073974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root @Override 708a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root protected String getCipherName(int keySize, Mode mode) { 709f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root final String baseCipherName; 710f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root if (keySize == 16) { 711f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root baseCipherName = "des-ede"; 712f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root } else { 713f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root baseCipherName = "des-ede3"; 714f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root } 715f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root 716a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root if (mode == Mode.ECB) { 717f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root return baseCipherName; 718a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } else { 719f6efe05285dfd12f6ab043cb66e9aec842d90e3aKenny Root return baseCipherName + "-" + mode.toString().toLowerCase(Locale.US); 720a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 721a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 722a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 723a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root @Override 724a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root protected void checkSupportedKeySize(int keySize) throws InvalidKeyException { 725a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root if (keySize != 16 && keySize != 24) { 726a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root throw new InvalidKeyException("key size must be 128 or 192 bits"); 727a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 728a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 729a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 730a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root @Override 731a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root protected void checkSupportedMode(Mode mode) throws NoSuchAlgorithmException { 732a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root switch (mode) { 733a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case CBC: 734a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case CFB: 735a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case CFB1: 736a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case CFB8: 737a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case ECB: 738a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case OFB: 739a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root return; 740a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root default: 741a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root throw new NoSuchAlgorithmException("Unsupported mode " + mode.toString()); 742a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 743a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 744a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 745a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root @Override 746a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root protected void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { 747a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root switch (padding) { 748a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case NOPADDING: 749a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root case PKCS5PADDING: 750a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root return; 751a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root default: 752a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root throw new NoSuchPaddingException("Unsupported padding " + padding.toString()); 753a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 754a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 755a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root 756a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root @Override 757a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root protected int getCipherBlockSize() { 758a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root return DES_BLOCK_SIZE; 759a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 760a31a304e93764c9b9a9e408ccc79c2ca6cad4fe1Kenny Root } 761ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 762ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root public static class ARC4 extends OpenSSLCipher { 763ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root public ARC4() { 764ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 765ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 766ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root @Override 7673974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root protected String getBaseCipherName() { 7683974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root return "ARCFOUR"; 7693974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root } 7703974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root 7713974cacc0af4d6c5e19bf290ea4cdbdc2887fe56Kenny Root @Override 772ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected String getCipherName(int keySize, Mode mode) { 773ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root return "rc4"; 774ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 775ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 776ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root @Override 777ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected void checkSupportedKeySize(int keySize) throws InvalidKeyException { 778ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 779ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 780ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root @Override 781ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected void checkSupportedMode(Mode mode) throws NoSuchAlgorithmException { 782ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root throw new NoSuchAlgorithmException("ARC4 does not support modes"); 783ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 784ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 785ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root @Override 786ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected void checkSupportedPadding(Padding padding) throws NoSuchPaddingException { 787ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root throw new NoSuchPaddingException("ARC4 does not support padding"); 788ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 789ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 790ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root @Override 791ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected int getCipherBlockSize() { 792ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root return 0; 793ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 794ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root 795ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root @Override 796ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root protected boolean supportsVariableSizeKey() { 797ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root return true; 798ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 799ce4ace90d085db0865286fb6819acc82e6c9f64eKenny Root } 8001ddc76d634923479be2b520b2bf20f71ff4f1f44Kenny Root} 801