Site Tools


javacard-api-samples:aes

AES Sample Code

Download Sample Code Discussion

/*
 * @file  AESSample.java
 * @version v1.0
 * Package AID: 4A617661436172644F53
 * Applet AID:  4A617661436172644F5301
 * @brief The ALgorithm of AES Sample Code in JavaCard API Specification
 * @comment The purpose of this example is only used to show the usage of API functions and there is no practical significance.
 * @copyright Copyright(C) 2016 JavaCardOS Technologies Co., Ltd. All rights reserved.
 */
package JavaCardOS.Sample.Algorithm;
 
import javacard.framework.*;
import javacard.security.KeyBuilder;
import javacard.security.*;
import javacardx.crypto.*;
 
public class AESSample extends Applet
{
    private static final byte INS_SET_AES_KEY              = (byte)0x10;
    private static final byte INS_SET_AES_ICV              = (byte)0x11;
    private static final byte INS_DO_AES_CIPHER            = (byte)0x12;
 
    private byte aesKeyLen;
    private byte[] aesKey;
    private byte[] aesICV;
 
    private Cipher aesEcbCipher;
    private Cipher aesCbcCipher;
 
    private Key tempAesKey1;
    private Key tempAesKey2;
    private Key tempAesKey3;
 
    public AESSample()
    {
        aesKey = new byte[32];
        aesICV = new byte[16];
        aesKeyLen = 0;
        //Create a AES ECB/CBS object instance of the AES algorithm.
        aesEcbCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, false);
        aesCbcCipher = Cipher.getInstance(Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, false);
        //Create uninitialized cryptographic keys for AES algorithms
        tempAesKey1 = KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_128, false);
        tempAesKey2 = KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_192, false);
        tempAesKey3 = KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
 
        JCSystem.requestObjectDeletion();
    }
 
    public static void install(byte[] bArray, short bOffset, byte bLength)
    {
        new AESSample().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
    }
 
    public void process(APDU apdu)
    {
        if (selectingApplet())
        {
            return;
        }
 
        byte[] buf = apdu.getBuffer();
        short len = apdu.setIncomingAndReceive();
 
        switch (buf[ISO7816.OFFSET_INS])
        {
        case INS_SET_AES_KEY:
            // SET_AES_KEY
            setAesKey(apdu, len);
            break;
        case INS_SET_AES_ICV:
            // SET_AES_ICV
            setAesICV(apdu, len);
            break;
        case INS_DO_AES_CIPHER:
            //DO_AES_CIPHER
            doAesCipher(apdu, len);
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
        }
    }
 
    //Set the key of AES Encrypt/Decrypt
    private void setAesKey(APDU apdu, short len)
    {
        byte[] buffer = apdu.getBuffer();
        byte keyLen = 0;
        switch (buffer[ISO7816.OFFSET_P1])
        {
        case (byte)0x01:
            if (len != 16) // The length of key is 16 bytes
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            keyLen = (byte)16;
            break;
        case (byte)0x02:
            if (len != 24) //The length of key is 24 bytes
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            keyLen = (byte)24;
            break;
        case (byte)0x03:
            if (len != 32) //The length of key is 32 bytes
            {
                ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
            }
            keyLen = (byte)32;
            break;
        default:
            ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
            break;
        }
 
        JCSystem.beginTransaction();
        //Copy the incoming AES Key value to the global variable 'aesKey'
        Util.arrayCopy(buffer, ISO7816.OFFSET_CDATA, aesKey, (short)0, len);
        aesKeyLen = keyLen;
        JCSystem.commitTransaction();
    }
 
    //Set AES ICV, ICV is the initial vector
    private void setAesICV(APDU apdu, short len)
    {
        if (len != 16)
        {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
        //Copy the incoming ICV value to the global variable 'aesICV'
        Util.arrayCopy(apdu.getBuffer(), ISO7816.OFFSET_CDATA, aesICV, (short)0, (short)16);
    }
 
    //Sets the Key data, and return the AESKey object. The plaintext length of input key data is 16/24/32 bytes.
    private Key getAesKey()
    {
        Key tempAesKey = null;
        switch (aesKeyLen)
        {
        case (byte)16:
            tempAesKey = tempAesKey1;
            break;
        case (byte)24:
            tempAesKey = tempAesKey2;
            break;
        case (byte)32:
            tempAesKey = tempAesKey3;
            break;
        default:
            ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
            break;
        }
        //Set the 'aesKey' key data value into the internal representation
        ((AESKey)tempAesKey).setKey(aesKey, (short)0);
        return tempAesKey;
    }
 
   //AES algorithm encrypt and decrypt
    private void doAesCipher(APDU apdu, short len)
    {
        //The byte length to be encrypted/decrypted must be a multiple of 16
        if (len <= 0 || len % 16 != 0)
        {
            ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
        }
 
        byte[] buffer = apdu.getBuffer();
        Key key = getAesKey();
        byte mode = buffer[ISO7816.OFFSET_P1] == (byte)0x00 ? Cipher.MODE_ENCRYPT : Cipher.MODE_DECRYPT;
        Cipher cipher = buffer[ISO7816.OFFSET_P2] == (byte)0x00 ? aesEcbCipher : aesCbcCipher;
        //Initializes the 'cipher' object with the appropriate Key and algorithm specific parameters.
        //AES algorithms in CBC mode expect a 16-byte parameter value for the initial vector(IV)
        if (cipher == aesCbcCipher)
        {
            cipher.init(key, mode, aesICV, (short)0, (short)16);
        }
        else
        {
            cipher.init(key, mode);
        }
        //This method must be invoked to complete a cipher operation. Generates encrypted/decrypted output from all/last input data.
        cipher.doFinal(buffer, ISO7816.OFFSET_CDATA, len, buffer, (short)0);
        apdu.setOutgoingAndSend((short)0, len);
    }
 
}

The test script of AES is as follows: Download Test Script

//The test script of AES
//Copyright(C) JavaCardOS Technologies Co., Ltd. All rights reserved.
 
//AES Select Applet
00A404000B4A617661436172644F530100;
//AES-CBC-256Key
//set Key  CBC-256 Key Length
80100300209AF0BF0D5D711B9E01C59ED55A015C8AB2D3980010B72CBBBA6E2C91F8ADC604;
//set ICV
80110000101C64F340DD29C891B4826509A1FF64E8;
//CBC encrypt
//expect: E2E6C4AB4D212BB52A292B6368137D3E9000
8012000110C9C9332182CFC8AB48908A972D283582;
//AES-CBC-256Key
//set Key  CBC-256 Key Length
8010030020B57260D2B78CF4B37F315000B7720F796A3E379E6934BB21EEB6449C803F3080;
//set ICV
80110000103DCBD02A91EA65D1A2E23A53584AA18A;
//CBC decrypt
//expect:722D19DB28EF9088CB5FE90784C16A3E336156D29CC4421A398B9C22C63E2F074FADA2B9D95AF7BBE2F246000E20AEB03BAFBE61E2768E92FDF537B29ADA75FF93BDBE4DE2A8F053229B6C5062F8F23D71546689B0F48622B59A6BA30EF151D53B3616B9FEF7AE9A95CE56EABB292E9BAF3B380B915BBFD3AB3238AF99F56E4EED4682D146DA18F92902D1A085EE9E609000
80120101902D5D6440C517EBC13EFC8E2471918C3C34620A287D9C5A84CBD77CDCC134E56614A880F0A897F317F6A523BAB1C9FAAEA9A368B3EF0FA7A73AFAC4FA89745B620A07A2D03B47A8A24FABDF1AD39BD90F91CA4FE2B5C667B42ECE36D657E38481D721D0C8C65094CA11B7CB2C1F30AFC7B482C79D16EA21126FFBDD5973A9EB2C42A014C090DA3FF80370EDD9DCB0073E;
//AES-ECB-192Key
//set Key
801002001800CF30D306C95D3851B85D11786917BA3C28F8FB0E349524;
//ECB encrypt
//expect:1108C33BCAB8B43FB229AFDACEBB7859A498371191DEBCD1E40916E2C72835E41B3F536A27D35429FED70B2973862F1C9000
801200003012A4D1CDB906E044B14CC2BC2D6DE6FBAE708568CC248266331195E0ECAEA825DED581F79473A2DE40846DC3003F8CB9;
//AES-ECB-192Key
//set Key
8010020018DCC25F4F162E0F9B5A2617F6341AF37AA41C3EE4C1F27848;
//ECB decrypt
//expect:475161225A00DBBD3CDEB304BB5F8FCCD40B266DB5BC164E23F646EB542D6BA988099087CDC1B98749F61D3EDFFAAAA50564D6BBCF49C9F3267E86877521A18C1897DA808BD356E65261B2F208CE065B9000
801201005006E99C9EBAB3D08F7EE117838078B3C7AF419F797B7672E2DBC2850695695878BAC232736FEE0827F3C4A051DE0BF70EA7ECDFF169A6EC53E78491EACD0D879E397A6E97796DB79B17DFC197125A427B;
javacard-api-samples/aes.txt · Last modified: 2017/05/13 02:43 (external edit)