javacardx.crypto.Cipher Maven / Gradle / Ivy
Show all versions of jcardsim Show documentation
/*
* Copyright 2011 Licel LLC.
*
* Licensed 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 javacardx.crypto;
import com.licel.jcardsim.crypto.AssymetricCipherImpl;
import com.licel.jcardsim.crypto.SymmetricCipherImpl;
import javacard.security.CryptoException;
import javacard.security.Key;
/**
* The Cipher
class is the abstract base class for Cipher algorithms. Implementations of Cipher
* algorithms must extend this class and implement all the abstract methods.
* The term "pad" is used in the public key cipher algorithms below to refer to all the
* operations specified in the referenced scheme to transform the message block into
* the cipher block size.
*
The asymmetric key algorithms encrypt using either a public key (to cipher) or a private key (to sign).
* In addition they decrypt using the either a private key (to decipher) or a public key (to verify).
*
A tear or card reset event resets an initialized
* Cipher
object to the state it was in when previously initialized
* via a call to init()
. For algorithms which support keys with transient
* key data sets, such as DES, triple DES and AES,
* the Cipher
object key becomes
* uninitialized on clear events associated with the Key
* object used to initialize the Cipher
object.
*
Even if a transaction is in progress, update of intermediate result state in the implementation
* instance shall not participate in the transaction.
*
Note:
*
* - On a tear or card reset event, the AES, DES, and triple DES algorithms in CBC mode
* reset the initial vector(IV) to 0. The initial vector(IV) can be re-initialized using the
*
init(Key, byte, byte[], short, short)
method.
*
*/
public abstract class Cipher {
/**
* Cipher algorithm ALG_DES_CBC_NOPAD
provides a cipher using DES in CBC mode
* or triple DES in outer CBC mode, and
* does not pad input data. If the input data is not (8-byte) block
* aligned it throws CryptoException
with the reason code ILLEGAL_USE
.
*/
public static final byte ALG_DES_CBC_NOPAD = 1;
/**
* Cipher algorithm ALG_DES_CBC_ISO9797_M1
provides a cipher using DES
* in CBC mode or triple DES in outer CBC mode, and pads
* input data according to the ISO 9797 method 1 scheme.
*/
public static final byte ALG_DES_CBC_ISO9797_M1 = 2;
/**
* Cipher algorithm ALG_DES_CBC_ISO9797_M2
provides a cipher using DES
* in CBC mode or triple DES in outer CBC mode, and pads
* input data according to the ISO 9797 method 2 (ISO 7816-4, EMV'96) scheme.
*/
public static final byte ALG_DES_CBC_ISO9797_M2 = 3;
/**
* Cipher algorithm ALG_DES_CBC_PKCS5
provides a cipher using DES
* in CBC mode or triple DES in outer CBC mode, and pads
* input data according to the PKCS#5 scheme.
*/
public static final byte ALG_DES_CBC_PKCS5 = 4;
/**
* Cipher algorithm ALG_DES_ECB_NOPAD
provides a cipher using DES in ECB mode,
* and does not pad input data. If the input data is not (8-byte) block
* aligned it throws CryptoException
with the reason code ILLEGAL_USE
.
*/
public static final byte ALG_DES_ECB_NOPAD = 5;
/**
* Cipher algorithm ALG_DES_ECB_ISO9797_M1
provides a cipher using DES
* in ECB mode, and pads
* input data according to the ISO 9797 method 1 scheme.
*/
public static final byte ALG_DES_ECB_ISO9797_M1 = 6;
/**
* Cipher algorithm ALG_DES_ECB_ISO9797_M2
provides a cipher using DES
* in ECB mode, and pads
* input data according to the ISO 9797 method 2 (ISO 7816-4, EMV'96) scheme.
*/
public static final byte ALG_DES_ECB_ISO9797_M2 = 7;
/**
* Cipher algorithm ALG_DES_ECB_PKCS5
provides a cipher using DES
* in ECB mode, and pads
* input data according to the PKCS#5 scheme.
*/
public static final byte ALG_DES_ECB_PKCS5 = 8;
/**
* Cipher algorithm ALG_RSA_ISO14888
provides a cipher using RSA, and pads
* input data according to the ISO 14888 scheme.
*/
public static final byte ALG_RSA_ISO14888 = 9;
/**
* Cipher algorithm ALG_RSA_PKCS1
provides a cipher using RSA, and pads
* input data according to the PKCS#1 (v1.5) scheme.
* Note:
*
* - This algorithm is only suitable for messages of limited length.
* The total number of input bytes processed may not be more than k-11,
* where k is the RSA key's modulus size in bytes.
*
- The encryption block(EB) during encryption with a Public key
* is built as follows:
* EB = 00 || 02 || PS || 00 || M
* :: M (input bytes) is the plaintext message
* :: PS is an octet string of length k-3-||M|| of pseudo
* random nonzero octets. The length of PS must be at least 8 octets.
* :: k is the RSA modulus size.
* - The encryption block(EB) during encryption with a Private key
* (used to compute signatures when the message digest is computed off-card)
* is built as follows:
* EB = 00 || 01 || PS || 00 || D
* :: D (input bytes) is the DER encoding of the
* hash computed elsewhere with an algorithm ID
* prepended if appropriate
* :: PS is an octet string of length k-3-||D|| with value
* FF. The length of PS must be at least 8 octets.
* :: k is the RSA modulus size.
*
*/
public static final byte ALG_RSA_PKCS1 = 10;
/**
* This Cipher algorithm ALG_RSA_ISO9796
should not be used. The
* ISO 9796-1 algorithm was withdrawn by ISO in July 2000.
*/
public static final byte ALG_RSA_ISO9796 = 11;
/**
* Cipher algorithm ALG_RSA_NOPAD
provides a cipher using RSA and
* does not pad input data. If the input data is bounded by incorrect
* padding bytes while using RSAPrivateCrtKey, incorrect output may result.
* If the input data is not block aligned it throws CryptoException
with
* the reason code ILLEGAL_USE
.
*/
public static final byte ALG_RSA_NOPAD = 12;
/**
* Cipher algorithm ALG_AES_BLOCK_128_CBC_NOPAD
provides a cipher using AES with
* block size 128 in CBC mode and
* does not pad input data. If the input data is not block
* aligned it throws CryptoException
with the reason code ILLEGAL_USE
.
*/
public static final byte ALG_AES_BLOCK_128_CBC_NOPAD = 13;
/**
* Cipher algorithm ALG_AES_BLOCK_128_ECB_NOPAD
provides a cipher using AES with
* block size 128 in ECB mode and
* does not pad input data. If the input data is not block
* aligned it throws CryptoException
with the reason code ILLEGAL_USE
.
*/
public static final byte ALG_AES_BLOCK_128_ECB_NOPAD = 14;
/**
* Cipher algorithm ALG_RSA_PKCS1_OAEP
provides a cipher using RSA, and
* pads input data according to the PKCS#1-OAEP scheme (IEEE 1363-2000).
*/
public static final byte ALG_RSA_PKCS1_OAEP = 15;
/**
* Cipher algorithm ALG_KOREAN_SEED_ECB_NOPAD provides a cipher using the
* Korean SEED algorithm specified in the Korean SEED Algorithm
* specification provided by KISA, Korea Information Security Agency in ECB
* mode and does not pad input data. If the input data is not block aligned
* it throws CryptoException with the reason code ILLEGAL_USE.
*
* @since 2.2.2
*/
public static final byte ALG_KOREAN_SEED_ECB_NOPAD = 16;
/**
* Cipher algorithm ALG_KOREAN_SEED_CBC_NOPAD provides a cipher using the
* Korean SEED algorithm specified in the Korean SEED Algorithm
* specification provided by KISA, Korea Information Security Agency in ECB
* mode and does not pad input data. If the input data is not block aligned
* it throws CryptoException with the reason code ILLEGAL_USE.
*
*
* @since 2.2.2
*/
public static final byte ALG_KOREAN_SEED_CBC_NOPAD = 17;
/**
* Used in init()
methods to indicate decryption mode.
*/
public static final byte MODE_DECRYPT = 1;
/**
* Used in init()
methods to indicate encryption mode.
*/
public static final byte MODE_ENCRYPT = 2;
/**
* Protected constructor.
*/
protected Cipher() {
}
/**
* Creates a Cipher
object instance of the selected algorithm.
* @param algorithm the desired Cipher algorithm. Valid codes listed in
* ALG_ .. constants above, for example, {@link #ALG_DES_CBC_NOPAD}
* @param externalAccess indicates that the instance will be shared among
* multiple applet instances and that the Cipher
instance will also be accessed (via a Shareable
* interface) when the owner of the Cipher
instance is not the currently selected applet.
* If true
the implementation must not allocate CLEAR_ON_DESELECT transient space for internal data.
* @return the Cipher
object instance of the requested algorithm
* @throws CryptoException with the following reason codes:
*
* CryptoException.NO_SUCH_ALGORITHM
if the requested algorithm is not supported
* or shared access mode is not supported.
*
*/
public static final Cipher getInstance(byte algorithm, boolean externalAccess)
throws CryptoException {
Cipher instance = null;
if (externalAccess) {
CryptoException.throwIt((short) 3);
}
switch (algorithm) {
case ALG_DES_CBC_NOPAD:
case ALG_DES_CBC_ISO9797_M1:
case ALG_DES_CBC_ISO9797_M2:
case ALG_DES_CBC_PKCS5:
case ALG_DES_ECB_NOPAD:
case ALG_DES_ECB_ISO9797_M1:
case ALG_DES_ECB_ISO9797_M2:
case ALG_DES_ECB_PKCS5:
case ALG_AES_BLOCK_128_CBC_NOPAD:
case ALG_AES_BLOCK_128_ECB_NOPAD:
instance = new SymmetricCipherImpl(algorithm);
break;
case ALG_RSA_PKCS1:
case ALG_RSA_NOPAD:
case ALG_RSA_ISO14888:
case ALG_RSA_ISO9796:
case ALG_RSA_PKCS1_OAEP:
instance = new AssymetricCipherImpl(algorithm);
break;
default:
CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
break;
}
return instance;
}
/**
* Initializes the Cipher
object with the appropriate Key
.
* This method should be used
* for algorithms which do not need initialization parameters or use default parameter
* values.
* init()
must be used to update the Cipher
object with a new key.
* If the Key
object is modified after invoking the init()
method,
* the behavior of the update()
and doFinal()
* methods is unspecified.
*
Note:
*
* - AES, DES, and triple DES algorithms in CBC mode will use 0 for initial vector(IV) if this
* method is used.
*
- For optimal performance, when the theKey parameter is a transient key, the implementation should,
* whenever possible, use transient space for internal storage.
*
* @param theKey the key object to use for encrypting or decrypting
* @param theMode one of MODE_DECRYPT
or MODE_ENCRYPT
* @throws CryptoException with the following reason codes:
*
* CryptoException.ILLEGAL_VALUE
if theMode
option is an undefined value or
* if the Key
is inconsistent with the Cipher
implementation.
* CryptoException.UNINITIALIZED_KEY
if theKey
instance is uninitialized.
*
*/
public abstract void init(Key theKey, byte theMode)
throws CryptoException;
/**
* Initializes the Cipher
object with the appropriate Key and algorithm specific
* parameters.
* init()
must be used to update the Cipher
object with a new key.
* If the Key
object is modified after invoking the init()
method,
* the behavior of the update()
and doFinal()
* methods is unspecified.
*
Note:
*
* - DES and triple DES algorithms in CBC mode expect an 8-byte parameter value for
* the initial vector(IV) in
bArray
.
* - AES algorithms in CBC mode expect a 16-byte parameter value for
* the initial vector(IV) in
bArray
.
* - AES algorithms in ECB mode, DES algorithms in ECB mode,
* RSA and DSA algorithms throw
CryptoException.ILLEGAL_VALUE
.
* - For optimal performance, when the theKey parameter is a transient key, the implementation should,
* whenever possible, use transient space for internal storage.
*
* @param theKey the key object to use for encrypting or decrypting.
* @param theMode one of MODE_DECRYPT
or MODE_ENCRYPT
* @param bArray byte array containing algorithm specific initialization info
* @param bOff offset within bArray where the algorithm specific data begins
* @param bLen byte length of algorithm specific parameter data
* @throws CryptoException with the following reason codes:
*
* CryptoException.ILLEGAL_VALUE
if theMode
option is an undefined value
* or if a byte array parameter option is not supported by the algorithm or if
* the bLen
is an incorrect byte length for the algorithm specific data or
* if the Key
is inconsistent with the Cipher
implementation.
* CryptoException.UNINITIALIZED_KEY
if theKey
instance is uninitialized.
*
*/
public abstract void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen)
throws CryptoException;
/**
* Gets the Cipher algorithm.
* @return the algorithm code defined above
*/
public abstract byte getAlgorithm();
/**
* Generates encrypted/decrypted output from all/last input data. This method must be invoked
* to complete a cipher operation. This method processes any remaining input data buffered by
* one or more calls to the update()
method as well as input data supplied in the
* inBuff
parameter.
* A call to this method also resets this Cipher
object to the state it was in
* when previously initialized via a call to init()
.
* That is, the object is reset and available to encrypt or decrypt
* (depending on the operation mode that was specified in the call to init()
) more data.
* In addition, note that the initial vector(IV) used in AES and DES algorithms will be reset to 0.
*
Notes:
*
* - When using block-aligned data (multiple of block size),
* if the input buffer,
inBuff
and the output buffer,
* outBuff
* are the same array, then the output data area must not partially overlap the input data area such that
* the input data is modified before it is used;
* if inBuff==outBuff
and
inOffset < outOffset < inOffset+inLength
,
* incorrect output may result.
* - When non-block aligned data is presented as input data, no amount of input
* and output buffer data overlap is allowed;
* if
inBuff==outBuff
and
outOffset < inOffset+inLength
,
* incorrect output may result.
* - AES, DES, and triple DES algorithms in CBC mode reset the initial vector(IV)
* to 0. The initial vector(IV) can be re-initialized using the
*
init(Key, byte, byte[], short, short)
method.
* - On decryption operations (except when ISO 9797 method 1 padding is used),
* the padding bytes are not written to
outBuff
.
* - On encryption and decryption operations, the number of bytes output into
outBuff
* may be larger or smaller than inLength
or even 0.
* - On decryption operations resulting in an
ArrayIndexOutOfBoundException
,
* outBuff
may be partially modified.
*
* @param inBuff the input buffer of data to be encrypted/decrypted
* @param inOffset the offset into the input buffer at which to begin encryption/decryption
* @param inLength the byte length to be encrypted/decrypted
* @param outBuff the output buffer, may be the same as the input buffer
* @param outOffset the offset into the output buffer where the resulting output data begins
* @return number of bytes output in outBuff
* @throws CryptoException with the following reason codes:
*
* CryptoException.UNINITIALIZED_KEY
if key not initialized.
* CryptoException.INVALID_INIT
if this Cipher
object is
* not initialized.
* CryptoException.ILLEGAL_USE
if one of the following conditions is met:
*
* - This
Cipher
algorithm
* does not pad the message and the message is not block aligned.
* - This
Cipher
algorithm
* does not pad the message and no input
* data has been provided in inBuff
or via the update()
method.
* - The input message length is not supported.
*
- The decrypted data is not bounded by appropriate padding bytes.
*
*
*/
public abstract short doFinal(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset)
throws CryptoException;
/**
* Generates encrypted/decrypted output from input data. This method is intended for multiple-part
* encryption/decryption operations.
* This method requires temporary storage of
* intermediate results. In addition, if the input data length is not block aligned
* (multiple of block size)
* then additional internal storage may be allocated at this time to store a partial
* input data block.
* This may result in additional resource consumption and/or slow performance.
*
This method should only be used if all the input data required for the cipher
* is not available in one byte array. If all the input data required for the cipher
* is located in a single byte array, use of the doFinal()
method to
* process all of the input data is recommended. The doFinal()
method
* must be invoked to complete processing of any remaining input data buffered by one or more calls
* to the update()
method.
*
Notes:
* - When using block-aligned data (multiple of block size),
* if the input buffer,
inBuff
and the output buffer,
* outBuff
* are the same array, then the output data area must not partially overlap the input data area such that
* the input data is modified before it is used;
* if inBuff==outBuff
and
inOffset < outOffset < inOffset+inLength
,
* incorrect output may result.
* - When non-block aligned data is presented as input data, no amount of input
* and output buffer data overlap is allowed;
* if
inBuff==outBuff
and
outOffset < inOffset+inLength
,
* incorrect output may result.
* - On decryption operations(except when ISO 9797 method 1 padding is used),
* the padding bytes are not written to
outBuff
.
* - On encryption and decryption operations,
* block alignment considerations may require that
* the number of bytes output into
outBuff
be larger or smaller than
* inLength
or even 0.
* - If
inLength
is 0 this method does nothing.
*
* @param inBuff the input buffer of data to be encrypted/decrypted
* @param inOffset the offset into the input buffer at which to begin encryption/decryption
* @param inLength the byte length to be encrypted/decryptedv
* @param outBuff the output buffer, may be the same as the input buffer
* @param outOffset the offset into the output buffer where the resulting ciphertext/plaintext begins
* @return number of bytes output in outBuff
* @throws CryptoException with the following reason codes:
*
* CryptoException.UNINITIALIZED_KEY
if key not initialized.
* CryptoException.INVALID_INIT
if this Cipher
object is
* not initialized.
* CryptoException.ILLEGAL_USE
if the input message length is not supported.
*
*/
public abstract short update(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset)
throws CryptoException;
}