OpenSslCipher.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.crypto.cipher;
- import java.nio.ByteBuffer;
- import java.security.GeneralSecurityException;
- import java.security.InvalidAlgorithmParameterException;
- import java.security.InvalidKeyException;
- import java.security.Key;
- import java.security.spec.AlgorithmParameterSpec;
- import java.util.Objects;
- import java.util.Properties;
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.ShortBufferException;
- /**
- * Implements the CryptoCipher using JNI into OpenSSL.
- * <p>
- * this class is not public/protected so does not appear in the main Javadoc Please ensure that property use is documented in the enum
- * CryptoRandomFactory.RandomProvider
- * </p>
- */
- final class OpenSslCipher implements CryptoCipher {
- private final OpenSsl openSslEngine;
- private boolean initialized;
- private final String transformation;
- /**
- * Constructs a {@link CryptoCipher} using JNI into OpenSSL
- *
- * @param props properties for OpenSSL openSslEngine (unused)
- * @param transformation transformation for OpenSSL openSslEngine (algorithm/mode/padding)
- * @throws GeneralSecurityException if OpenSSL openSslEngine initialize failed
- */
- public OpenSslCipher(final Properties props, final String transformation) // NOPMD
- throws GeneralSecurityException {
- this.transformation = transformation;
- final Throwable loadingFailureReason = OpenSsl.getLoadingFailureReason();
- if (loadingFailureReason != null) {
- throw new IllegalStateException(loadingFailureReason);
- }
- openSslEngine = OpenSsl.getInstance(transformation);
- }
- /**
- * Closes the OpenSSL openSslEngine. Clean the OpenSsl native context.
- */
- @Override
- public void close() {
- openSslEngine.clean();
- }
- /**
- * Encrypts or decrypts data in a single-part operation, or finishes a
- * multiple-part operation.
- *
- * @param input the input byte array
- * @param inputOffset the offset in input where the input starts
- * @param inputLen the input length
- * @param output the byte array for the result
- * @param outputOffset the offset in output where the result is stored
- * @return the number of bytes stored in output
- * @throws ShortBufferException if the given output byte array is too small
- * to hold the result
- * @throws BadPaddingException if this openSslEngine is in decryption mode, and
- * (un)padding has been requested, but the decrypted data is not
- * bounded by the appropriate padding bytes
- * @throws IllegalBlockSizeException if this openSslEngine is a block openSslEngine, no
- * padding has been requested (only in encryption mode), and the
- * total input length of the data processed by this openSslEngine is not a
- * multiple of block size; or if this encryption algorithm is unable
- * to process the input data provided.
- */
- @Override
- public int doFinal(final byte[] input, final int inputOffset, final int inputLen,
- final byte[] output, final int outputOffset) throws ShortBufferException,
- IllegalBlockSizeException, BadPaddingException {
- return openSslEngine.doFinal(input, inputOffset, inputLen, output,outputOffset);
- }
- /**
- * Encrypts or decrypts data in a single-part operation, or finishes a
- * multiple-part operation. The data is encrypted or decrypted, depending on
- * how this openSslEngine was initialized.
- *
- * @param inBuffer the input ByteBuffer
- * @param outBuffer the output ByteBuffer
- * @return int number of bytes stored in {@code output}
- * @throws BadPaddingException if this openSslEngine is in decryption mode, and
- * (un)padding has been requested, but the decrypted data is not
- * bounded by the appropriate padding bytes
- * @throws IllegalBlockSizeException if this openSslEngine is a block openSslEngine, no
- * padding has been requested (only in encryption mode), and the
- * total input length of the data processed by this openSslEngine is not a
- * multiple of block size; or if this encryption algorithm is unable
- * to process the input data provided.
- * @throws ShortBufferException if the given output buffer is too small to
- * hold the result
- */
- @Override
- public int doFinal(final ByteBuffer inBuffer, final ByteBuffer outBuffer)
- throws ShortBufferException, IllegalBlockSizeException,
- BadPaddingException {
- return openSslEngine.doFinal(inBuffer, outBuffer);
- }
- /**
- * Returns the algorithm name of this {@code CryptoCipher} object.
- *
- * <p>
- * This is the same name that was specified in one of the
- * {@code CryptoCipherFactory#getInstance} calls that created this
- * {@code CryptoCipher} object..
- * </p>
- *
- * @return the algorithm name of this {@code CryptoCipher} object.
- */
- @Override
- public String getAlgorithm() {
- return transformation;
- }
- /**
- * Returns the block size (in bytes).
- *
- * @return the block size (in bytes), or 0 if the underlying algorithm is
- * not a block openSslEngine
- */
- @Override
- public int getBlockSize() {
- return CryptoCipherFactory.AES_BLOCK_SIZE;
- }
- /**
- * Initializes the openSslEngine with mode, key and iv.
- *
- * @param mode {@link Cipher#ENCRYPT_MODE} or {@link Cipher#DECRYPT_MODE}
- * @param key crypto key for the openSslEngine
- * @param params the algorithm parameters
- * @throws InvalidKeyException If key length is invalid
- * @throws InvalidAlgorithmParameterException if IV length is wrong
- */
- @Override
- public void init(final int mode, final Key key, final AlgorithmParameterSpec params)
- throws InvalidKeyException, InvalidAlgorithmParameterException {
- Objects.requireNonNull(key, "key");
- Objects.requireNonNull(params, "params");
- final int cipherMode = mode == Cipher.ENCRYPT_MODE ? OpenSsl.ENCRYPT_MODE: OpenSsl.DECRYPT_MODE;
- openSslEngine.init(cipherMode, key.getEncoded(), params);
- initialized = true;
- }
- /**
- * Continues a multiple-part encryption/decryption operation. The data is
- * encrypted or decrypted, depending on how this openSslEngine was initialized.
- *
- * @param input the input byte array
- * @param inputOffset the offset in input where the input starts
- * @param inputLen the input length
- * @param output the byte array for the result
- * @param outputOffset the offset in output where the result is stored
- * @return the number of bytes stored in output
- * @throws ShortBufferException if there is insufficient space in the output
- * byte array
- */
- @Override
- public int update(final byte[] input, final int inputOffset, final int inputLen,
- final byte[] output, final int outputOffset) throws ShortBufferException {
- return openSslEngine
- .update(input, inputOffset, inputLen, output, outputOffset);
- }
- /**
- * Continues a multiple-part encryption/decryption operation. The data is
- * encrypted or decrypted, depending on how this openSslEngine was initialized.
- *
- * @param inBuffer the input ByteBuffer
- * @param outBuffer the output ByteBuffer
- * @return int number of bytes stored in {@code output}
- * @throws ShortBufferException if there is insufficient space in the output
- * buffer
- */
- @Override
- public int update(final ByteBuffer inBuffer, final ByteBuffer outBuffer)
- throws ShortBufferException {
- return openSslEngine.update(inBuffer, outBuffer);
- }
- /**
- * Continues a multi-part update of the Additional Authentication
- * Data (AAD).
- * <p>
- * Calls to this method provide AAD to the opensslEngine when operating in
- * modes such as AEAD (GCM). If this opensslEngine is operating in
- * either GCM mode, all AAD must be supplied before beginning
- * operations on the ciphertext (via the {@code update} and
- * {@code doFinal} methods).
- * </p>
- *
- * @param aad the buffer containing the Additional Authentication Data
- *
- * @throws IllegalArgumentException if the {@code aad}
- * byte array is null
- * @throws IllegalStateException if this opensslEngine is in a wrong state
- * (e.g., has not been initialized), does not accept AAD, or if
- * operating in either GCM mode and one of the {@code update}
- * methods has already been called for the active
- * encryption/decryption operation
- * @throws UnsupportedOperationException if the implementation {@code opensslEngine}
- * doesn't support this operation.
- */
- @Override
- public void updateAAD(final byte[] aad) throws IllegalArgumentException,
- IllegalStateException, UnsupportedOperationException {
- if (aad == null) {
- throw new IllegalArgumentException("aad buffer is null");
- }
- if (!initialized) {
- throw new IllegalStateException("Cipher not initialized");
- }
- if (aad.length == 0) {
- return;
- }
- openSslEngine.updateAAD(aad);
- }
- /**
- * Continues a multi-part update of the Additional Authentication
- * Data (AAD).
- * <p>
- * Calls to this method provide AAD to the opensslEngine when operating in
- * modes such as AEAD (GCM). If this opensslEngine is operating in
- * either GCM mode, all AAD must be supplied before beginning
- * operations on the ciphertext (via the {@code update} and
- * {@code doFinal} methods).
- * </p>
- *
- * @param aad the buffer containing the Additional Authentication Data
- *
- * @throws IllegalArgumentException if the {@code aad}
- * byte array is null
- * @throws IllegalStateException if this opensslEngine is in a wrong state
- * (e.g., has not been initialized), does not accept AAD, or if
- * operating in either GCM mode and one of the {@code update}
- * methods has already been called for the active
- * encryption/decryption operation
- * @throws UnsupportedOperationException if the implementation {@code opensslEngine}
- * doesn't support this operation.
- */
- @Override
- public void updateAAD(final ByteBuffer aad) throws IllegalArgumentException,
- IllegalStateException, UnsupportedOperationException {
- if (aad == null) {
- throw new IllegalArgumentException("aad buffer is null");
- }
- if (!initialized) {
- throw new IllegalStateException("Cipher not initialized");
- }
- final int aadLen = aad.limit() - aad.position();
- if (aadLen == 0) {
- return;
- }
- final byte[] aadBytes = new byte[aadLen];
- aad.get(aadBytes);
- openSslEngine.updateAAD(aadBytes);
- }
- }