zoukankan      html  css  js  c++  java
  • 如何获取JavaCard剩余空间

    0x01应用场景

    获取JavaCard卡内剩余空间,一方面是在评估一张卡的时候需要用到,另一方面是在应用个人化或者运行时需要用到。

    例如:应用提供商为了保证自己的应用在卡内运行期间能够不受空间影响,一般会在个人化(安装应用)的时候先分配好需要用到的空间,以免空间被后来应用占用,导致运行失败。

    0x02空间类型

    卡内剩余空间包括获取卡内的剩余永久存储器(E2P or Flash),还有获取易失性存储器空间(RAM),这里的RAM分为两部分,一部分是在卡片复位时清零的内存CLEAR_ON_RESET,缩写为COR或者RTR(Clear_on_Reset Transient RAM);另一部分为应用在取消选择的时候清零的内存CLEAR_ON_DESELECT,缩写为COD或者DTR(Clear_on_Deselect Transient RAM)。本文将通过实例获取卡内的这三种存储器剩余空间。

    0x03获取接口

    对于获取JavaCard内可用空间,API提供了相应的接口JCSystem.getAvaliableMemory(byte memoryType) ,位于javacard.framework包下,如下所示,引用自JCAPI v2.2.2。 

     

    getAvailableMemory

    public static short getAvailableMemory(byte memoryType)
                                    throws SystemException
    Obtains the amount of memory of the specified type that is available to the applet. Note that implementation-dependent memory overhead structures may also use the same memory pool.

    Notes:

    • The number of bytes returned is only an upper bound on the amount of memory available due to overhead requirements.
    • Allocation of CLEAR_ON_RESET transient objects may affect the amount of CLEAR_ON_DESELECT transient memory available.
    • Allocation of CLEAR_ON_DESELECT transient objects may affect the amount of CLEAR_ON_RESET transient memory available.
    • If the number of available bytes is greater than 32767, then this method returns 32767.
    • The returned count is not an indicator of the size of object which may be created since memory fragmentation is possible.
    Parameters:
    memoryType - the type of memory being queried. One of the MEMORY_TYPE_* constants defined above. See MEMORY_TYPE_PERSISTENT.
    Returns:
    the upper bound on available bytes of memory for the specified type
    Throws:
    SystemException - with the following reason codes:
    • SystemException.ILLEGAL_VALUE if memoryType is not a valid memory type.

      根据接口描述,如果可用字节数超过32767(0x3FFF),则只返回32767。那如何返回超过32767的空间,可参考本文后面的代码实例。

    0x04代码实例

    1.获取DTR剩余空间

     1     /**
     2      * 获取剩余MEMORY_TYPE_TRANSIENT_DESELECT空间
     3      * @return
     4      */
     5     public int getFreeDTR(){
     6         //首先取得剩余空间大小
     7         short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
     8         int allmemsize = memsize;
     9         //如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
    10         while(memsize == (short)32767){
    11             JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);//不存储返回的数组对象
    12             memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
    13             allmemsize += memsize;
    14         }
    15         return allmemsize;
    16     }

     2.获取RTR剩余空间

     1     /**
     2      * 获取剩余的MEMORY_TYPE_TRANSIENT_RESET空间
     3      * @return
     4      */
     5     public int getFreeRTR(){
     6         //首先取得剩余空间大小
     7         short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
     8         int allmemsize = memsize;
     9         //如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
    10         while(memsize == (short)32767){
    11             JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_RESET);//不存储返回的数组对象
    12             memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
    13             allmemsize += memsize;
    14         }
    15         return allmemsize;
    16     }

     3.获取E2P/Flash的剩余空间

     1     /**
     2      * 获取剩余的E2P/Flash空间,如果剩余空间大于0x3FFF,则此接口将创建数组,然后再获取新的剩余空间,
     3      * 数组对象头将占用几个字节(根据对象存储结构不一样,可能占用字节数不同,一般数组头为7字节),因此存在误差。
     4      * @return
     5      */
     6     public int getFreePersistent(){
     7         //首先取得剩余空间大小
     8         short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
     9         int allmemsize = memsize;
    10         //如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
    11         while(memsize == (short)32767){
    12             byte[] tmp=new byte[memsize]; //不存储返回的数组对象
    13             memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
    14             allmemsize += memsize;
    15         }
    16         return allmemsize;
    17     }

     注意

    1.获取剩余空间的应用自身的代码需要占用部分空间,本例中的应用代码主468字节,存储在卡内空间为 278 字节.

    2.DTR与RTR可能使用同一块区域。

    3.以上代码在使用converter转成cap文件时需要加上支持int类型的选项,如果卡片本身不支持int,则代码中相应的地方需要做调整,譬如说如果卡内相应存储器空间大于0x3FFF时,可以将每次取得的值存储在apdubuffer中,一起返回到卡外,然后再计算。 

    完整代码

      1 package GetFreeSpacePkg;
      2 
      3 import javacard.framework.APDU;
      4 import javacard.framework.ISO7816;
      5 import javacard.framework.Applet;
      6 import javacard.framework.ISOException;
      7 import javacard.framework.JCSystem;
      8 
      9 /**
     10  * 获取卡内剩余空间,包括E2P/Flash与RAM.
     11  * 对于E2P/Flash来说,如果卡内剩余空间超过0x3FFF,则此应用返回的数据会有较小的误差。
     12  * 测试命令:
     13  * 
     14  * 8000000000 //get DTR
     15  * 8001000000 //get RTR
     16  * 8002000000 //get E2P/Flash
     17  *  
     18  * @author SCPlatform@outlook.com
     19  */
     20 public class GetFreeSpaceApplet extends Applet {
     21     public static void install(byte[] bArray, short bOffset, byte bLength) {
     22         new GetFreeSpaceApplet().register(bArray, (short) (bOffset + 1),bArray[bOffset]);
     23     }
     24 
     25     public void process(APDU apdu) {
     26         if (selectingApplet()) {
     27             return;
     28         }
     29         
     30         byte[] buf = apdu.getBuffer();
     31         int iFreeSpace=0; 
     32         switch (buf[ISO7816.OFFSET_INS]) {
     33         case (byte) 0x00://DTR
     34             iFreeSpace = getFreeDTR();
     35             break;
     36         case (byte) 0x01://RTR
     37             iFreeSpace = getFreeRTR();
     38             break;
     39         case (byte) 0x02://persistent
     40             iFreeSpace = getFreePersistent();
     41             break;
     42         default:
     43             ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
     44         }
     45         JCSystem.requestObjectDeletion();
     46         buf[3]=(byte)(iFreeSpace);
     47         buf[2]=(byte)(iFreeSpace>>8);
     48         buf[1]=(byte)(iFreeSpace>>16);
     49         buf[0]=(byte)(iFreeSpace>>24);
     50         apdu.setOutgoingAndSend((short)0, (short)4);
     51     }
     52     /**
     53      * 获取剩余MEMORY_TYPE_TRANSIENT_DESELECT空间
     54      * @return
     55      */
     56     public int getFreeDTR(){
     57         //首先取得剩余空间大小
     58         short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
     59         int allmemsize = memsize;
     60         //如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
     61         while(memsize == (short)32767){
     62             JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);//不存储返回的数组对象
     63             memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT);
     64             allmemsize += memsize;
     65         }
     66         return allmemsize;
     67     }
     68     
     69     /**
     70      * 获取剩余的MEMORY_TYPE_TRANSIENT_RESET空间
     71      * @return
     72      */
     73     public int getFreeRTR(){
     74         //首先取得剩余空间大小
     75         short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
     76         int allmemsize = memsize;
     77         //如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
     78         while(memsize == (short)32767){
     79             JCSystem.makeTransientByteArray(memsize,JCSystem.MEMORY_TYPE_TRANSIENT_RESET);//不存储返回的数组对象
     80             memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
     81             allmemsize += memsize;
     82         }
     83         return allmemsize;
     84     }
     85     
     86     /**
     87      * 获取剩余的E2P/Flash空间,如果剩余空间大于0x3FFF,则此接口将创建数组,然后再获取新的剩余空间,
     88      * 数组对象头将占用几个字节(根据对象存储结构不一样,可能占用字节数不同,一般数组头为7字节),因此存在误差。
     89      * @return
     90      */
     91     public int getFreePersistent(){
     92         //首先取得剩余空间大小
     93         short memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
     94         int allmemsize = memsize;
     95         //如果返回值为0x3FFF,则剩余空间大于此值,可继续取得剩余空间
     96         while(memsize == (short)32767){
     97             byte[] tmp=new byte[memsize]; //不存储返回的数组对象
     98             memsize = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
     99             allmemsize += memsize;
    100         }
    101         return allmemsize;
    102     }
    103 }

     0x05资料参考

    1.Application Programming Interface Java Card™ Platform, Version 2.2.2

    作者:SCPlatform
    Email:SCPlatform@outlook.com
    本文旨在学习、交流使用,任何对文章内容的出版、印刷,对文章中提到的技术的商业使用时,请注意可能存在的法律风险。

  • 相关阅读:
    关于三次握手与四次挥手你要知道这些
    seafile看不见repo报500错误的解决方法
    VMWare Workstation 配置docker多macvlan网络方法
    利用Python3的dpkt库进行ARP扫描
    关于LAMP配置Let’s Encrypt SSL证书
    OpenSSL生成CA证书及终端用户证书
    CentOS7.2安装Vim8和YouCompleteMe
    CentOS 7.2安装Jenkins自动构建Git项目
    CentOS 7.2 安装Gerrit 2.14.6
    CentOS7.2编译GCC7.3
  • 原文地址:https://www.cnblogs.com/SCPlatform/p/5125200.html
Copyright © 2011-2022 走看看