All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.licel.jcardsim.crypto.SymmetricCipherImpl Maven / Gradle / Ivy

There is a newer version: 3.0.6.0
Show newest version
/*
 * 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 com.licel.jcardsim.crypto;

import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.Key;
import javacardx.crypto.Cipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.ISO7816d4Padding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.ParametersWithIV;

/**
 * Implementation Cipher with symmetric keys based
 * on BouncyCastle CryptoAPI.
 * @see Cipher
 */
public class SymmetricCipherImpl extends Cipher {

    byte algorithm;
    BufferedBlockCipher engine;
    boolean isInitialized;

    public SymmetricCipherImpl(byte algorithm) {
        this.algorithm = algorithm;
    }

    public void init(Key theKey, byte theMode) throws CryptoException {
        selectCipherEngine(theKey);
        engine.init(theMode == MODE_ENCRYPT, ((SymmetricKeyImpl) theKey).getParameters());
        isInitialized = true;
    }

    public void init(Key theKey, byte theMode, byte[] bArray, short bOff, short bLen) throws CryptoException {
        switch (algorithm) {
            case ALG_DES_ECB_NOPAD:
            case ALG_DES_ECB_ISO9797_M1:
            case ALG_DES_ECB_ISO9797_M2:
            case ALG_DES_ECB_PKCS5:
                CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
                break;
            case ALG_DES_CBC_NOPAD:
            case ALG_DES_CBC_ISO9797_M1:
            case ALG_DES_CBC_ISO9797_M2:
            case ALG_DES_CBC_PKCS5:
                if (bLen != (short) 8) {
                    CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
                }
                break;
        }
        selectCipherEngine(theKey);
        byte[] iv = JCSystem.makeTransientByteArray(bLen, JCSystem.CLEAR_ON_RESET);
        Util.arrayCopyNonAtomic(bArray, bOff, iv, (short) 0, bLen);
        engine.init(theMode == MODE_ENCRYPT, new ParametersWithIV(((SymmetricKeyImpl) theKey).getParameters(), iv));
        isInitialized = true;
    }

    public byte getAlgorithm() {
        return algorithm;
    }

    public short doFinal(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) throws CryptoException {
        if (!isInitialized) {
            CryptoException.throwIt(CryptoException.INVALID_INIT);
        }

        short processedBytes = (short) engine.processBytes(inBuff, inOffset, inLength, outBuff, outOffset);
        try {
            return (short) (engine.doFinal(outBuff, outOffset + processedBytes) + processedBytes);
        } catch (Exception ex) {
            CryptoException.throwIt(CryptoException.ILLEGAL_USE);
        }
        return -1;
    }

    public short update(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset) throws CryptoException {
        if (!isInitialized) {
            CryptoException.throwIt(CryptoException.INVALID_INIT);
        }
        return (short) engine.processBytes(inBuff, inOffset, inLength, outBuff, outOffset);
    }

    private void selectCipherEngine(Key theKey) {
        if (theKey == null) {
            CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
        }
        if (!theKey.isInitialized()) {
            CryptoException.throwIt(CryptoException.UNINITIALIZED_KEY);
        }
        if (!(theKey instanceof SymmetricKeyImpl)) {
            CryptoException.throwIt(CryptoException.ILLEGAL_VALUE);
        }
        SymmetricKeyImpl key = (SymmetricKeyImpl) theKey;
        switch (algorithm) {
            case ALG_DES_CBC_NOPAD:
            case ALG_AES_BLOCK_128_CBC_NOPAD:
                engine = new BufferedBlockCipher(new CBCBlockCipher(key.getCipher()));
                break;
            case ALG_DES_CBC_ISO9797_M1:
                engine = new PaddedBufferedBlockCipher(new CBCBlockCipher(key.getCipher()), new ZeroBytePadding());
                break;
            case ALG_DES_CBC_ISO9797_M2:
                engine = new PaddedBufferedBlockCipher(new CBCBlockCipher(key.getCipher()), new ISO7816d4Padding());
                break;
            case ALG_DES_CBC_PKCS5:
                engine = new PaddedBufferedBlockCipher(new CBCBlockCipher(key.getCipher()), new PKCS7Padding());
                break;
            case ALG_DES_ECB_NOPAD:
            case ALG_AES_BLOCK_128_ECB_NOPAD:                
                engine = new BufferedBlockCipher(key.getCipher());
                break;
            case ALG_DES_ECB_ISO9797_M1:
                engine = new PaddedBufferedBlockCipher(key.getCipher(), new ZeroBytePadding());
                break;
            case ALG_DES_ECB_ISO9797_M2:
                engine = new PaddedBufferedBlockCipher(key.getCipher(), new ISO7816d4Padding());
                break;
            case ALG_DES_ECB_PKCS5:
                engine = new PaddedBufferedBlockCipher(key.getCipher(), new PKCS7Padding());
                break;
            case ALG_AES_CBC_ISO9797_M2:
                engine = new PaddedBufferedBlockCipher(new CBCBlockCipher(key.getCipher()), new ISO7816d4Padding());
                break;
            default:
                CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM);
                break;
        }
    }
    public byte getPaddingAlgorithm() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public byte getCipherAlgorithm() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy