Skip to content

Commit 07b0cd8

Browse files
committed
adding JCMathLib core files
1 parent f08e1b4 commit 07b0cd8

16 files changed

+5090
-0
lines changed

JCMathLib/!uploader/opcrypto.cap

30 KB
Binary file not shown.

JCMathLib/src/opencrypto/jcmathlib/Bignat.java

Lines changed: 1882 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
package opencrypto.jcmathlib;
2+
3+
import javacard.framework.JCSystem;
4+
import javacard.framework.Util;
5+
import javacard.security.KeyBuilder;
6+
import javacard.security.KeyPair;
7+
import javacard.security.MessageDigest;
8+
import javacard.security.RSAPublicKey;
9+
import javacardx.crypto.Cipher;
10+
11+
/**
12+
*
13+
* @author Petr Svenda
14+
*/
15+
public class Bignat_Helper {
16+
private final ECConfig ecc;
17+
18+
/**
19+
* Helper flag which signalizes that code is executed inside simulator
20+
* (during tests). Is used to address simulator specific behaviour workaround
21+
* if required.
22+
*/
23+
public boolean bIsSimulator = false;
24+
25+
byte[] helper_BN_array1 = null;
26+
byte[] helper_BN_array2 = null;
27+
/**
28+
* Number of pre-allocated helper arrays
29+
*/
30+
public static final byte NUM_HELPER_ARRAYS = 2;
31+
32+
byte[] fnc_deep_resize_tmp = null;
33+
public byte[] fnc_mult_resultArray1 = null;
34+
byte[] fnc_mult_resultArray2 = null;
35+
byte[] tmp_array_short = null;
36+
37+
byte[] fnc_same_value_array1 = null;
38+
byte[] fnc_same_value_hash = null;
39+
40+
41+
// These Bignats helper_BN_? are allocated
42+
Bignat helper_BN_A;
43+
Bignat helper_BN_B;
44+
Bignat helper_BN_C;
45+
Bignat helper_BN_D;
46+
Bignat helper_BN_E;
47+
Bignat helper_BN_F;
48+
49+
// These Bignats are just pointing to some helper_BN_? so reasonable naming is preserved yet no need to actually allocated whole Bignat object
50+
Bignat fnc_mod_exp_modBN;
51+
52+
Bignat fnc_mod_add_tmp;
53+
Bignat fnc_mod_sub_tmp;
54+
Bignat fnc_mod_sub_tmpOther;
55+
Bignat fnc_mod_sub_tmpThis;
56+
57+
Bignat fnc_mod_mult_tmpThis;
58+
59+
Bignat fnc_mult_mod_tmpThis;
60+
Bignat fnc_mult_mod_tmp_x;
61+
Bignat fnc_mult_mod_tmp_mod;
62+
63+
Bignat fnc_divide_tmpThis;
64+
65+
Bignat fnc_exponentiation_i;
66+
Bignat fnc_exponentiation_tmp;
67+
68+
Bignat fnc_sqrt_p_1;
69+
Bignat fnc_sqrt_Q;
70+
Bignat fnc_sqrt_S;
71+
Bignat fnc_sqrt_tmp;
72+
Bignat fnc_sqrt_exp;
73+
Bignat fnc_sqrt_z;
74+
75+
Bignat fnc_mod_minus_2;
76+
77+
Bignat fnc_negate_tmp;
78+
79+
Bignat fnc_int_add_tmpMag;
80+
Bignat fnc_int_multiply_mod;
81+
Bignat fnc_int_multiply_tmpThis;
82+
Bignat fnc_int_divide_tmpThis;
83+
84+
RSAPublicKey fnc_NmodE_pubKey;
85+
Cipher fnc_NmodE_cipher;
86+
87+
public Bignat ONE;
88+
public Bignat TWO;
89+
public Bignat THREE;
90+
91+
92+
// Helper objects for fast multiplication of two large numbers (without modulo)
93+
KeyPair fnc_mult_keypair = null;
94+
RSAPublicKey fnc_mult_pubkey_pow2 = null;
95+
Cipher fnc_mult_cipher = null;
96+
MessageDigest hashEngine;
97+
98+
static byte[] CONST_ONE = {0x01};
99+
static byte[] CONST_TWO = {0x02};
100+
101+
public Bignat_Helper(ECConfig ecCfg) {
102+
ecc = ecCfg;
103+
104+
tmp_array_short = ecc.memAlloc.allocateByteArray((short) 2, JCSystem.MEMORY_TYPE_TRANSIENT_RESET); // only 2b RAM for faster add(short)
105+
fnc_NmodE_cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
106+
fnc_NmodE_pubKey = (RSAPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PUBLIC, ecc.MODULO_RSA_ENGINE_MAX_LENGTH_BITS, false);
107+
108+
// Multiplication speedup engines and arrays used by Bignat.mult_RSATrick()
109+
helper_BN_array1 = ecc.memAlloc.allocateByteArray((short) (ecc.MULT_RSA_ENGINE_MAX_LENGTH_BITS / 8), ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_array1));
110+
ecc.locker.registerLock(helper_BN_array1);
111+
helper_BN_array2 = ecc.memAlloc.allocateByteArray((short) (ecc.MULT_RSA_ENGINE_MAX_LENGTH_BITS / 8), ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_array2));
112+
ecc.locker.registerLock(helper_BN_array2);
113+
114+
fnc_deep_resize_tmp = helper_BN_array1;
115+
fnc_mult_resultArray1 = helper_BN_array1;
116+
fnc_mult_resultArray2 = helper_BN_array2;
117+
118+
fnc_same_value_array1 = helper_BN_array1;
119+
fnc_same_value_hash = helper_BN_array2;
120+
121+
helper_BN_A = new Bignat(ecc.MAX_BIGNAT_SIZE, ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_A), ecc);
122+
helper_BN_B = new Bignat(ecc.MAX_BIGNAT_SIZE, ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_B), ecc);
123+
helper_BN_C = new Bignat(ecc.MAX_BIGNAT_SIZE, ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_C), ecc);
124+
helper_BN_D = new Bignat(ecc.MAX_BIGNAT_SIZE, ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_D), ecc);
125+
helper_BN_E = new Bignat(ecc.MAX_BIGNAT_SIZE, ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_E), ecc);
126+
helper_BN_F = new Bignat((short) (ecc.MAX_BIGNAT_SIZE + 2), ecc.memAlloc.getAllocatorType(ObjectAllocator.BNH_helper_BN_F), ecc); // +2 is to correct for infrequent RSA result with two or more leading zeroes
127+
128+
// BN below are just reassigned allocated helper_BN_? so that same helper_BN_? is not used in parallel (checked by lock() unlock())
129+
fnc_mod_add_tmp = helper_BN_A;
130+
131+
fnc_mod_sub_tmpThis = helper_BN_A;
132+
fnc_mod_sub_tmp = helper_BN_B;
133+
fnc_mod_sub_tmpOther = helper_BN_C;
134+
135+
fnc_mult_mod_tmpThis = helper_BN_A;
136+
fnc_mult_mod_tmp_mod = helper_BN_B;
137+
fnc_mult_mod_tmp_x = helper_BN_C;
138+
139+
fnc_exponentiation_tmp = helper_BN_A;
140+
fnc_exponentiation_i = helper_BN_B;
141+
142+
fnc_mod_minus_2 = helper_BN_B;
143+
144+
fnc_negate_tmp = helper_BN_B;
145+
146+
fnc_sqrt_S = helper_BN_A;
147+
fnc_sqrt_exp = helper_BN_A;
148+
fnc_sqrt_p_1 = helper_BN_B;
149+
fnc_sqrt_Q = helper_BN_C;
150+
fnc_sqrt_tmp = helper_BN_D;
151+
fnc_sqrt_z = helper_BN_E;
152+
153+
fnc_mod_mult_tmpThis = helper_BN_E; // mod_mult is called from fnc_sqrt => requires helper_BN_E not being locked in fnc_sqrt when mod_mult is called
154+
155+
fnc_divide_tmpThis = helper_BN_E; // divide is called from fnc_sqrt => requires helper_BN_E not being locked in fnc_sqrt when divide is called
156+
157+
fnc_mod_exp_modBN = helper_BN_F; // mod_exp is called from fnc_sqrt => requires helper_BN_F not being locked in fnc_sqrt when mod_exp is called
158+
159+
fnc_int_add_tmpMag = helper_BN_A;
160+
fnc_int_multiply_mod = helper_BN_A;
161+
fnc_int_multiply_tmpThis = helper_BN_B;
162+
fnc_int_divide_tmpThis = helper_BN_A;
163+
164+
// Allocate BN constants always in EEPROM (only reading)
165+
ONE = new Bignat((short) 1, JCSystem.MEMORY_TYPE_PERSISTENT, ecc);
166+
ONE.one();
167+
TWO = new Bignat((short) 1, JCSystem.MEMORY_TYPE_PERSISTENT, ecc);
168+
TWO.two();
169+
THREE = new Bignat((short) 1, JCSystem.MEMORY_TYPE_PERSISTENT, ecc);
170+
THREE.three();
171+
172+
// Speedup for fast multiplication
173+
fnc_mult_keypair = new KeyPair(KeyPair.ALG_RSA_CRT, ecc.MULT_RSA_ENGINE_MAX_LENGTH_BITS);
174+
fnc_mult_keypair.genKeyPair();
175+
fnc_mult_pubkey_pow2 = (RSAPublicKey) fnc_mult_keypair.getPublic();
176+
//mult_privkey_pow2 = (RSAPrivateCrtKey) mult_keypair.getPrivate();
177+
fnc_mult_pubkey_pow2.setExponent(CONST_TWO, (short) 0, (short) CONST_TWO.length);
178+
fnc_mult_cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
179+
180+
hashEngine = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
181+
182+
183+
ecc.FLAG_FAST_MULT_VIA_RSA = false; // set true only if succesfully allocated and tested below
184+
try { // Subsequent code may fail on some real (e.g., Infineon CJTOP80K) cards - catch exception
185+
fnc_mult_cipher.init(fnc_mult_pubkey_pow2, Cipher.MODE_ENCRYPT);
186+
// Try operation - if doesn't work, exception SW_CANTALLOCATE_BIGNAT is emitted
187+
Util.arrayFillNonAtomic(fnc_mult_resultArray1, (short) 0, (short) fnc_mult_resultArray1.length, (byte) 6);
188+
fnc_mult_cipher.doFinal(fnc_mult_resultArray1, (short) 0, (short) fnc_mult_resultArray1.length, fnc_mult_resultArray1, (short) 0);
189+
ecc.FLAG_FAST_MULT_VIA_RSA = true;
190+
} catch (Exception ignored) {} // discard exception
191+
}
192+
193+
/**
194+
* Erase all values stored in helper objects
195+
*/
196+
void erase() {
197+
helper_BN_A.erase();
198+
helper_BN_B.erase();
199+
helper_BN_C.erase();
200+
helper_BN_D.erase();
201+
helper_BN_E.erase();
202+
helper_BN_F.erase();
203+
204+
Util.arrayFillNonAtomic(tmp_array_short, (short) 0, (short) tmp_array_short.length, (byte) 0);
205+
Util.arrayFillNonAtomic(helper_BN_array1, (short) 0, (short) helper_BN_array1.length, (byte) 0);
206+
Util.arrayFillNonAtomic(helper_BN_array2, (short) 0, (short) helper_BN_array2.length, (byte) 0);
207+
}
208+
209+
/**
210+
* Unlocks all helper objects
211+
*/
212+
public void unlockAll() {
213+
if (helper_BN_A.isLocked()) {
214+
helper_BN_A.unlock();
215+
}
216+
if (helper_BN_B.isLocked()) {
217+
helper_BN_B.unlock();
218+
}
219+
if (helper_BN_C.isLocked()) {
220+
helper_BN_C.unlock();
221+
}
222+
if (helper_BN_D.isLocked()) {
223+
helper_BN_D.unlock();
224+
}
225+
if (helper_BN_E.isLocked()) {
226+
helper_BN_E.unlock();
227+
}
228+
if (helper_BN_F.isLocked()) {
229+
helper_BN_F.unlock();
230+
}
231+
}
232+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package opencrypto.jcmathlib;
2+
3+
import javacard.framework.ISOException;
4+
5+
/**
6+
* Configure itself to proper lengths and other parameters according to intended length of ECC
7+
* @author Petr Svenda
8+
*/
9+
public class ECConfig {
10+
/**
11+
* The size of speedup engine used for fast modulo exponent computation
12+
* (must be larger than biggest Bignat used)
13+
*/
14+
public short MODULO_RSA_ENGINE_MAX_LENGTH_BITS = (short) 512;
15+
/**
16+
* The size of speedup engine used for fast multiplication of large numbers
17+
* Must be larger than 2x biggest Bignat used
18+
*/
19+
public short MULT_RSA_ENGINE_MAX_LENGTH_BITS = (short) 768;
20+
/**
21+
* The size of largest integer used in computations
22+
*/
23+
public short MAX_BIGNAT_SIZE = (short) 65; // ((short) (MODULO_ENGINE_MAX_LENGTH_BITS / 8) + 1);
24+
/**
25+
* The size of largest ECC point used
26+
*/
27+
public short MAX_POINT_SIZE = (short) 64;
28+
/**
29+
* The size of single coordinate of the largest ECC point used
30+
*/
31+
public short MAX_COORD_SIZE = (short) 32; // MAX_POINT_SIZE / 2
32+
33+
34+
/**
35+
* If true, fast multiplication of large numbers via RSA engine can be used.
36+
* Is set automatically after successful allocation of required engines
37+
*/
38+
public boolean FLAG_FAST_MULT_VIA_RSA = false;
39+
/**
40+
* Threshold length in bits of an operand after which speedup with RSA multiplication is used.
41+
* Schoolbook multiplication is used for shorter operands
42+
*/
43+
public short FAST_MULT_VIA_RSA_TRESHOLD_LENGTH = (short) 16;
44+
45+
/**
46+
* I true, fast multiplication of ECPoints via KeyAgreement can be used
47+
* Is set automatically after successful allocation of required engines
48+
*/
49+
public boolean FLAG_FAST_EC_MULT_VIA_KA = false;
50+
51+
/**
52+
* Object responsible for logical locking and unlocking of shared arrays and objects
53+
*/
54+
public ObjectLocker locker = null;
55+
/**
56+
* Object responsible for easy management of target placement (RAM/EEPROM) fro allocated objects
57+
*/
58+
public ObjectAllocator memAlloc = null;
59+
/**
60+
* Helper structure containing all preallocated objects necessary for Bignat operations
61+
*/
62+
public Bignat_Helper bnh = null;
63+
/**
64+
* Helper structure containing all preallocated objects necessary for ECPoint operations
65+
*/
66+
public ECPoint_Helper ech = null;
67+
68+
/**
69+
* Creates new control structure for requested bit length with all preallocated arrays and engines
70+
* @param maxECLength maximum length of ECPoint objects supported. The provided value is used to
71+
* initialize properly underlying arrays and engines.
72+
*/
73+
public ECConfig(short maxECLength) {
74+
// Set proper lengths and other internal settings based on required ECC length
75+
if (maxECLength <= (short) 256) {
76+
setECC256Config();
77+
}
78+
else if (maxECLength <= (short) 384) {
79+
setECC384Config();
80+
}
81+
else if (maxECLength <= (short) 512) {
82+
setECC512Config();
83+
}
84+
else {
85+
ISOException.throwIt(ReturnCodes.SW_ECPOINT_INVALIDLENGTH);
86+
}
87+
88+
// Allocate long-term helper values
89+
locker = new ObjectLocker((short) (ECPoint_Helper.NUM_HELPER_ARRAYS + Bignat_Helper.NUM_HELPER_ARRAYS));
90+
//locker.setLockingActive(false); // if required, locking can be disabled
91+
memAlloc = new ObjectAllocator();
92+
memAlloc.setAllAllocatorsRAM();
93+
//if required, memory for helper objects and arrays can be in persistent memory to save RAM (or some tradeoff)
94+
//ObjectAllocator.setAllAllocatorsEEPROM(); //ObjectAllocator.setAllocatorsTradeoff();
95+
96+
// Allocate helper objects for BN and EC
97+
bnh = new Bignat_Helper(this);
98+
ech = new ECPoint_Helper(this);
99+
}
100+
101+
public void refreshAfterReset() {
102+
if (locker != null) { locker.refreshAfterReset();}
103+
}
104+
105+
void reset() {
106+
FLAG_FAST_MULT_VIA_RSA = false;
107+
FLAG_FAST_EC_MULT_VIA_KA = false;
108+
}
109+
110+
public void setECC256Config() {
111+
reset();
112+
MODULO_RSA_ENGINE_MAX_LENGTH_BITS = (short) 512;
113+
MULT_RSA_ENGINE_MAX_LENGTH_BITS = (short) 768;
114+
MAX_POINT_SIZE = (short) 64;
115+
computeDerivedLengths();
116+
}
117+
public void setECC384Config() {
118+
reset();
119+
MODULO_RSA_ENGINE_MAX_LENGTH_BITS = (short) 768;
120+
MULT_RSA_ENGINE_MAX_LENGTH_BITS = (short) 1024;
121+
MAX_POINT_SIZE = (short) 96;
122+
computeDerivedLengths();
123+
}
124+
public void setECC512Config() {
125+
reset();
126+
MODULO_RSA_ENGINE_MAX_LENGTH_BITS = (short) 1024;
127+
MULT_RSA_ENGINE_MAX_LENGTH_BITS = (short) 1280;
128+
MAX_POINT_SIZE = (short) 128;
129+
computeDerivedLengths();
130+
}
131+
public void setECC521Config() {
132+
reset();
133+
MODULO_RSA_ENGINE_MAX_LENGTH_BITS = (short) 1280;
134+
MULT_RSA_ENGINE_MAX_LENGTH_BITS = (short) 1280;
135+
MAX_POINT_SIZE = (short) 129;
136+
computeDerivedLengths();
137+
}
138+
139+
private void computeDerivedLengths() {
140+
MAX_BIGNAT_SIZE = (short) ((short) (MODULO_RSA_ENGINE_MAX_LENGTH_BITS / 8) + 1);
141+
MAX_COORD_SIZE = (short) (MAX_POINT_SIZE / 2);
142+
}
143+
144+
/**
145+
* Unlocks all logically locked arrays and objects. Useful as recovery after premature end of some operation (e.g., due to exception)
146+
* when some objects remains locked.
147+
*/
148+
void unlockAll() {
149+
bnh.unlockAll();
150+
ech.unlockAll();
151+
locker.unlockAll();
152+
}
153+
}

0 commit comments

Comments
 (0)