package opencrypto.jcmathlib; import javacard.framework.ISOException; import javacard.framework.JCSystem; import javacard.framework.Util; /** * The control point for unified allocation of arrays and objects with customable * specification of allocator type (RAM/EEPROM) for particular array. Allows for * quick personalization and optimization of memory use when compiling for cards * with more/less available memory. * * @author Petr Svenda */ public class ObjectAllocator { short allocatedInRAM = 0; short allocatedInEEPROM = 0; byte[] ALLOCATOR_TYPE_ARRAY = null; public static final byte BNH_helper_BN_array1 = 0; public static final byte BNH_helper_BN_array2 = 1; public static final byte BNH_helper_BN_A = 2; public static final byte BNH_helper_BN_B = 3; public static final byte BNH_helper_BN_C = 4; public static final byte BNH_helper_BN_D = 5; public static final byte BNH_helper_BN_E = 6; public static final byte BNH_helper_BN_F = 7; public static final byte ECPH_helperEC_BN_A = 8; public static final byte ECPH_helperEC_BN_B = 9; public static final byte ECPH_helperEC_BN_C = 10; public static final byte ECPH_helperEC_BN_D = 11; public static final byte ECPH_helperEC_BN_E = 12; public static final byte ECPH_helperEC_BN_F = 13; public static final byte ECPH_uncompressed_point_arr1 = 14; public static final byte ECPH_hashArray = 15; public static final short ALLOCATOR_TYPE_ARRAY_LENGTH = (short) (ECPH_hashArray + 1); /** * Creates new allocator control object, resets performance counters */ public ObjectAllocator() { ALLOCATOR_TYPE_ARRAY = new byte[ALLOCATOR_TYPE_ARRAY_LENGTH]; setAllAllocatorsRAM(); resetAllocatorCounters(); } /** * All type of allocator for all object as EEPROM */ public final void setAllAllocatorsEEPROM() { Util.arrayFillNonAtomic(ALLOCATOR_TYPE_ARRAY, (short) 0, (short) ALLOCATOR_TYPE_ARRAY.length, JCSystem.MEMORY_TYPE_PERSISTENT); } /** * All type of allocator for all object as RAM */ public void setAllAllocatorsRAM() { Util.arrayFillNonAtomic(ALLOCATOR_TYPE_ARRAY, (short) 0, (short) ALLOCATOR_TYPE_ARRAY.length, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); } /** * All type of allocator for selected object as RAM (faster), rest EEPROM (saving RAM) * The current settings is heuristically obtained from measurements of performance of Bignat and ECPoint operations */ public void setAllocatorsTradeoff() { // Set initial allocators into EEPROM setAllAllocatorsEEPROM(); // Put only the most perfromance relevant ones into RAM ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_array1] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_array2] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_A] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_B] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_C] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_D] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_E] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[BNH_helper_BN_F] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[ECPH_helperEC_BN_B] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[ECPH_helperEC_BN_C] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; ALLOCATOR_TYPE_ARRAY[ECPH_uncompressed_point_arr1] = JCSystem.MEMORY_TYPE_TRANSIENT_RESET; } /** * Allocates new byte[] array with provided length either in RAM or EEPROM based on an allocator type. * Method updates internal counters of bytes allocated with specific allocator. Use {@code getAllocatedInRAM()} * or {@code getAllocatedInEEPROM} for counters readout. * @param length length of array * @param allocatorType type of allocator * @return allocated array */ public byte[] allocateByteArray(short length, byte allocatorType) { switch (allocatorType) { case JCSystem.MEMORY_TYPE_PERSISTENT: allocatedInEEPROM += length; return new byte[length]; case JCSystem.MEMORY_TYPE_TRANSIENT_RESET: allocatedInRAM += length; return JCSystem.makeTransientByteArray(length, JCSystem.CLEAR_ON_RESET); case JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT: allocatedInRAM += length; return JCSystem.makeTransientByteArray(length, JCSystem.CLEAR_ON_DESELECT); } return null; } /** * Returns pre-set allocator type for provided object identified by unique objectAllocatorID * @param objectAllocatorID unique id of target object * @return allocator type */ public byte getAllocatorType(short objectAllocatorID) { if (objectAllocatorID >= 0 && objectAllocatorID <= (short) ALLOCATOR_TYPE_ARRAY.length) { return ALLOCATOR_TYPE_ARRAY[objectAllocatorID]; } else { ISOException.throwIt(ReturnCodes.SW_ALLOCATOR_INVALIDOBJID); return -1; } } /** * Returns number of bytes allocated in RAM via {@code allocateByteArray()} since last reset of counters. * @return number of bytes allocated in RAM via this control object */ public short getAllocatedInRAM() { return allocatedInRAM; } /** * Returns number of bytes allocated in EEPROM via {@code allocateByteArray()} * since last reset of counters. * * @return number of bytes allocated in EEPROM via this control object */ public short getAllocatedInEEPROM() { return allocatedInEEPROM; } /** * Resets counters of allocated bytes in RAM and EEPROM */ public final void resetAllocatorCounters() { allocatedInRAM = 0; allocatedInEEPROM = 0; } }