惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - SCPlatform

windown 使用python 自动切换网络 CPU封装技术介绍 openssl unicode编译以及VC++2015环境下的问题 重新开启此博 MIFARE Classic S50技术详解 Mifare简介 如何获取JavaCard栈信息 JavaCard应用开发环境 如何统合分析一张JavaCard BER-TLV数据结构 智能卡中的数据结构 加密解密算法 SCPlatform博客文章总目录 C#实现简体中文和繁体中文的转换 QueryString 整站过滤 关于脚本注入的问题 开发Blog需注意的Blog基本特征和功能要素 java 学习步骤 CodeSmith 实体生成模板(C#版)
如何获取JavaCard剩余空间
SCPlatform · 2012-01-12 · via 博客园 - SCPlatform

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