Skip to content
petrs edited this page Jul 26, 2017 · 24 revisions

JCMathLib cryptographic library for Java Card

The JCMathLib is focused on the provision of low-level operations with large numbers (Bignat, Integer) and ECPoints which executes reasonably fast and requires only a decent amount of resources (especially transient RAM which is a scarse resource). The implementation is fully based on the public Java Card API and requires no proprietary functions.

The requirements

The JCMathLib requires the following features to be supported by used smart card to provide its full functionality:

  • Support for RSA cipher engine without any padding (ALG_RSA_NOPAD) [common]
  • Possibility to set RSA public exponent to value 2 [common].
    • If not supported, fast big number multiplication cannot be used.
  • Possibility to set arbitrary public RSA exponent and modulus [common].
    • If not supported, fast modular exponentiation cannot be used.
  • Support for EC KeyPair with prime field (KeyPair.ALG_EC_FP) for required EC key length (e.g., 256b) [common on newer cards].
    • If not supported, Bignat and Integer operations can be used but not ECPoint operations.
  • Support for KeyAgreement with plain (not hashed) output (ALG_EC_SVDP_DH_PLAIN) [only newer cards].
    • If not supported, ECPoint.multiplication() with large scalar cannot be used.
  • Support for EC signature computation (any hash function, e.g., Signature.ALG_ECDSA_SHA_256) [common on newer cards].
    • If not supported, ECPoint.multiplication() with large scalar cannot be used.
  • Enough RAM memory to store helper arrays and objects. For 256 bits EC, about 1KB is required [common].
    • If enough RAM is not available, (part of) helpers can be allocated in EEPROM in exchange for a lower computation speed.

Performance and memory overhead

Speed of operations

The table below provides the performance of EC operations as measured on real smart cards. Provided measurements are an average out of 1000 operation runs.

ECPoint operations (256b) NXP J2E081 NXP J2D081 G&D Smartcafe 6.0
randomize() 296 ms 245 ms 503 ms
add(256b) 2995 ms 2892 ms 2747 ms
negation() 112 ms 109 ms 94 ms
multiplication(256b) 4157 ms 3981 ms 3854 ms

Notes:

  • Time for randomize() operation is very close to the native performance offered by used card.
  • Time for multiplication with scalar can be improved close to native performance if card supports KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY

TODO: measurements for Bignat

RAM memory overhead of the library and separate objects

JCSystem.getAvailableMemory() method is used to obtain free memory before and after allocation of target object. The memory overhead of whole JCMathLib (helper arrays and objects) is measured in configuration set to support 256 bits EC. Memory requirements neccessary to use single ECPoint and Bignat is also enumerated (both set to work with 256b values).

NXP J2E081 NXP J2D081 G&D Smartcafe 6.0
JCMathLib(256b) 1144 B 1152 B 923 B
new ECPoint(256b) 0* B 0* B 0* B
new Bignat(256b) 32 B 32 B 32 B

Notes:

  • For all cards, helper arrays of the same lengths are allocated. The difference in the memory consumption between different cards is probably caused by the different internal handling of memory consumed by cryptographic engines and key objects which are also allocated by JCMathLib library.
  • 0 bytes required for single ECPoint is caused by internal storage of ECPoint value in KeyPair object. The KeyPair is stored in EEPROM hence no RAM overhead.

Compilation, upload, dependencies

  • ant-javacard
  • GlobalPlatformPro

Examples

  • Example use for ECPoint operations
  • Example use for Bignat and Integer operations

Important: Java Card programming is not exactly equal to standard Java

Note that Java Card programming is different from standard Java programming although basic Java Card applet can be compiled using javac tool. The list of notable differences can be found in Java Card documentation, but the most important ones are:

  • Memory is very limited (especially fast transient RAM), an allocation is slow and garbage collection can be completely missing. As a result, all require arrays and objects are usually allocated in the applet constructor and reused during the whole lifetime of an applet on a card.
  • Operator new will put an object into persistent memory which will persist loss removal of a card from a smart card reader but is also quite slow to write. If an array is to be allocated in fast RAM, a dedicated method like JCSystem.getTransientByteArray() needs to be is used.
  • Object oriented hierarchies and features are used, but only in a limited fashion. Frequently accessed attributes might be public instead of modified via setters. A large number of arguments slow down method calls.
  • For performance reasons, copy-free programming is preferred. Instead of creating new and new arrays with intermediate results, the in-place modification is performed with array passed together with start offset and data length. Dedicated methods from JCSystem class are used for fast memory operations like copy or fill or arrays.
  • As a card environment defends itself against an adversary, it also makes difficult to debug and profile applet on a card. As a result, a code is usually first debugged in a simulator. But as a simulator itself is never a perfect representation of real card, execution on real hardware usually requires additional debugging.

So don't be surprised to see some deviations from good Java programming practices. But if you will spot something incorrect, let us know please - possibly by pull request? :)

Clone this wiki locally