├── .gitignore
├── LICENSE
├── README.md
├── build.xml
├── demo
└── templates
│ ├── input_applet_files
│ └── OCUnitTests.java
│ ├── template_profiler_applet
│ ├── PM.java
│ └── PMC.java
│ └── template_profiler_client
│ ├── build.xml
│ ├── manifest.mf
│ ├── nbproject
│ ├── build-impl.xml
│ ├── genfiles.properties
│ ├── project.properties
│ └── project.xml
│ └── src
│ └── jcprofiler
│ ├── CardManager.java
│ ├── JCProfiler_client.java
│ ├── PMC.java
│ └── PerfTests.java
├── dist
└── README.TXT
├── lib
└── commons-cli-1.3.1.jar
├── nbproject
├── build-impl.xml
├── genfiles.properties
├── project.properties
└── project.xml
└── src
└── opencryptoutils
├── JCProfiler.java
├── PerfCodeConfig.java
└── PerfCodeGenerator.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | /dist/*.jar
15 | *.war
16 | *.ear
17 | *.zip
18 | *.tar.gz
19 | *.rar
20 |
21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22 | hs_err_pid*
23 |
24 | # Javadoc
25 | /dist/javadoc/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JCProfiler
2 | Performance profiler for JavaCard code
3 |
4 | The performance profiling of JavaCard applet code is a notoriously difficult task. As the card environment is build to protect the stored and processed secrets against an attacker with direct physical access, it is difficult to obtain a precise timing trace of the executed code on the granularity of separate methods or even lines of code. To the best of our knowledge, there is no open-source performance profiler available for the JavaCard platform. So we decided to build one.
5 |
6 | The profiler is based on the following idea: The source code of an applet is extended with numerous additional lines of code called "performance traps" capable to prematurely interrupt the applet's execution if the condition match the controlling _trapID_ variable. The trap can be inserted after every single line of an applet's original code to achieved the finest profiling granularity if required. The client-side testing application is then repeatedly executed with the different value of controlling _trapID_ variable. As a result increasingly larger chunk of applet's code is executed before interrupted on the corresponding trap. The client-side time measurements are collected and processed to compute the time difference between the two consecutive traps - resulting in the time required to execute a block of an original code between these two traps.
7 |
8 | The usage is simple:
9 | 1. Developer signalizes interseting parts of code to profile by insertion of fixed strings
10 | 2. JCProfiler tool automatically generates all necessary testing code
11 | 3. Developer sets proper applet AID, applet CLA and APDU command which will trigger inspected operation
12 | 4. Performance measurement client is executed to collect all timing measurements
13 | 5. Applet source code is annotted with the extracted timings
14 |
15 | Take a look at short tutorial (thx Matej Evin):
16 |
17 | [](https://www.youtube.com/watch?v=4eYKty6G4fg)
18 |
19 | Please read [wiki](https://github.com/petrs/JCProfiler/wiki) for all details.
20 |
21 | ## Simple example
22 | The code below was automatically transformed and profiled after insertion of perfromance traps 'PM.check(PM.TRAP...'. Time in milliseconds provides time necessary to reach particular trap from the previous one. A name of card and unique profiling session ID in braces (gd60,1500968219581).
23 |
24 | ```` java
25 | private short multiplication_x_KA(Bignat scalar, byte[] outBuffer, short outBufferOffset) {
26 | PM.check(PM.TRAP_ECPOINT_MULT_X_1); // 40 ms (gd60,1500968219581)
27 | priv.setS(scalar.as_byte_array(), (short) 0, scalar.length());
28 | PM.check(PM.TRAP_ECPOINT_MULT_X_2); // 12 ms (gd60,1500968219581)
29 |
30 | keyAgreement.init(priv);
31 | PM.check(PM.TRAP_ECPOINT_MULT_X_3); // 120 ms (gd60,1500968219581)
32 |
33 | short len = this.getW(point_arr1, (short) 0);
34 | PM.check(PM.TRAP_ECPOINT_MULT_X_4); // 9 ms (gd60,1500968219581)
35 | len = keyAgreement.generateSecret(point_arr1, (short) 0, len, outBuffer, outBufferOffset);
36 | PM.check(PM.TRAP_ECPOINT_MULT_X_5); // 186 ms (gd60,1500968219581)
37 |
38 | return COORD_SIZE;
39 | }
40 | ````
41 |
42 |
43 | ### Satisfied users so far
44 | * [JCMathLib](https://github.com/OpenCryptoProject/JCMathLib) library for Bignat and ECPoint operations
45 | * [AEonJC](https://github.com/palkrajesh/AEonJC) implementation of ACORN, AEGIS, ASCON, CLOC, and MORUS authenticated encryption functions
46 | * You? Give it a try - love to hear the feedback :)
47 |
48 | ### Future work
49 | * Proper ant compilation, travis...
50 | * Averaging from multiple results instead of single run
51 | * Better analysis of applet and detection of developer-provided info
52 | * Automatic insertion of all performance traps (no requirement for manual templates)
53 | * Code improvements (a lot of hardcoded strings etc. )
54 |
55 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Builds, tests, and runs the project JCProfiler.
12 |
13 |
73 |
74 |
--------------------------------------------------------------------------------
/demo/templates/input_applet_files/OCUnitTests.java:
--------------------------------------------------------------------------------
1 | package opencrypto.jcmathlib;
2 |
3 |
4 | import javacard.framework.APDU;
5 | import javacard.framework.Applet;
6 | import javacard.framework.CardRuntimeException;
7 | import javacard.framework.ISO7816;
8 | import javacard.framework.ISOException;
9 | import javacard.framework.JCSystem;
10 | import javacard.framework.PINException;
11 | import javacard.framework.SystemException;
12 | import javacard.framework.TransactionException;
13 | import javacard.framework.Util;
14 | import javacard.security.CryptoException;
15 |
16 | /**
17 | *
18 | * @author Vasilios Mavroudis and Petr Svenda
19 | */
20 | public class OCUnitTests extends Applet {
21 | // Main instruction CLAss
22 | public final static byte CLA_OC_UT = (byte) 0xB0; // OpenCrypto Unit Tests
23 |
24 | // INStructions
25 | // Card Management
26 | public final static byte INS_SETUP = (byte) 0x01;
27 | public final static byte INS_STATUS = (byte) 0x02;
28 | public final static byte INS_CLEANUP = (byte) 0x03;
29 | //public final static byte INS_TESTRSAMULT = (byte) 0x04;
30 | public final static byte INS_PERF_SETSTOP = (byte) 0x05;
31 | public final static byte INS_FREEMEMORY = (byte) 0x06;
32 | public final static byte INS_GET_ALLOCATOR_STATS = (byte) 0x07;
33 |
34 | //BigNatural and BigInteger Operations
35 | public final static byte INS_INT_STR = (byte) 0x09;
36 | public final static byte INS_INT_ADD = (byte) 0x10;
37 | public final static byte INS_INT_SUB = (byte) 0x11;
38 | public final static byte INS_INT_MUL = (byte) 0x12;
39 | public final static byte INS_INT_DIV = (byte) 0x13;
40 | //public final static byte INS_INT_EXP = (byte) 0x14;
41 | public final static byte INS_INT_MOD = (byte) 0x15;
42 |
43 | public final static byte INS_BN_STR = (byte) 0x20;
44 | public final static byte INS_BN_ADD = (byte) 0x21;
45 | public final static byte INS_BN_SUB = (byte) 0x22;
46 | public final static byte INS_BN_MUL = (byte) 0x23;
47 | public final static byte INS_BN_EXP = (byte) 0x24;
48 | public final static byte INS_BN_MOD = (byte) 0x25;
49 | public final static byte INS_BN_SQRT = (byte) 0x26;
50 | public final static byte INS_BN_MUL_SCHOOL = (byte) 0x27;
51 |
52 | public final static byte INS_BN_ADD_MOD = (byte) 0x30;
53 | public final static byte INS_BN_SUB_MOD = (byte) 0x31;
54 | public final static byte INS_BN_MUL_MOD = (byte) 0x32;
55 | public final static byte INS_BN_EXP_MOD = (byte) 0x33;
56 | public final static byte INS_BN_INV_MOD = (byte) 0x34;
57 | public final static byte INS_BN_POW2_MOD = (byte) 0x35;
58 |
59 | //EC Operations
60 | public final static byte INS_EC_GEN = (byte) 0x40;
61 | public final static byte INS_EC_DBL = (byte) 0x41;
62 | public final static byte INS_EC_ADD = (byte) 0x42;
63 | public final static byte INS_EC_MUL = (byte) 0x43;
64 | public final static byte INS_EC_NEG = (byte) 0x44;
65 | public final static byte INS_EC_SETCURVE_G = (byte) 0x45;
66 | public final static byte INS_EC_COMPARE = (byte) 0x46;
67 |
68 |
69 | static boolean bIsSimulator = false;
70 | static boolean bTEST_256b_CURVE = true;
71 | static boolean bTEST_512b_CURVE = false;
72 |
73 | short[] m_memoryInfo = null;
74 | short m_memoryInfoOffset = 0;
75 |
76 | ECConfig m_ecc = null;
77 |
78 | ECCurve m_testCurve = null;
79 |
80 | ECPoint m_testPoint1 = null;
81 | ECPoint m_testPoint2 = null;
82 |
83 | byte[] m_customG = null;
84 | ECCurve m_testCurveCustom = null;
85 | ECPoint m_testPointCustom = null;
86 |
87 | Bignat m_testBN1;
88 | Bignat m_testBN2;
89 | Bignat m_testBN3;
90 |
91 | Integer m_testINT1;
92 | Integer m_testINT2;
93 |
94 | public OCUnitTests() {
95 | m_memoryInfo = new short[(short) (7 * 3)]; // Contains RAM and EEPROM memory required for basic library objects
96 | m_memoryInfoOffset = snapshotAvailableMemory((short) 1, m_memoryInfo, m_memoryInfoOffset);
97 | if (bTEST_256b_CURVE) {
98 | m_ecc = new ECConfig((short) 256);
99 | }
100 | if (bTEST_512b_CURVE) {
101 | m_ecc = new ECConfig((short) 512);
102 | }
103 | m_memoryInfoOffset = snapshotAvailableMemory((short) 2, m_memoryInfo, m_memoryInfoOffset);
104 |
105 |
106 | // Pre-allocate test objects (no new allocation for every tested operation)
107 | if (bTEST_256b_CURVE) {
108 | m_testCurve = new ECCurve(false, SecP256r1.p, SecP256r1.a, SecP256r1.b, SecP256r1.G, SecP256r1.r, m_ecc);
109 | m_memoryInfoOffset = snapshotAvailableMemory((short) 3, m_memoryInfo, m_memoryInfoOffset);
110 | // m_testCurveCustom and m_testPointCustom will have G occasionally changed so we need separate ECCurve
111 | m_customG = new byte[(short) SecP256r1.G.length];
112 | Util.arrayCopyNonAtomic(SecP256r1.G, (short) 0, m_customG, (short) 0, (short) SecP256r1.G.length);
113 | m_testCurveCustom = new ECCurve(false, SecP256r1.p, SecP256r1.a, SecP256r1.b, m_customG, SecP256r1.r, m_ecc);
114 | }
115 | if (bTEST_512b_CURVE) {
116 | m_testCurve = new ECCurve(false, P512r1.p, P512r1.a, P512r1.b, P512r1.G, P512r1.r, m_ecc);
117 | // m_testCurveCustom and m_testPointCustom will have G occasionally changed so we need separate ECCurve
118 | m_customG = new byte[(short) P512r1.G.length];
119 | Util.arrayCopyNonAtomic(P512r1.G, (short) 0, m_customG, (short) 0, (short) P512r1.G.length);
120 | m_testCurveCustom = new ECCurve(false, P512r1.p, P512r1.a, P512r1.b, m_customG, P512r1.r, m_ecc);
121 | }
122 |
123 | m_memoryInfoOffset = snapshotAvailableMemory((short) 5, m_memoryInfo, m_memoryInfoOffset);
124 | m_testPoint1 = new ECPoint(m_testCurve, m_ecc);
125 | m_memoryInfoOffset = snapshotAvailableMemory((short) 6, m_memoryInfo, m_memoryInfoOffset);
126 | m_testPoint2 = new ECPoint(m_testCurve, m_ecc);
127 | m_testPointCustom = new ECPoint(m_testCurveCustom, m_ecc);
128 |
129 | // Testing Bignat objects used in tests
130 | m_memoryInfoOffset = snapshotAvailableMemory((short) 7, m_memoryInfo, m_memoryInfoOffset);
131 | byte memoryType = JCSystem.MEMORY_TYPE_TRANSIENT_RESET;
132 | m_testBN1 = new Bignat(m_ecc.MAX_BIGNAT_SIZE, memoryType, m_ecc);
133 | m_memoryInfoOffset = snapshotAvailableMemory((short) 8, m_memoryInfo, m_memoryInfoOffset);
134 | m_testBN2 = new Bignat(m_ecc.MAX_BIGNAT_SIZE, memoryType, m_ecc);
135 | m_testBN3 = new Bignat(m_ecc.MAX_BIGNAT_SIZE, memoryType, m_ecc);
136 |
137 | short intLen = 4;
138 | m_testINT1 = new Integer(intLen, m_ecc);
139 | m_testINT2 = new Integer(intLen, m_ecc);
140 | }
141 |
142 | public static void install(byte[] bArray, short bOffset, byte bLength) {
143 | // GP-compliant JavaCard applet registration
144 | //new UnitTests().register(bArray, (short) (bOffset + 1), bArray[bOffset]);
145 | if (bLength == 0) {
146 | bIsSimulator = true;
147 | }
148 | new OCUnitTests().register();
149 | }
150 |
151 | public boolean select() {
152 | updateAfterReset();
153 | return true;
154 | }
155 | public void process(APDU apdu) {
156 | byte[] apdubuf = apdu.getBuffer();
157 |
158 | // Good practice: Return 9000 on SELECT
159 | if (selectingApplet()) {
160 | return;
161 | }
162 |
163 | // Check CLA byte
164 | if (apdubuf[ISO7816.OFFSET_CLA] != CLA_OC_UT) {
165 | ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
166 | }
167 |
168 | // Process Input
169 | short dataLen = apdu.setIncomingAndReceive(); // returns length of data field
170 |
171 | try {
172 | switch (apdubuf[ISO7816.OFFSET_INS]) {
173 | case INS_CLEANUP:
174 | m_ecc.unlockAll();
175 | break;
176 | case INS_FREEMEMORY:
177 | if (!bIsSimulator) {
178 | JCSystem.requestObjectDeletion();
179 | }
180 | break;
181 | case INS_PERF_SETSTOP:
182 | PM.m_perfStop = Util.makeShort(apdubuf[ISO7816.OFFSET_CDATA], apdubuf[(short) (ISO7816.OFFSET_CDATA + 1)]);
183 | break;
184 | case INS_GET_ALLOCATOR_STATS:
185 | short offset = 0;
186 | Util.setShort(apdubuf, offset, m_ecc.memAlloc.getAllocatedInRAM());
187 | offset += 2;
188 | Util.setShort(apdubuf, offset, m_ecc.memAlloc.getAllocatedInEEPROM());
189 | offset += 2;
190 | for (short i = 0; i < (short) m_memoryInfo.length; i++) {
191 | Util.setShort(apdubuf, offset, m_memoryInfo[i]);
192 | offset += 2;
193 | }
194 | apdu.setOutgoingAndSend((short) 0, offset);
195 | break;
196 |
197 | //==============================================================
198 | case INS_EC_GEN:
199 | test_EC_GEN(apdu);
200 | break;
201 | case INS_EC_SETCURVE_G:
202 | test_EC_SETCURVE_G(apdu, dataLen);
203 | break;
204 | case INS_EC_DBL:
205 | test_EC_DBL(apdu);
206 | break;
207 |
208 | case INS_EC_ADD:
209 | test_EC_ADD(apdu);
210 | break;
211 |
212 | case INS_EC_MUL:
213 | test_EC_MUL(apdu);
214 | break;
215 |
216 | case INS_EC_NEG:
217 | test_EC_NEG(apdu);
218 | break;
219 |
220 | case INS_EC_COMPARE:
221 | test_EC_COMPARE(apdu);
222 | break;
223 |
224 | //==============================================================
225 | case INS_BN_STR:
226 | test_BN_STR(apdu, dataLen);
227 | break;
228 |
229 | case INS_BN_ADD:
230 | test_BN_ADD(apdu, dataLen);
231 | break;
232 |
233 | case INS_BN_SUB:
234 | test_BN_SUB(apdu, dataLen);
235 | break;
236 |
237 | case INS_BN_MUL:
238 | test_BN_MUL(apdu, dataLen, true);
239 | break;
240 | case INS_BN_MUL_SCHOOL:
241 | test_BN_MUL(apdu, dataLen, false);
242 | break;
243 |
244 | case INS_BN_EXP:
245 | test_BN_EXP(apdu, dataLen);
246 | break;
247 | case INS_BN_SQRT:
248 | test_BN_SQRT(apdu, dataLen);
249 | break;
250 |
251 | case INS_BN_MOD:
252 | test_BN_MOD(apdu, dataLen);
253 | break;
254 |
255 | case INS_BN_ADD_MOD:
256 | test_BN_ADD_MOD(apdu, dataLen);
257 | break;
258 |
259 | case INS_BN_SUB_MOD:
260 | test_BN_SUB_MOD(apdu, dataLen);
261 | break;
262 |
263 | case INS_BN_MUL_MOD:
264 | test_BN_MUL_MOD(apdu, dataLen);
265 | break;
266 |
267 | case INS_BN_EXP_MOD:
268 | test_BN_EXP_MOD(apdu, dataLen);
269 | break;
270 |
271 | case INS_BN_POW2_MOD:
272 | test_BN_POW2_MOD(apdu, dataLen);
273 | break;
274 |
275 | case INS_BN_INV_MOD:
276 | test_BN_INV_MOD(apdu, dataLen);
277 | break;
278 |
279 | // ---------------------------------------
280 | case INS_INT_STR:
281 | test_INT_STR(apdu, dataLen);
282 | break;
283 |
284 | case INS_INT_ADD:
285 | test_INT_ADD(apdu, dataLen);
286 | break;
287 |
288 | case INS_INT_SUB:
289 | test_INT_SUB(apdu, dataLen);
290 | break;
291 |
292 | case INS_INT_MUL:
293 | test_INT_MUL(apdu, dataLen);
294 | break;
295 |
296 | case INS_INT_DIV:
297 | test_INT_DIV(apdu, dataLen);
298 | break;
299 |
300 | //case (byte) Configuration.INS_INT_EXP:
301 | // test_INT_EXP(apdu, dataLen);
302 | // break;
303 | case INS_INT_MOD:
304 | test_INT_MOD(apdu, dataLen);
305 | break;
306 |
307 | default:
308 | // good practice: If you don't know the INStruction, say so:
309 | ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
310 | }
311 | // Capture all reasonable exceptions and change into readable ones (instead of 0x6f00)
312 | } catch (ISOException e) {
313 | throw e; // Our exception from code, just re-emit
314 | } catch (ArrayIndexOutOfBoundsException e) {
315 | ISOException.throwIt(ReturnCodes.SW_ArrayIndexOutOfBoundsException);
316 | } catch (ArithmeticException e) {
317 | ISOException.throwIt(ReturnCodes.SW_ArithmeticException);
318 | } catch (ArrayStoreException e) {
319 | ISOException.throwIt(ReturnCodes.SW_ArrayStoreException);
320 | } catch (NullPointerException e) {
321 | ISOException.throwIt(ReturnCodes.SW_NullPointerException);
322 | } catch (NegativeArraySizeException e) {
323 | ISOException.throwIt(ReturnCodes.SW_NegativeArraySizeException);
324 | } catch (CryptoException e) {
325 | ISOException.throwIt((short) (ReturnCodes.SW_CryptoException_prefix | e.getReason()));
326 | } catch (SystemException e) {
327 | ISOException.throwIt((short) (ReturnCodes.SW_SystemException_prefix | e.getReason()));
328 | } catch (PINException e) {
329 | ISOException.throwIt((short) (ReturnCodes.SW_PINException_prefix | e.getReason()));
330 | } catch (TransactionException e) {
331 | ISOException.throwIt((short) (ReturnCodes.SW_TransactionException_prefix | e.getReason()));
332 | } catch (CardRuntimeException e) {
333 | ISOException.throwIt((short) (ReturnCodes.SW_CardRuntimeException_prefix | e.getReason()));
334 | } catch (Exception e) {
335 | ISOException.throwIt(ReturnCodes.SW_Exception);
336 | }
337 |
338 | }
339 |
340 |
341 | final short snapshotAvailableMemory(short tag, short[] buffer, short bufferOffset) {
342 | buffer[bufferOffset] = tag;
343 | buffer[(short) (bufferOffset + 1)] = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET);
344 | buffer[(short) (bufferOffset + 2)] = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
345 | return (short) (bufferOffset + 3);
346 | }
347 |
348 |
349 | void test_EC_GEN(APDU apdu) {
350 | byte[] apdubuf = apdu.getBuffer();
351 |
352 | PM.check(PMC.TRAP_EC_GEN_0);
353 | m_testPoint1.randomize();
354 | PM.check(PMC.TRAP_EC_GEN_0);
355 |
356 | short len = m_testPoint1.getW(apdubuf, (short) 0);
357 | PM.check(PMC.TRAP_EC_GEN_0);
358 | apdu.setOutgoingAndSend((short) 0, len);
359 | }
360 |
361 | void updateAfterReset() {
362 | if (m_testCurve != null) { m_testCurve.updateAfterReset(); }
363 | if (m_testCurveCustom != null) {m_testCurveCustom.updateAfterReset(); }
364 | if (m_ecc != null) {
365 | m_ecc.refreshAfterReset();
366 | m_ecc.unlockAll();
367 | }
368 | if (m_ecc.bnh != null) {m_ecc.bnh.bIsSimulator = bIsSimulator; }
369 | }
370 | void test_EC_SETCURVE_G(APDU apdu, short dataLen) {
371 | byte[] apdubuf = apdu.getBuffer();
372 |
373 | Util.arrayCopyNonAtomic(apdubuf, ISO7816.OFFSET_CDATA, m_customG, (short) 0, dataLen);
374 | PM.check(PM.TRAP_EC_SETCURVE_1);
375 |
376 | if (apdubuf[ISO7816.OFFSET_P2] == 1) { // If required, complete new custom curve and point is allocated
377 | m_testCurveCustom = new ECCurve(false, SecP256r1.p, SecP256r1.a, SecP256r1.b, m_customG, SecP256r1.r, m_ecc);
378 | m_testPointCustom = new ECPoint(m_testCurveCustom, m_ecc);
379 | PM.check(PM.TRAP_EC_SETCURVE_2);
380 | // Release unused previous objects
381 | if (!bIsSimulator) {
382 | JCSystem.requestObjectDeletion();
383 | }
384 | }
385 | else {
386 | // Otherwise, only G is set and relevant objects are updated
387 | m_testCurveCustom.setG(apdubuf, (short) ISO7816.OFFSET_CDATA, m_testCurveCustom.POINT_SIZE);
388 | m_testPointCustom.updatePointObjects(); // After changing curve parameters, internal objects needs to be actualized
389 | }
390 | }
391 |
392 | void test_EC_DBL(APDU apdu) {
393 | byte[] apdubuf = apdu.getBuffer();
394 |
395 | PM.check(PM.TRAP_EC_DBL_1);
396 | m_testPointCustom.setW(apdubuf, (short) ISO7816.OFFSET_CDATA, m_testCurveCustom.POINT_SIZE);
397 | // NOTE: for doubling, curve G must be also set. Here we expect that test_EC_SETCURVE_G() was called before
398 | PM.check(PM.TRAP_EC_DBL_2);
399 | m_testPointCustom.makeDouble(); //G + G
400 | PM.check(PM.TRAP_EC_DBL_3);
401 |
402 | short len = m_testPointCustom.getW(apdubuf, (short) 0);
403 | PM.check(PM.TRAP_EC_DBL_4);
404 | apdu.setOutgoingAndSend((short) 0, len);
405 | }
406 |
407 | void test_EC_ADD(APDU apdu) {
408 | byte[] apdubuf = apdu.getBuffer();
409 |
410 | PM.check(PM.TRAP_EC_ADD_1);
411 | m_testPoint1.setW(apdubuf, (short) ISO7816.OFFSET_CDATA, m_testCurve.POINT_SIZE);
412 | PM.check(PM.TRAP_EC_ADD_2);
413 | m_testPoint2.setW(apdubuf, (short) (ISO7816.OFFSET_CDATA + m_testCurve.POINT_SIZE), m_testCurve.POINT_SIZE);
414 | PM.check(PM.TRAP_EC_ADD_3);
415 | m_testPoint1.add(m_testPoint2);
416 | PM.check(PM.TRAP_EC_ADD_4);
417 |
418 | short len = m_testPoint1.getW(apdubuf, (short) 0);
419 | PM.check(PM.TRAP_EC_ADD_5);
420 | apdu.setOutgoingAndSend((short) 0, len);
421 | }
422 |
423 | void test_EC_MUL(APDU apdu) {
424 | byte[] apdubuf = apdu.getBuffer();
425 | short p1_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
426 |
427 | PM.check(PM.TRAP_EC_MUL_1);
428 | Bignat scalar = m_testBN1;
429 | scalar.set_size(p1_len);
430 | scalar.from_byte_array(p1_len, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
431 | PM.check(PM.TRAP_EC_MUL_2);
432 | m_testPoint1.setW(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1_len), m_testCurve.POINT_SIZE);
433 | PM.check(PM.TRAP_EC_MUL_3);
434 | m_testPoint1.multiplication(scalar);
435 | PM.check(PM.TRAP_EC_MUL_4);
436 |
437 | short len = m_testPoint1.getW(apdubuf, (short) 0);
438 | PM.check(PM.TRAP_EC_MUL_5);
439 | apdu.setOutgoingAndSend((short) 0, len);
440 | }
441 |
442 | void test_EC_NEG(APDU apdu) {
443 | byte[] apdubuf = apdu.getBuffer();
444 | short p1_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
445 |
446 | m_testPoint1.setW(apdubuf, ISO7816.OFFSET_CDATA, p1_len);
447 | m_testPoint1.negate();
448 | short len = m_testPoint1.getW(apdubuf, (short) 0);
449 | apdu.setOutgoingAndSend((short) 0, len);
450 | }
451 |
452 |
453 | void test_EC_COMPARE(APDU apdu) {
454 | byte[] apdubuf = apdu.getBuffer();
455 | short p1_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
456 | short p2_len = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
457 |
458 | m_testPoint1.setW(apdubuf, (short) ISO7816.OFFSET_CDATA, p1_len);
459 | m_testPoint2.setW(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1_len), p2_len);
460 | apdubuf[0] = 0; apdubuf[1] = 0; apdubuf[2] = 0; apdubuf[3] = 0; // Tests expects big integer
461 | apdubuf[4] = m_testPoint1.isEqual(m_testPoint2) ? (byte) 1 : (byte) 0;
462 | apdu.setOutgoingAndSend((short) 0, (short) 5);
463 | }
464 |
465 |
466 | void test_BN_STR(APDU apdu, short dataLen) {
467 | byte[] apdubuf = apdu.getBuffer();
468 |
469 | PM.check(PM.TRAP_BN_STR_1);
470 | Bignat num = m_testBN1;
471 | num.set_size(dataLen);
472 | PM.check(PM.TRAP_BN_STR_2);
473 | num.from_byte_array(dataLen, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
474 | PM.check(PM.TRAP_BN_STR_3);
475 | short len = num.copy_to_buffer(apdubuf, (short) 0);
476 | apdu.setOutgoingAndSend((short) 0, len);
477 | }
478 |
479 | void test_BN_ADD(APDU apdu, short dataLen) {
480 | byte[] apdubuf = apdu.getBuffer();
481 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
482 |
483 | PM.check(PM.TRAP_BN_ADD_1);
484 | Bignat num1 = m_testBN1;
485 | num1.set_size(p1);
486 | PM.check(PM.TRAP_BN_ADD_2);
487 | Bignat num2 = m_testBN2;
488 | num2.set_size((short) (dataLen - p1));
489 | PM.check(PM.TRAP_BN_ADD_3);
490 | Bignat sum = m_testBN3;
491 | sum.set_size((short) (p1 + 1));
492 |
493 | PM.check(PM.TRAP_BN_ADD_4);
494 | num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
495 | num2.from_byte_array((short) (dataLen - p1), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
496 | PM.check(PM.TRAP_BN_ADD_5);
497 | sum.copy(num1);
498 | PM.check(PM.TRAP_BN_ADD_6);
499 | sum.add(num2);
500 | PM.check(PM.TRAP_BN_ADD_7);
501 | short len = sum.copy_to_buffer(apdubuf, (short) 0);
502 | apdu.setOutgoingAndSend((short) 0, len);
503 | }
504 |
505 | void test_BN_SUB(APDU apdu, short dataLen) {
506 | byte[] apdubuf = apdu.getBuffer();
507 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
508 |
509 | PM.check(PM.TRAP_BN_SUB_1);
510 | Bignat sub1 = m_testBN1;
511 | sub1.set_size(p1);
512 | PM.check(PM.TRAP_BN_SUB_2);
513 | Bignat sub2 = m_testBN2;
514 | sub2.set_size((short) (dataLen - p1));
515 | PM.check(PM.TRAP_BN_SUB_3);
516 | Bignat result = m_testBN3;
517 | result.set_size((short) (p1 + 1));
518 | PM.check(PM.TRAP_BN_SUB_4);
519 | sub1.from_byte_array(dataLen, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
520 | sub2.from_byte_array(dataLen, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
521 | PM.check(PM.TRAP_BN_SUB_5);
522 | result.copy(sub1);
523 | PM.check(PM.TRAP_BN_SUB_6);
524 | result.subtract(sub2);
525 | PM.check(PM.TRAP_BN_SUB_7);
526 | short len = result.copy_to_buffer(apdubuf, (short) 0);
527 | apdu.setOutgoingAndSend((short) 0, len);
528 | }
529 |
530 | void test_BN_MUL(APDU apdu, short dataLen, boolean bFastEngine) {
531 | byte[] apdubuf = apdu.getBuffer();
532 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
533 |
534 | PM.check(PM.TRAP_BN_MUL_1);
535 | Bignat mul1 = m_testBN1;
536 | mul1.set_size(p1);
537 | PM.check(PM.TRAP_BN_MUL_2);
538 | Bignat mul2 = m_testBN2;
539 | mul2.set_size((short) (dataLen - p1));
540 | PM.check(PM.TRAP_BN_MUL_3);
541 | Bignat product = m_testBN3;
542 | product.set_size(dataLen);
543 | PM.check(PM.TRAP_BN_MUL_4);
544 | mul1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
545 | mul2.from_byte_array((short)(dataLen-p1), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
546 | PM.check(PM.TRAP_BN_MUL_5);
547 | if (bFastEngine) {
548 | product.mult_rsa_trick(mul1, mul2, null, null);
549 | }
550 | else {
551 | product.mult_schoolbook(mul1, mul2);
552 | }
553 | PM.check(PM.TRAP_BN_MUL_6);
554 | short len = product.copy_to_buffer(apdubuf, (short) 0);
555 | apdu.setOutgoingAndSend((short) 0, len);
556 | }
557 |
558 | void test_BN_EXP(APDU apdu, short dataLen) {
559 | byte[] apdubuf = apdu.getBuffer();
560 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
561 | short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF);
562 |
563 | PM.check(PM.TRAP_BN_EXP_1);
564 | Bignat base = m_testBN1;
565 | base.set_size(p1);
566 | PM.check(PM.TRAP_BN_EXP_2);
567 | Bignat exp = m_testBN2;
568 | exp.set_size((short) (dataLen - p1));
569 | PM.check(PM.TRAP_BN_EXP_3);
570 | Bignat res = m_testBN3;
571 | res.set_size((short) (m_ecc.MAX_BIGNAT_SIZE / 2));
572 | PM.check(PM.TRAP_BN_EXP_4);
573 | base.from_byte_array(p1, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
574 | exp.from_byte_array((short) (dataLen - p1), (short) 0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
575 | PM.check(PM.TRAP_BN_EXP_5);
576 | res.exponentiation(base, exp);
577 | PM.check(PM.TRAP_BN_EXP_6);
578 | short len = res.copy_to_buffer(apdubuf, (short) 0);
579 | apdu.setOutgoingAndSend((short) 0, len);
580 | }
581 |
582 | void test_BN_SQRT(APDU apdu, short dataLen) {
583 | byte[] apdubuf = apdu.getBuffer();
584 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
585 |
586 | Bignat num = m_testBN1;
587 | num.set_size(p1);
588 | num.from_byte_array(p1, p1, apdubuf, ISO7816.OFFSET_CDATA);
589 | Bignat num2 = m_testBN2;
590 | num2.clone(m_testCurve.pBN);
591 | num.sqrt_FP(num2);
592 | short len = num.copy_to_buffer(apdubuf, (short) 0);
593 | apdu.setOutgoingAndSend((short) 0, len);
594 | }
595 |
596 |
597 | void test_BN_MOD(APDU apdu, short dataLen) {
598 | byte[] apdubuf = apdu.getBuffer();
599 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
600 |
601 | PM.check(PM.TRAP_BN_MOD_1);
602 | Bignat num = m_testBN1;
603 | num.set_size(p1);
604 | PM.check(PM.TRAP_BN_MOD_2);
605 | Bignat mod = m_testBN2;
606 | mod.set_size((short) (dataLen - p1));
607 | PM.check(PM.TRAP_BN_MOD_3);
608 | num.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
609 | mod.from_byte_array((short)(dataLen-p1), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
610 | PM.check(PM.TRAP_BN_MOD_4);
611 | num.mod(mod);
612 | PM.check(PM.TRAP_BN_MOD_5);
613 | short len = num.copy_to_buffer(apdubuf, (short) 0);
614 | apdu.setOutgoingAndSend((short) 0, len);
615 | }
616 |
617 | void test_BN_ADD_MOD(APDU apdu, short dataLen) {
618 | byte[] apdubuf = apdu.getBuffer();
619 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
620 | short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF);
621 |
622 | PM.check(PM.TRAP_BN_ADD_MOD_1);
623 | Bignat num1 = m_testBN1;
624 | num1.set_size(p1);
625 | PM.check(PM.TRAP_BN_ADD_MOD_2);
626 | Bignat num2 = m_testBN2;
627 | num2.set_size(p2);
628 | PM.check(PM.TRAP_BN_ADD_MOD_3);
629 | Bignat mod = m_testBN3;
630 | mod.set_size((short) (dataLen - p1 - p2));
631 | PM.check(PM.TRAP_BN_ADD_MOD_4);
632 | num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
633 | num2.from_byte_array(p2, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
634 | PM.check(PM.TRAP_BN_ADD_MOD_5);
635 | mod.from_byte_array((short)(dataLen-p1-p2), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1+p2));
636 | PM.check(PM.TRAP_BN_ADD_MOD_6);
637 | num1.mod_add(num2, mod);
638 | PM.check(PM.TRAP_BN_ADD_MOD_7);
639 | short len = num1.copy_to_buffer(apdubuf, (short) 0);
640 | apdu.setOutgoingAndSend((short) 0, len);
641 | }
642 |
643 | void test_BN_SUB_MOD(APDU apdu, short dataLen) {
644 | byte[] apdubuf = apdu.getBuffer();
645 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
646 | short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF);
647 |
648 | PM.check(PM.TRAP_BN_SUB_MOD_1);
649 | Bignat num1 = m_testBN1;
650 | num1.set_size(p1);
651 | PM.check(PM.TRAP_BN_SUB_MOD_2);
652 | Bignat num2 = m_testBN2;
653 | num2.set_size(p2);
654 | PM.check(PM.TRAP_BN_SUB_MOD_3);
655 | Bignat mod = m_testBN3;
656 | mod.set_size((short) (dataLen - p1 - p2));
657 | PM.check(PM.TRAP_BN_SUB_MOD_4);
658 | num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
659 | num2.from_byte_array(p2, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
660 | mod.from_byte_array((short)(dataLen-p1-p2), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1+p2));
661 | PM.check(PM.TRAP_BN_SUB_MOD_5);
662 | num1.mod_sub(num2, mod);
663 | PM.check(PM.TRAP_BN_SUB_MOD_6);
664 | short len = num1.copy_to_buffer(apdubuf, (short) 0);
665 | apdu.setOutgoingAndSend((short) 0, len);
666 | }
667 |
668 | void test_BN_MUL_MOD(APDU apdu, short dataLen) {
669 | byte[] apdubuf = apdu.getBuffer();
670 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
671 | short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF);
672 |
673 | PM.check(PM.TRAP_BN_MUL_MOD_1);
674 | Bignat num1 = m_testBN1;
675 | num1.set_size(p1);
676 | PM.check(PM.TRAP_BN_MUL_MOD_2);
677 | Bignat num2 = m_testBN2;
678 | num2.set_size(p2);
679 | PM.check(PM.TRAP_BN_MUL_MOD_3);
680 | Bignat mod = m_testBN3;
681 | mod.set_size((short) (dataLen - p1 - p2));
682 | PM.check(PM.TRAP_BN_MUL_MOD_4);
683 | num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
684 | num2.from_byte_array(p2, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
685 | mod.from_byte_array((short)(dataLen-p1-p2), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1+p2));
686 | PM.check(PM.TRAP_BN_MUL_MOD_5);
687 | num1.mod_mult(num1, num2, mod);
688 | PM.check(PM.TRAP_BN_MUL_MOD_6);
689 | short len = num1.copy_to_buffer(apdubuf, (short) 0);
690 | apdu.setOutgoingAndSend((short) 0, len);
691 | }
692 |
693 | void test_BN_EXP_MOD(APDU apdu, short dataLen) {
694 | byte[] apdubuf = apdu.getBuffer();
695 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
696 | short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF);
697 |
698 | PM.check(PM.TRAP_BN_EXP_MOD_1);
699 | Bignat num1 = m_testBN1;
700 | num1.set_size(p1);
701 | PM.check(PM.TRAP_BN_EXP_MOD_2);
702 | Bignat num2 = m_testBN2;
703 | num2.set_size(p2);
704 | PM.check(PM.TRAP_BN_EXP_MOD_3);
705 | Bignat mod = m_testBN3;
706 | mod.set_size((short) (dataLen - p1 - p2));
707 | PM.check(PM.TRAP_BN_EXP_MOD_4);
708 | num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
709 | num2.from_byte_array(p2, (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
710 | mod.from_byte_array((short)(dataLen-p1-p2), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1+p2));
711 | PM.check(PM.TRAP_BN_EXP_MOD_5);
712 | num1.mod_exp(num2, mod);
713 | PM.check(PM.TRAP_BN_EXP_MOD_6);
714 | short len = num1.copy_to_buffer(apdubuf, (short) 0);
715 | apdu.setOutgoingAndSend((short) 0, len);
716 | }
717 |
718 | void test_BN_POW2_MOD(APDU apdu, short dataLen) {
719 | byte[] apdubuf = apdu.getBuffer();
720 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
721 | short p2 = (short) (apdubuf[ISO7816.OFFSET_P2] & 0x00FF);
722 |
723 | PM.check(PM.TRAP_BN_POW2_MOD_1);
724 | Bignat num1 = m_testBN1;
725 | num1.set_size(p1);
726 | Bignat mod = m_testBN3;
727 | mod.set_size((short) (dataLen - p1));
728 | num1.from_byte_array(p1, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
729 | mod.from_byte_array((short) (dataLen - p1), (short) 0, apdubuf, (short) (ISO7816.OFFSET_CDATA + p1));
730 | PM.check(PM.TRAP_BN_POW2_MOD_2);
731 | //num1.pow2Mod_RSATrick(mod);
732 | num1.mod_exp2(mod);
733 | PM.check(PM.TRAP_BN_POW2_MOD_3);
734 | short len = num1.copy_to_buffer(apdubuf, (short) 0);
735 | apdu.setOutgoingAndSend((short) 0, len);
736 | }
737 |
738 | void test_BN_INV_MOD(APDU apdu, short dataLen) {
739 | byte[] apdubuf = apdu.getBuffer();
740 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
741 |
742 | PM.check(PM.TRAP_BN_INV_MOD_1);
743 | Bignat num1 = m_testBN1;
744 | num1.set_size(p1);
745 | PM.check(PM.TRAP_BN_INV_MOD_2);
746 | Bignat mod = m_testBN2;
747 | mod.set_size((short) (dataLen - p1));
748 | PM.check(PM.TRAP_BN_INV_MOD_3);
749 | num1.from_byte_array(p1, (short)0, apdubuf, ISO7816.OFFSET_CDATA);
750 | mod.from_byte_array((short)(dataLen-p1), (short)0, apdubuf, (short)(ISO7816.OFFSET_CDATA+p1));
751 | PM.check(PM.TRAP_BN_INV_MOD_4);
752 | num1.mod_inv(mod);
753 | PM.check(PM.TRAP_BN_INV_MOD_5);
754 | short len = num1.copy_to_buffer(apdubuf, (short) 0);
755 | apdu.setOutgoingAndSend((short) 0, len);
756 | }
757 |
758 | void test_INT_STR(APDU apdu, short dataLen) {
759 | byte[] apdubuf = apdu.getBuffer();
760 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
761 |
762 | PM.check(PM.TRAP_INT_STR_1);
763 | //Integer num_int = new Integer(dataLen, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
764 | Integer num_int = m_testINT1;
765 | num_int.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, dataLen);
766 | PM.check(PM.TRAP_INT_STR_2);
767 | short len = num_int.toByteArray(apdubuf, (short) 0);
768 | apdu.setOutgoingAndSend((short) 0, len);
769 | }
770 |
771 | void test_INT_ADD(APDU apdu, short dataLen) {
772 | byte[] apdubuf = apdu.getBuffer();
773 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
774 |
775 | PM.check(PM.TRAP_INT_ADD_1);
776 | //Integer num_add_1 = new Integer(dataLen, (short) 0, apdubuf, ISO7816.OFFSET_CDATA);
777 | Integer num_add_1 = m_testINT1;
778 | num_add_1.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, p1);
779 | PM.check(PM.TRAP_INT_ADD_2);
780 | //Integer num_add_2 = new Integer((short) (dataLen - p1), (short) 0, apdubuf, (short) (ISO7816.OFFSET_CDATA + p1));
781 | Integer num_add_2 = m_testINT2;
782 | num_add_2.fromByteArray(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1), p1);
783 | PM.check(PM.TRAP_INT_ADD_3);
784 | num_add_1.add(num_add_2);
785 | PM.check(PM.TRAP_INT_ADD_4);
786 | short len = num_add_1.toByteArray(apdubuf, (short) 0);
787 | apdu.setOutgoingAndSend((short) 0, len);
788 | }
789 |
790 | void test_INT_SUB(APDU apdu, short dataLen) {
791 | byte[] apdubuf = apdu.getBuffer();
792 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
793 |
794 | PM.check(PM.TRAP_INT_SUB_1);
795 | Integer num_sub_1 = m_testINT1;
796 | num_sub_1.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, p1);
797 | Integer num_sub_2 = m_testINT2;
798 | num_sub_2.fromByteArray(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1), p1);
799 | PM.check(PM.TRAP_INT_SUB_2);
800 |
801 | num_sub_1.subtract(num_sub_2);
802 | PM.check(PM.TRAP_INT_SUB_3);
803 | short len = num_sub_1.toByteArray(apdubuf, (short) 0);
804 | apdu.setOutgoingAndSend((short) 0, len);
805 | }
806 |
807 | void test_INT_MUL(APDU apdu, short dataLen) {
808 | byte[] apdubuf = apdu.getBuffer();
809 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
810 |
811 | PM.check(PM.TRAP_INT_MUL_1);
812 | Integer num_mul_1 = m_testINT1;
813 | num_mul_1.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, p1);
814 | Integer num_mul_2 = m_testINT2;
815 | num_mul_2.fromByteArray(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1), p1);
816 | PM.check(PM.TRAP_INT_MUL_2);
817 |
818 | num_mul_1.multiply(num_mul_2);
819 | PM.check(PM.TRAP_INT_MUL_3);
820 | short len = num_mul_1.toByteArray(apdubuf, (short) 0);
821 | apdu.setOutgoingAndSend((short) 0, len);
822 | }
823 |
824 | void test_INT_DIV(APDU apdu, short dataLen) {
825 | byte[] apdubuf = apdu.getBuffer();
826 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
827 |
828 | PM.check(PM.TRAP_INT_DIV_1);
829 | Integer num_div_1 = m_testINT1;
830 | num_div_1.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, p1);
831 | Integer num_div_2 = m_testINT2;
832 | num_div_2.fromByteArray(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1), p1);
833 | PM.check(PM.TRAP_INT_DIV_2);
834 |
835 | num_div_1.divide(num_div_2);
836 | PM.check(PM.TRAP_INT_DIV_3);
837 |
838 | short len = num_div_1.toByteArray(apdubuf, (short) 0);
839 | apdu.setOutgoingAndSend((short) 0, len);
840 | }
841 |
842 | void test_INT_MOD(APDU apdu, short dataLen) {
843 | byte[] apdubuf = apdu.getBuffer();
844 | short p1 = (short) (apdubuf[ISO7816.OFFSET_P1] & 0x00FF);
845 |
846 | PM.check(PM.TRAP_INT_MOD_1);
847 | Integer num_mod_1 = m_testINT1;
848 | num_mod_1.fromByteArray(apdubuf, ISO7816.OFFSET_CDATA, p1);
849 | Integer num_mod_2 = m_testINT2;
850 | num_mod_2.fromByteArray(apdubuf, (short) (ISO7816.OFFSET_CDATA + p1), p1);
851 | PM.check(PM.TRAP_INT_MOD_2);
852 |
853 | num_mod_1.modulo(num_mod_2);
854 | PM.check(PM.TRAP_INT_MOD_3);
855 | short len = num_mod_1.toByteArray(apdubuf, (short) 0);
856 | apdu.setOutgoingAndSend((short) 0, len);
857 | }
858 | }
859 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_applet/PM.java:
--------------------------------------------------------------------------------
1 | package jcprofiler; // TODO: change to your applet package
2 |
3 | import javacard.framework.ISOException;
4 |
5 | /**
6 | * Utility class for performance profiling. Contains currently set trap stop and trap reaction method.
7 | * @author Petr Svenda
8 | */
9 | public class PM {
10 | public static short m_perfStop = -1; // Performace measurement stop indicator
11 |
12 | // if m_perfStop equals to stopCondition, exception is throws (trap hit)
13 | public static void check(short stopCondition) {
14 | if (PM.m_perfStop == stopCondition) {
15 | ISOException.throwIt(stopCondition);
16 | }
17 | }
18 |
19 | }
20 |
21 | !!! TODO: Move code below into your main applet class into process() method.
22 | If INS value 0xf5 is already taken, change it to any other, but don't forget
23 | to modify correspondingly also the value of JCProfiler_client.PerfTests.INS_PERF_SETTRAPID
24 | // ----- begin of code to be moved
25 | public final static byte INS_PERF_SETSTOP = (byte) 0xf5;
26 | case INS_PERF_SETSTOP:
27 | PM.m_perfStop = Util.makeShort(apdubuf[ISO7816.OFFSET_CDATA], apdubuf[(short) (ISO7816.OFFSET_CDATA + 1)]);
28 | break;
29 | // ----- end of code to be moved
30 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_applet/PMC.java:
--------------------------------------------------------------------------------
1 | package jcprofiler; // TODO: change to your applet package
2 |
3 | /**
4 | * Utility class for performance profiling constants
5 | * @author Petr Svenda
6 | */
7 | public class PMC {
8 | public static final short PERF_START = (short) 0x0001;
9 |
10 | public static final short TRAP_UNDEFINED = (short) 0xffff;
11 |
12 | //### PLACEHOLDER PMC CONSTANTS
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Builds, tests, and runs the project JCProfiler_client.
12 |
13 |
73 |
74 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/manifest.mf:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | X-COMMENT: Main-Class will be added automatically by build
3 |
4 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/nbproject/genfiles.properties:
--------------------------------------------------------------------------------
1 | build.xml.data.CRC32=f227f3f8
2 | build.xml.script.CRC32=8e215913
3 | build.xml.stylesheet.CRC32=8064a381@1.75.2.48
4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
6 | nbproject/build-impl.xml.data.CRC32=f227f3f8
7 | nbproject/build-impl.xml.script.CRC32=7e5f8c81
8 | nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
9 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/nbproject/project.properties:
--------------------------------------------------------------------------------
1 | annotation.processing.enabled=true
2 | annotation.processing.enabled.in.editor=false
3 | annotation.processing.processor.options=
4 | annotation.processing.processors.list=
5 | annotation.processing.run.all.processors=true
6 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
7 | build.classes.dir=${build.dir}/classes
8 | build.classes.excludes=**/*.java,**/*.form
9 | # This directory is removed when the project is cleaned:
10 | build.dir=build
11 | build.generated.dir=${build.dir}/generated
12 | build.generated.sources.dir=${build.dir}/generated-sources
13 | # Only compile against the classpath explicitly listed here:
14 | build.sysclasspath=ignore
15 | build.test.classes.dir=${build.dir}/test/classes
16 | build.test.results.dir=${build.dir}/test/results
17 | # Uncomment to specify the preferred debugger connection transport:
18 | #debug.transport=dt_socket
19 | debug.classpath=\
20 | ${run.classpath}
21 | debug.test.classpath=\
22 | ${run.test.classpath}
23 | # Files in build.classes.dir which should be excluded from distribution jar
24 | dist.archive.excludes=
25 | # This directory is removed when the project is cleaned:
26 | dist.dir=dist
27 | dist.jar=${dist.dir}/JCProfiler_client.jar
28 | dist.javadoc.dir=${dist.dir}/javadoc
29 | excludes=
30 | includes=**
31 | jar.compress=false
32 | javac.classpath=
33 | # Space-separated list of extra javac options
34 | javac.compilerargs=
35 | javac.deprecation=false
36 | javac.processorpath=\
37 | ${javac.classpath}
38 | javac.source=1.8
39 | javac.target=1.8
40 | javac.test.classpath=\
41 | ${javac.classpath}:\
42 | ${build.classes.dir}
43 | javac.test.processorpath=\
44 | ${javac.test.classpath}
45 | javadoc.additionalparam=
46 | javadoc.author=false
47 | javadoc.encoding=${source.encoding}
48 | javadoc.noindex=false
49 | javadoc.nonavbar=false
50 | javadoc.notree=false
51 | javadoc.private=false
52 | javadoc.splitindex=true
53 | javadoc.use=true
54 | javadoc.version=false
55 | javadoc.windowtitle=
56 | main.class=simpleapdu.JCProfiler_client
57 | manifest.file=manifest.mf
58 | meta.inf.dir=${src.dir}/META-INF
59 | mkdist.disabled=false
60 | platform.active=default_platform
61 | run.classpath=\
62 | ${javac.classpath}:\
63 | ${build.classes.dir}
64 | # Space-separated list of JVM arguments used when running the project.
65 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
66 | # To set system properties for unit tests define test-sys-prop.name=value:
67 | run.jvmargs=
68 | run.test.classpath=\
69 | ${javac.test.classpath}:\
70 | ${build.test.classes.dir}
71 | source.encoding=UTF-8
72 | src.dir=src
73 | test.src.dir=test
74 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/nbproject/project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.netbeans.modules.java.j2seproject
4 |
5 |
6 | JCProfiler_client
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/src/jcprofiler/CardManager.java:
--------------------------------------------------------------------------------
1 | package jcprofiler;
2 |
3 | import java.util.List;
4 | import javax.smartcardio.*;
5 |
6 | /**
7 | *
8 | * @author Petr Svenda
9 | */
10 | public class CardManager {
11 | CardTerminal m_terminal = null;
12 | CardChannel m_channel = null;
13 | Card m_card = null;
14 | Long m_lastTransmitTime = (long) 0;
15 |
16 | public final static byte OFFSET_CDATA = 5;
17 | public final static short SW_NO_ERROR = (short) 0x9000;
18 |
19 | public boolean ConnectToCard(byte[] appletAID) throws Exception {
20 | // Try all readers, connect to fisrt card
21 | List terminalList = GetReaderList();
22 |
23 | if (terminalList.isEmpty()) {
24 | System.out.println("No terminals found");
25 | }
26 |
27 | //List numbers of Card readers
28 | for (int i = 0; i < terminalList.size(); i++) {
29 | System.out.println(i + " : " + terminalList.get(i));
30 | m_terminal = (CardTerminal) terminalList.get(i);
31 | if (m_terminal.isCardPresent()) {
32 | m_card = m_terminal.connect("*");
33 | System.out.println("card: " + m_card);
34 | m_channel = m_card.getBasicChannel();
35 |
36 | //reset the card
37 | ATR atr = m_card.getATR();
38 | System.out.println(bytesToHex(m_card.getATR().getBytes()));
39 |
40 | System.out.println("Selecting applet...");
41 | CommandAPDU cmd = new CommandAPDU(0x00, 0xa4, 0x04, 0x00, appletAID);
42 | ResponseAPDU response = transmit(cmd);
43 |
44 | return true;
45 | }
46 | }
47 |
48 | return false;
49 | }
50 |
51 | public void DisconnectFromCard() throws Exception {
52 | if (m_card != null) {
53 | m_card.disconnect(false);
54 | m_card = null;
55 | }
56 | }
57 |
58 | public List GetReaderList() {
59 | try {
60 | TerminalFactory factory = TerminalFactory.getDefault();
61 | List readersList = factory.terminals().list();
62 | return readersList;
63 | } catch (Exception ex) {
64 | System.out.println("Exception : " + ex);
65 | return null;
66 | }
67 | }
68 |
69 | public ResponseAPDU transmit(CommandAPDU cmd) throws CardException {
70 | log(cmd);
71 |
72 | long elapsed = -System.currentTimeMillis();
73 | ResponseAPDU response = m_channel.transmit(cmd);
74 | elapsed += System.currentTimeMillis();
75 | m_lastTransmitTime = elapsed;
76 |
77 | log(response, m_lastTransmitTime);
78 |
79 | return response;
80 | }
81 |
82 | private void log(CommandAPDU cmd) {
83 | System.out.printf("--> %s\n", toHex(cmd.getBytes()),
84 | cmd.getBytes().length);
85 | }
86 |
87 | private void log(ResponseAPDU response, long time) {
88 | String swStr = String.format("%02X", response.getSW());
89 | byte[] data = response.getData();
90 | if (data.length > 0) {
91 | System.out.printf("<-- %s %s (%d) [%d ms]\n", toHex(data), swStr,
92 | data.length, time);
93 | } else {
94 | System.out.printf("<-- %s [%d ms]\n", swStr, time);
95 | }
96 | }
97 |
98 | public String byteToHex(byte data) {
99 | StringBuilder buf = new StringBuilder();
100 | buf.append(toHexChar((data >>> 4) & 0x0F));
101 | buf.append(toHexChar(data & 0x0F));
102 | return buf.toString();
103 | }
104 |
105 | public char toHexChar(int i) {
106 | if ((0 <= i) && (i <= 9)) {
107 | return (char) ('0' + i);
108 | } else {
109 | return (char) ('a' + (i - 10));
110 | }
111 | }
112 |
113 | public String bytesToHex(byte[] data) {
114 | StringBuilder buf = new StringBuilder();
115 | for (int i = 0; i < data.length; i++) {
116 | buf.append(byteToHex(data[i]));
117 | buf.append(" ");
118 | }
119 | return (buf.toString());
120 | }
121 |
122 | public static byte[] hexStringToByteArray(String s) {
123 | String sanitized = s.replace(" ", "");
124 | byte[] b = new byte[sanitized.length() / 2];
125 | for (int i = 0; i < b.length; i++) {
126 | int index = i * 2;
127 | int v = Integer.parseInt(sanitized.substring(index, index + 2), 16);
128 | b[i] = (byte) v;
129 | }
130 | return b;
131 | }
132 |
133 | public static String toHex(byte[] bytes) {
134 | return toHex(bytes, 0, bytes.length);
135 | }
136 |
137 | public static String toHex(byte[] bytes, int offset, int len) {
138 | String result = "";
139 |
140 | for (int i = offset; i < offset + len; i++) {
141 | result += String.format("%02X", bytes[i]);
142 | }
143 |
144 | return result;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/src/jcprofiler/JCProfiler_client.java:
--------------------------------------------------------------------------------
1 | package jcprofiler;
2 |
3 |
4 | /**
5 | * @author Petr Svenda
6 | */
7 | public class JCProfiler_client {
8 |
9 | public static void main(String[] args) {
10 | JCProfiler_client app = new JCProfiler_client();
11 | app.run(args);
12 | }
13 |
14 | private void run(String[] args) {
15 | System.out.println("JCProfiler v1.0 by OpenCryptoProject, 2017");
16 | try {
17 | PerfTests perfTests = new PerfTests();
18 | perfTests.RunPerformanceTests(1, true);
19 | } catch (Exception ex) {
20 | System.out.println("Exception : " + ex);
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/src/jcprofiler/PMC.java:
--------------------------------------------------------------------------------
1 | package jcprofiler;
2 |
3 | /**
4 | * Utility class for performance profiling constants
5 | * @author Petr Svenda
6 | */
7 | public class PMC {
8 | public static final short PERF_START = (short) 0x0001;
9 |
10 | public static final short TRAP_UNDEFINED = (short) 0xffff;
11 |
12 | //### PLACEHOLDER PMC CONSTANTS
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/demo/templates/template_profiler_client/src/jcprofiler/PerfTests.java:
--------------------------------------------------------------------------------
1 | package jcprofiler;
2 |
3 | import javafx.util.Pair;
4 |
5 | import javax.smartcardio.CardException;
6 | import javax.smartcardio.CommandAPDU;
7 | import javax.smartcardio.ResponseAPDU;
8 | import java.io.*;
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 |
12 | /**
13 | * @author Petr Svenda
14 | */
15 | public class PerfTests {
16 | final static byte[] APPLET_AID = {0x55, 0x6e, 0x69, 0x74, 0x54, 0x65, 0x73, 0x74, 0x73}; // TODO: fill your applet AID
17 | static final byte APPLET_CLA = (byte) 0xB0; // TODO: fill your applet_CLA
18 | static final byte[] APDU_TRIGGER = {APPLET_CLA, 0x40, 0, 0, 0}; // TODO: set proper APDU which will trigger the target operation
19 | static final byte[] APDU_CLEANUP = {APPLET_CLA, 0x03, 0, 0, 0}; // TODO: set proper on-card cleaning command (if necessary). Set to null if not necessary
20 | static final String CARD_NAME = "noCardNameGiven"; // TODO: fill name of your card;
21 |
22 | static final byte INS_PERF_SETTRAPID = (byte) 0xf5;
23 | static byte[] APDU_SETTRAPID = {APPLET_CLA, INS_PERF_SETTRAPID, 0, 0, 2, 0, 0};
24 | static final byte[] APDU_SETTRAPID_NONE = {APPLET_CLA, INS_PERF_SETTRAPID, 0, 0, 2, 0, 0};
25 |
26 | class PerfConfig {
27 | public String cardName = "noCardNameGiven";
28 | public FileOutputStream perfFile = null;
29 | public ArrayList> perfResultsSingleOp = new ArrayList<>();
30 | public ArrayList perfResultsSubparts = new ArrayList<>();
31 | public HashMap> perfResultsSubpartsRaw = new HashMap<>(); // hashmap with key being perf trap id, folowed by pair
32 | public boolean bMeasurePerf = true;
33 | public short[] perfStops = null;
34 | public short perfStopComplete = -1;
35 | public ArrayList failedPerfTraps = new ArrayList<>();
36 | }
37 |
38 | PerfTests() {
39 | buildPerfMapping();
40 | }
41 |
42 | void RunPerformanceTests(int numRepeats, boolean MODIFY_SOURCE_FILES_BY_PERF) throws Exception {
43 | PerfConfig cfg = new PerfConfig();
44 | String experimentID = String.format("%d", System.currentTimeMillis());
45 | cfg.perfFile = new FileOutputStream(String.format("OC_PERF_log_%s.csv", experimentID));
46 |
47 | try {
48 | CardManager cardMngr = new CardManager();
49 | System.out.println("Connecting to card...");
50 | cardMngr.ConnectToCard(APPLET_AID);
51 | System.out.println(" Done.");
52 |
53 | cardMngr.transmit(new CommandAPDU(APDU_SETTRAPID_NONE)); // erase any previous performance stop
54 | if (APDU_CLEANUP != null) { // reset if required
55 | cardMngr.transmit(new CommandAPDU(APDU_CLEANUP));
56 | }
57 |
58 | System.out.println("\n-------------- Performance profiling start --------------\n\n");
59 |
60 | //### PLACEHOLDER PERFTRAPS INIT
61 | for (int repeat = 0; repeat < numRepeats; repeat++) {
62 | CommandAPDU cmd = new CommandAPDU(APDU_TRIGGER);
63 | PerfAnalyzeCommand("insert nice name", cmd, cardMngr, cfg);
64 | }
65 |
66 | System.out.println("\n-------------- Performance profiling finished --------------\n\n");
67 | System.out.print("Disconnecting from card...");
68 | cardMngr.DisconnectFromCard();
69 | System.out.println(" Done.");
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 |
74 | if (cfg.failedPerfTraps.size() > 0) {
75 | System.out.println("#########################");
76 | System.out.println("!!! SOME PERFORMANCE TRAPS NOT REACHED !!!");
77 | System.out.println("#########################");
78 | for (String trap : cfg.failedPerfTraps) {
79 | System.out.println(trap);
80 | }
81 | } else {
82 | System.out.println("##########################");
83 | System.out.println("ALL PERFORMANCE TRAPS REACHED CORRECTLY");
84 | System.out.println("##########################");
85 | }
86 |
87 | // Save performance traps into single file
88 | String perfFileName = String.format("TRAP_RAW_%s.csv", experimentID);
89 | SavePerformanceResults(cfg.perfResultsSubpartsRaw, perfFileName);
90 |
91 | // If required, modification of source code files is attempted
92 | if (MODIFY_SOURCE_FILES_BY_PERF) {
93 | String dirPath = "..\\Profiler_applet\\";
94 | System.out.println(String.format("INFO: going to insert profiled info into files in '%s' directory", dirPath));
95 | InsertPerfInfoIntoFiles(dirPath, cfg.cardName, experimentID, cfg.perfResultsSubpartsRaw);
96 | }
97 | }
98 |
99 | static void SavePerformanceResults(HashMap> perfResultsSubpartsRaw, String fileName) throws FileNotFoundException, IOException {
100 | // Save performance traps into single file
101 | FileOutputStream perfLog = new FileOutputStream(fileName);
102 | String output = "trapID, previous trapID, time difference between trapID and previous trapID (ms)\n";
103 | perfLog.write(output.getBytes());
104 | for (Short perfID : perfResultsSubpartsRaw.keySet()) {
105 | output = String.format("%d, %d, %d\n", perfID, perfResultsSubpartsRaw.get(perfID).getKey(), perfResultsSubpartsRaw.get(perfID).getValue());
106 | perfLog.write(output.getBytes());
107 | }
108 | perfLog.close();
109 | }
110 |
111 | static void LoadPerformanceResults(String fileName, HashMap> perfResultsSubpartsRaw) throws FileNotFoundException, IOException {
112 | BufferedReader br = new BufferedReader(new FileReader(fileName));
113 | String strLine;
114 | while ((strLine = br.readLine()) != null) {
115 | if (strLine.contains("trapID,")) {
116 | // skip header line
117 | } else {
118 | String[] cols = strLine.split(",");
119 | Short perfID = Short.parseShort(cols[0].trim());
120 | Short prevPerfID = Short.parseShort(cols[1].trim());
121 | Long elapsed = Long.parseLong(cols[2].trim());
122 |
123 | perfResultsSubpartsRaw.put(perfID, new Pair(prevPerfID, elapsed));
124 | }
125 | }
126 | br.close();
127 | }
128 |
129 | public static byte[] shortToByteArray(int s) {
130 | return new byte[]{(byte) ((s & 0xFF00) >> 8), (byte) (s & 0x00FF)};
131 | }
132 |
133 | long PerfAnalyzeCommand(String operationName, CommandAPDU cmd, CardManager cardMngr, PerfConfig cfg) throws CardException, IOException {
134 | System.out.println(operationName);
135 | short prevPerfStop = PMC.PERF_START;
136 | long prevTransmitTime = 0;
137 | long lastFromPrevTime = 0;
138 | try {
139 | for (short trapID : cfg.perfStops) {
140 | System.arraycopy(shortToByteArray(trapID), 0, APDU_SETTRAPID, CardManager.OFFSET_CDATA, 2); // set required stop condition
141 | String operationNamePerf = String.format("%s_%s", operationName, getPerfStopName(trapID));
142 | cardMngr.transmit(new CommandAPDU(APDU_SETTRAPID)); // set performance trap
143 | ResponseAPDU response = cardMngr.transmit(cmd); // execute target operation
144 | boolean bFailedToReachTrap = false;
145 | if (trapID != cfg.perfStopComplete) { // Check expected error to be equal performance trap
146 | if (response.getSW() != (trapID & 0xffff)) {
147 | // we have not reached expected performance trap
148 | cfg.failedPerfTraps.add(getPerfStopName(trapID));
149 | bFailedToReachTrap = true;
150 | }
151 | }
152 | writePerfLog(operationNamePerf, response.getSW() == (CardManager.SW_NO_ERROR & 0xffff), cardMngr.m_lastTransmitTime, cfg.perfResultsSingleOp, cfg.perfFile);
153 | long fromPrevTime = cardMngr.m_lastTransmitTime - prevTransmitTime;
154 | if (bFailedToReachTrap) {
155 | cfg.perfResultsSubparts.add(String.format("[%s-%s], \tfailed to reach after %d ms (0x%x)", getPerfStopName(prevPerfStop), getPerfStopName(trapID), cardMngr.m_lastTransmitTime, response.getSW()));
156 | } else {
157 | cfg.perfResultsSubparts.add(String.format("[%s-%s], \t%d ms", getPerfStopName(prevPerfStop), getPerfStopName(trapID), fromPrevTime));
158 | cfg.perfResultsSubpartsRaw.put(trapID, new Pair(prevPerfStop, fromPrevTime));
159 | lastFromPrevTime = fromPrevTime;
160 | }
161 |
162 | prevPerfStop = trapID;
163 | prevTransmitTime = cardMngr.m_lastTransmitTime;
164 |
165 | if (APDU_CLEANUP != null) {
166 | cardMngr.transmit(new CommandAPDU(APDU_CLEANUP)); // free memory after command
167 | }
168 | }
169 | } catch (Exception e) {
170 | // Print what we have measured so far
171 | for (String res : cfg.perfResultsSubparts) {
172 | System.out.println(res);
173 | }
174 | throw e;
175 | }
176 | // Print measured performance info
177 | for (String res : cfg.perfResultsSubparts) {
178 | System.out.println(res);
179 | }
180 |
181 | return lastFromPrevTime;
182 | }
183 |
184 |
185 | static void writePerfLog(String operationName, boolean bResult, Long time, ArrayList> perfResults, FileOutputStream perfFile) throws IOException {
186 | perfResults.add(new Pair(operationName, time));
187 | perfFile.write(String.format("%s,%d,%s\n", operationName, time, bResult).getBytes());
188 | perfFile.flush();
189 | }
190 |
191 | static void InsertPerfInfoIntoFiles(String basePath, String cardName, String experimentID, HashMap> perfResultsSubpartsRaw) throws FileNotFoundException, IOException {
192 | File dir = new File(basePath);
193 | String[] filesArray = dir.list();
194 | if ((filesArray != null) && dir.isDirectory()) {
195 | // make subdir for results
196 | String outputDir = String.format("%s/perf/%s/", basePath, experimentID);
197 | new File(outputDir).mkdirs();
198 |
199 | for (String fileName : filesArray) {
200 | File dir2 = new File(basePath + fileName);
201 | if (!dir2.isDirectory()) {
202 | InsertPerfInfoIntoFile(String.format("%s/%s", basePath, fileName), cardName, experimentID, outputDir, perfResultsSubpartsRaw);
203 | }
204 | }
205 | }
206 | }
207 |
208 | static final String PERF_TRAP_CALL = "PM.check(PMC.";
209 | static final String PERF_TRAP_CALL_END = ");";
210 |
211 | static void InsertPerfInfoIntoFile(String filePath, String cardName, String experimentID, String outputDir, HashMap> perfResultsSubpartsRaw) throws FileNotFoundException, IOException {
212 | try {
213 | BufferedReader br = new BufferedReader(new FileReader(filePath));
214 | String basePath = filePath.substring(0, filePath.lastIndexOf("/"));
215 | String fileName = filePath.substring(filePath.lastIndexOf("/"));
216 |
217 | String fileNamePerf = String.format("%s/%s", outputDir, fileName);
218 | FileOutputStream fileOut = new FileOutputStream(fileNamePerf);
219 | String strLine;
220 | String resLine;
221 | // For every line of program try to find perfromance trap. If found and perf. is available, then insert comment into code
222 | while ((strLine = br.readLine()) != null) {
223 |
224 | if (strLine.contains(PERF_TRAP_CALL)) {
225 | int trapStart = strLine.indexOf(PERF_TRAP_CALL);
226 | int trapEnd = strLine.indexOf(PERF_TRAP_CALL_END);
227 | // We have perf. trap, now check if we also corresponding measurement
228 | String perfTrapName = (String) strLine.substring(trapStart + PERF_TRAP_CALL.length(), trapEnd);
229 | short perfID = getPerfStopFromName(perfTrapName);
230 |
231 | if (perfResultsSubpartsRaw.containsKey(perfID)) {
232 | // We have measurement for this trap, add into comment section
233 | resLine = String.format("%s // %d ms (%s,%s) %s", (String) strLine.substring(0, trapEnd + PERF_TRAP_CALL_END.length()), perfResultsSubpartsRaw.get(perfID).getValue(), cardName, experimentID, (String) strLine.subSequence(trapEnd + PERF_TRAP_CALL_END.length(), strLine.length()));
234 | } else {
235 | resLine = strLine;
236 | }
237 | } else {
238 | resLine = strLine;
239 | }
240 | resLine += "\n";
241 | fileOut.write(resLine.getBytes());
242 | }
243 |
244 | fileOut.close();
245 | } catch (Exception e) {
246 | System.out.println(String.format("Failed to transform file %s ", filePath) + e);
247 | }
248 | }
249 |
250 | public static HashMap PERF_TRAPS_MAPPING = new HashMap<>();
251 |
252 | public static void buildPerfMapping() {
253 | PERF_TRAPS_MAPPING.put(PMC.PERF_START, "PERF_START");
254 |
255 | //### PLACEHOLDER PMC MAPPINGS
256 |
257 | }
258 |
259 | public static String getPerfStopName(short stopID) {
260 | if (PERF_TRAPS_MAPPING.containsKey(stopID)) {
261 | return PERF_TRAPS_MAPPING.get(stopID);
262 | } else {
263 | assert (false);
264 | return "PERF_UNDEFINED";
265 | }
266 | }
267 |
268 | public static short getPerfStopFromName(String stopName) {
269 | for (Short stopID : PERF_TRAPS_MAPPING.keySet()) {
270 | if (PERF_TRAPS_MAPPING.get(stopID).equalsIgnoreCase(stopName)) {
271 | return stopID;
272 | }
273 | }
274 | assert (false);
275 | return PMC.TRAP_UNDEFINED;
276 | }
277 | }
278 |
--------------------------------------------------------------------------------
/dist/README.TXT:
--------------------------------------------------------------------------------
1 | ========================
2 | BUILD OUTPUT DESCRIPTION
3 | ========================
4 |
5 | When you build an Java application project that has a main class, the IDE
6 | automatically copies all of the JAR
7 | files on the projects classpath to your projects dist/lib folder. The IDE
8 | also adds each of the JAR files to the Class-Path element in the application
9 | JAR files manifest file (MANIFEST.MF).
10 |
11 | To run the project from the command line, go to the dist folder and
12 | type the following:
13 |
14 | java -jar "JCProfiler.jar"
15 |
16 | To distribute this project, zip up the dist folder (including the lib folder)
17 | and distribute the ZIP file.
18 |
19 | Notes:
20 |
21 | * If two JAR files on the project classpath have the same name, only the first
22 | JAR file is copied to the lib folder.
23 | * Only JAR files are copied to the lib folder.
24 | If the classpath contains other types of files or folders, these files (folders)
25 | are not copied.
26 | * If a library on the projects classpath also has a Class-Path element
27 | specified in the manifest,the content of the Class-Path element has to be on
28 | the projects runtime path.
29 | * To set a main class in a standard Java project, right-click the project node
30 | in the Projects window and choose Properties. Then click Run and enter the
31 | class name in the Main Class field. Alternatively, you can manually type the
32 | class name in the manifest Main-Class element.
33 |
--------------------------------------------------------------------------------
/lib/commons-cli-1.3.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenCryptoProject/JCProfiler/4a14775f67a4ccf4ee0a5c38d0a2ccb8c0eb70d4/lib/commons-cli-1.3.1.jar
--------------------------------------------------------------------------------
/nbproject/build-impl.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 | Must set src.dir
227 | Must set test.src.dir
228 | Must set build.dir
229 | Must set dist.dir
230 | Must set build.classes.dir
231 | Must set dist.javadoc.dir
232 | Must set build.test.classes.dir
233 | Must set build.test.results.dir
234 | Must set build.classes.excludes
235 | Must set dist.jar
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 | Must set javac.includes
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 | No tests executed.
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 | Must set JVM to use for profiling in profiler.info.jvm
716 | Must set profiler agent JVM arguments in profiler.info.jvmargs.agent
717 |
718 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 | Must select some files in the IDE or set javac.includes
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
992 |
993 |
994 | To run this application from the command line without Ant, try:
995 |
996 | java -jar "${dist.jar.resolved}"
997 |
998 |
999 |
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 |
1032 |
1033 |
1034 |
1035 |
1036 |
1037 |
1038 |
1039 |
1040 |
1041 |
1042 |
1043 | Must select one file in the IDE or set run.class
1044 |
1045 |
1046 |
1047 | Must select one file in the IDE or set run.class
1048 |
1049 |
1050 |
1055 |
1056 |
1057 |
1058 |
1059 |
1060 |
1061 |
1062 |
1063 |
1064 |
1065 |
1066 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1073 |
1074 | Must select one file in the IDE or set debug.class
1075 |
1076 |
1077 |
1078 |
1079 | Must select one file in the IDE or set debug.class
1080 |
1081 |
1082 |
1083 |
1084 | Must set fix.includes
1085 |
1086 |
1087 |
1088 |
1089 |
1090 |
1091 |
1096 |
1099 |
1100 | This target only works when run from inside the NetBeans IDE.
1101 |
1102 |
1103 |
1104 |
1105 |
1106 |
1107 |
1108 |
1109 | Must select one file in the IDE or set profile.class
1110 | This target only works when run from inside the NetBeans IDE.
1111 |
1112 |
1113 |
1114 |
1115 |
1116 |
1117 |
1118 |
1119 | This target only works when run from inside the NetBeans IDE.
1120 |
1121 |
1122 |
1123 |
1124 |
1125 |
1126 |
1127 |
1128 |
1129 |
1130 |
1131 |
1132 | This target only works when run from inside the NetBeans IDE.
1133 |
1134 |
1135 |
1136 |
1137 |
1138 |
1139 |
1140 |
1141 |
1142 |
1143 |
1144 |
1145 |
1146 |
1147 |
1148 |
1149 |
1150 |
1151 |
1152 |
1153 |
1154 |
1157 |
1158 |
1159 |
1160 |
1161 |
1162 |
1163 |
1164 |
1165 |
1166 |
1167 |
1168 |
1169 |
1170 | Must select one file in the IDE or set run.class
1171 |
1172 |
1173 |
1174 |
1175 |
1176 | Must select some files in the IDE or set test.includes
1177 |
1178 |
1179 |
1180 |
1181 | Must select one file in the IDE or set run.class
1182 |
1183 |
1184 |
1185 |
1186 | Must select one file in the IDE or set applet.url
1187 |
1188 |
1189 |
1190 |
1195 |
1196 |
1197 |
1198 |
1199 |
1200 |
1201 |
1202 |
1203 |
1204 |
1205 |
1206 |
1207 |
1208 |
1209 |
1210 |
1211 |
1212 |
1213 |
1214 |
1215 |
1216 |
1217 |
1218 |
1219 |
1220 |
1221 |
1222 |
1223 |
1224 |
1225 |
1226 |
1227 |
1228 |
1229 |
1230 |
1231 |
1232 |
1233 |
1234 |
1239 |
1240 |
1241 |
1242 |
1243 |
1244 |
1245 |
1246 |
1247 |
1248 |
1249 |
1250 |
1251 |
1252 |
1253 |
1254 |
1255 |
1256 |
1257 |
1258 |
1259 |
1260 |
1261 |
1262 |
1263 |
1264 |
1265 | Must select some files in the IDE or set javac.includes
1266 |
1267 |
1268 |
1269 |
1270 |
1271 |
1272 |
1273 |
1274 |
1275 |
1276 |
1277 |
1282 |
1283 |
1284 |
1285 |
1286 |
1287 |
1288 |
1289 | Some tests failed; see details above.
1290 |
1291 |
1292 |
1293 |
1294 |
1295 |
1296 |
1297 |
1298 | Must select some files in the IDE or set test.includes
1299 |
1300 |
1301 |
1302 | Some tests failed; see details above.
1303 |
1304 |
1305 |
1306 | Must select some files in the IDE or set test.class
1307 | Must select some method in the IDE or set test.method
1308 |
1309 |
1310 |
1311 | Some tests failed; see details above.
1312 |
1313 |
1314 |
1319 |
1320 | Must select one file in the IDE or set test.class
1321 |
1322 |
1323 |
1324 | Must select one file in the IDE or set test.class
1325 | Must select some method in the IDE or set test.method
1326 |
1327 |
1328 |
1329 |
1330 |
1331 |
1332 |
1333 |
1334 |
1335 |
1336 |
1337 |
1342 |
1343 | Must select one file in the IDE or set applet.url
1344 |
1345 |
1346 |
1347 |
1348 |
1349 |
1350 |
1355 |
1356 | Must select one file in the IDE or set applet.url
1357 |
1358 |
1359 |
1360 |
1361 |
1362 |
1363 |
1364 |
1369 |
1370 |
1371 |
1372 |
1373 |
1374 |
1375 |
1376 |
1377 |
1378 |
1379 |
1380 |
1381 |
1382 |
1383 |
1384 |
1385 |
1386 |
1387 |
1388 |
1389 |
1390 |
1391 |
1392 |
1393 |
1394 |
1395 |
1396 |
1397 |
1398 |
1399 |
1400 |
1401 |
1402 |
1403 |
1404 |
1405 |
1406 |
1407 |
1408 |
1409 |
1410 |
1411 |
1412 |
1413 |
1414 |
--------------------------------------------------------------------------------
/nbproject/genfiles.properties:
--------------------------------------------------------------------------------
1 | build.xml.data.CRC32=03c39f61
2 | build.xml.script.CRC32=4eeb9406
3 | build.xml.stylesheet.CRC32=8064a381@1.75.2.48
4 | # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
5 | # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
6 | nbproject/build-impl.xml.data.CRC32=03c39f61
7 | nbproject/build-impl.xml.script.CRC32=39761f8e
8 | nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
9 |
--------------------------------------------------------------------------------
/nbproject/project.properties:
--------------------------------------------------------------------------------
1 | annotation.processing.enabled=true
2 | annotation.processing.enabled.in.editor=false
3 | annotation.processing.processors.list=
4 | annotation.processing.run.all.processors=true
5 | annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
6 | application.title=JCProfiler
7 | application.vendor=petrs
8 | build.classes.dir=${build.dir}/classes
9 | build.classes.excludes=**/*.java,**/*.form
10 | # This directory is removed when the project is cleaned:
11 | build.dir=build
12 | build.generated.dir=${build.dir}/generated
13 | build.generated.sources.dir=${build.dir}/generated-sources
14 | # Only compile against the classpath explicitly listed here:
15 | build.sysclasspath=ignore
16 | build.test.classes.dir=${build.dir}/test/classes
17 | build.test.results.dir=${build.dir}/test/results
18 | # Uncomment to specify the preferred debugger connection transport:
19 | #debug.transport=dt_socket
20 | debug.classpath=\
21 | ${run.classpath}
22 | debug.test.classpath=\
23 | ${run.test.classpath}
24 | # Files in build.classes.dir which should be excluded from distribution jar
25 | dist.archive.excludes=
26 | # This directory is removed when the project is cleaned:
27 | dist.dir=dist
28 | dist.jar=${dist.dir}/JCProfiler.jar
29 | dist.javadoc.dir=${dist.dir}/javadoc
30 | endorsed.classpath=
31 | excludes=
32 | file.reference.commons-cli-1.3.1.jar=lib\\commons-cli-1.3.1.jar
33 | includes=**
34 | jar.compress=false
35 | javac.classpath=\
36 | ${file.reference.commons-cli-1.3.1.jar}
37 | # Space-separated list of extra javac options
38 | javac.compilerargs=
39 | javac.deprecation=false
40 | javac.processorpath=\
41 | ${javac.classpath}
42 | javac.source=1.8
43 | javac.target=1.8
44 | javac.test.classpath=\
45 | ${javac.classpath}:\
46 | ${build.classes.dir}
47 | javac.test.processorpath=\
48 | ${javac.test.classpath}
49 | javadoc.additionalparam=
50 | javadoc.author=false
51 | javadoc.encoding=${source.encoding}
52 | javadoc.noindex=false
53 | javadoc.nonavbar=false
54 | javadoc.notree=false
55 | javadoc.private=false
56 | javadoc.splitindex=true
57 | javadoc.use=true
58 | javadoc.version=false
59 | javadoc.windowtitle=
60 | main.class=opencryptoutils.JCProfiler
61 | manifest.file=manifest.mf
62 | meta.inf.dir=${src.dir}/META-INF
63 | mkdist.disabled=false
64 | platform.active=default_platform
65 | run.classpath=\
66 | ${javac.classpath}:\
67 | ${build.classes.dir}
68 | # Space-separated list of JVM arguments used when running the project.
69 | # You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
70 | # To set system properties for unit tests define test-sys-prop.name=value:
71 | run.jvmargs=
72 | run.test.classpath=\
73 | ${javac.test.classpath}:\
74 | ${build.test.classes.dir}
75 | source.encoding=UTF-8
76 | src.dir=src
77 | test.src.dir=test
78 |
--------------------------------------------------------------------------------
/nbproject/project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | org.netbeans.modules.java.j2seproject
4 |
5 |
6 | JCProfiler
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/opencryptoutils/JCProfiler.java:
--------------------------------------------------------------------------------
1 | package opencryptoutils;
2 |
3 | import java.io.IOException;
4 | import org.apache.commons.cli.*;
5 |
6 |
7 | /**
8 | *
9 | * @author Petr Svenda
10 | */
11 | public class JCProfiler {
12 | private Options opts = new Options();
13 | private static final String CLI_HEADER = "\nJCProfiler, a javacard profiler utility.\n\n";
14 | private static final String CLI_FOOTER = "\nMIT Licensed\nCopyright (c) 2017 Petr Svenda , OpenCryptoProject";
15 |
16 | public static void main(String[] args) {
17 | JCProfiler app = new JCProfiler();
18 | app.run(args);
19 | }
20 |
21 | /**
22 | * @param args the command line arguments
23 | */
24 | private void run(String[] args) {
25 | try {
26 | CommandLine cli = parseArgs(args);
27 |
28 | //if help, print and quit
29 | if (cli.hasOption("help")) {
30 | help();
31 | return;
32 | }
33 |
34 | if (cli.hasOption("setTraps")) {
35 | PerfCodeGenerator gen = new PerfCodeGenerator();
36 |
37 | String methodBaseName = cli.getOptionValue("methodBaseName", "EC_GEN");
38 | String startConstString = cli.getOptionValue("trapIDStartConst", "7770");
39 | short startTrapIDConst = Short.parseShort(startConstString, 16);
40 | PerfCodeConfig cfg = new PerfCodeConfig("not_set", methodBaseName, methodBaseName, 0, startTrapIDConst);
41 |
42 | String baseDir = cli.getOptionValue("baseDir", "");
43 | gen.generatePersonalizedProfiler(cfg, baseDir);
44 | }
45 | } catch (MissingArgumentException maex) {
46 | System.err.println("Option, " + maex.getOption().getOpt() + " requires an argument: " + maex.getOption().getArgName());
47 | } catch (NumberFormatException nfex) {
48 | System.err.println("Not a number. " + nfex.getMessage());
49 | } catch (ParseException | IOException ex) {
50 | System.err.println(ex.getMessage());
51 | } finally {
52 | }
53 | }
54 |
55 |
56 | /**
57 | * Parses command-line options.
58 | *
59 | * @param args cli arguments
60 | * @return parsed CommandLine object
61 | * @throws ParseException if there are any problems encountered while
62 | * parsing the command line tokens
63 | */
64 | private CommandLine parseArgs(String[] args) throws ParseException {
65 | /*
66 | * Actions:
67 | * -st / --setTraps
68 | *
69 | * Options:
70 | * -bd / --baseDir [base_directory]
71 | * -mbd / --methodBaseName [name]
72 | * -tsc / --trapIDStartConst [start_constant]
73 | *
74 | */
75 | OptionGroup actions = new OptionGroup();
76 | actions.setRequired(true);
77 | actions.addOption(Option.builder("h").longOpt("help").desc("Print help.").build());
78 | actions.addOption(Option.builder("st").longOpt("setTraps").desc("Parse input source code files, search for template performance traps and generates both card-side and client-side files for performance profiling.").build());
79 | opts.addOptionGroup(actions);
80 |
81 | opts.addOption(Option.builder("tsc").longOpt("trapIDStartConst").desc("Initial start value (short) for trapID constants.").hasArg().argName("start_constant").build());
82 | opts.addOption(Option.builder("bd").longOpt("baseDir").desc("Base directory with template files").hasArg().argName("base_directory").required(true).build());
83 | opts.addOption(Option.builder("mbd").longOpt("methodBaseName").desc("Base name of method to be profiled.").hasArg().argName("name").required(true).build());
84 |
85 | CommandLineParser parser = new DefaultParser();
86 | return parser.parse(opts, args);
87 | }
88 |
89 | /**
90 | * Prints help.
91 | */
92 | private void help() {
93 | HelpFormatter help = new HelpFormatter();
94 | help.setOptionComparator(null);
95 | help.printHelp("JCProfiler.jar", CLI_HEADER, opts, CLI_FOOTER, true);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/opencryptoutils/PerfCodeConfig.java:
--------------------------------------------------------------------------------
1 | package opencryptoutils;
2 |
3 | /**
4 | *
5 | * @author Petr Svenda
6 | */
7 | public class PerfCodeConfig {
8 |
9 | public String methodName;
10 | public String insBase;
11 | public String baseName;
12 | public String testName;
13 | public String apduCode;
14 | public int numStops;
15 | public int baseStopCode;
16 |
17 | PerfCodeConfig(String methodName, String insBase, String testName, int numStops, int baseStopCode) {
18 | this.methodName = methodName;
19 | this.insBase = insBase;
20 | this.baseName = String.format("TRAP_%s", insBase);
21 | this.apduCode = String.format("INS_%s", insBase);
22 | this.testName = testName;
23 | this.numStops = numStops;
24 | this.baseStopCode = baseStopCode;
25 | }
26 | PerfCodeConfig(PerfCodeConfig other) {
27 | this.methodName = other.methodName;
28 | this.insBase = other.insBase;
29 | this.baseName = other.baseName;
30 | this.apduCode = other.apduCode;
31 | this.testName = other.testName;
32 | this.numStops = other.numStops;
33 | this.baseStopCode = other.baseStopCode;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/opencryptoutils/PerfCodeGenerator.java:
--------------------------------------------------------------------------------
1 | package opencryptoutils;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.FileOutputStream;
7 | import java.io.FileReader;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.OutputStream;
11 | import java.nio.file.Files;
12 | import java.nio.file.NoSuchFileException;
13 | import static java.nio.file.StandardCopyOption.*;
14 | import java.util.ArrayList;
15 |
16 | /**
17 | *
18 | * @author Petr Svenda
19 | */
20 | public class PerfCodeGenerator {
21 | public final static int MAX_TRAPS_PER_METHOD = 16;
22 |
23 | void generatePerfStopStrings() {
24 | ArrayList testList = new ArrayList<>();
25 | /*
26 | testList.add(new PerfCodeConfig("EC_MUL", "EC scalar-point multiplication", 6, 0x7780));
27 |
28 | testList.add(new PerfCodeConfig("BN_STR", "BigNatural Storage", 3, 0x7740));
29 | testList.add(new PerfCodeConfig("BN_ADD", "BigNatural Addition", 7, 0x7730));
30 | testList.add(new PerfCodeConfig("BN_SUB", "BigNatural Subtraction", 7, 0x7720));
31 | testList.add(new PerfCodeConfig("BN_MUL", "BigNatural Multiplication", 6, 0x7710));
32 | testList.add(new PerfCodeConfig("BN_EXP", "BigNatural Exponentiation", 6, 0x7700));
33 | testList.add(new PerfCodeConfig("BN_MOD", "BigNatural Modulo", 5, 0x76f0));
34 | testList.add(new PerfCodeConfig("BN_ADD_MOD", "BigNatural Addition (Modulo)", 7, 0x76e0));
35 | testList.add(new PerfCodeConfig("BN_SUB_MOD", "BigNatural Subtraction (Modulo)", 6, 0x76d0));
36 | testList.add(new PerfCodeConfig("BN_MUL_MOD", "BigNatural Multiplication (Modulo)", 6, 0x76c0));
37 | testList.add(new PerfCodeConfig("BN_EXP_MOD", "BigNatural Exponentiation (Modulo)", 6, 0x76b0));
38 | testList.add(new PerfCodeConfig("BN_INV_MOD", "BigNatural Inversion (Modulo)", 5, 0x76a0));
39 |
40 | testList.add(new PerfCodeConfig("INT_STR", "Integer Storage", 2, 0x7690));
41 | testList.add(new PerfCodeConfig("INT_ADD", "Integer Addition", 4, 0x7680));
42 | testList.add(new PerfCodeConfig("INT_SUB", "Integer Subtraction", 4, 0x7670));
43 | testList.add(new PerfCodeConfig("INT_MUL", "Integer Multiplication", 4, 0x7660));
44 | testList.add(new PerfCodeConfig("INT_DIV", "Integer Division", 4, 0x7650));
45 | testList.add(new PerfCodeConfig("INT_EXP", "Integer Exponentiation", 4, 0x7640));
46 | testList.add(new PerfCodeConfig("INT_MOD", "Integer Modulo", 4, 0x7630));
47 |
48 | testList.add(new PerfCodeConfig("ECCURVE_NEWKEYPAIR", "ECCurve_newKeyPair", 7, 0x75f0));
49 | testList.add(new PerfCodeConfig("ECPOINT_ADD", "ECPoint_add", 7, 0x75e0));
50 | testList.add(new PerfCodeConfig("ECPOINT_MULT", "ECPoint_multiplication", 12, 0x75d0));
51 | */
52 | testList.add(new PerfCodeConfig("short multiplication_x(", "ECPOINT_MULT_X", "ECPoint_multiplication_x", 5, 0x75c0));
53 | testList.add(new PerfCodeConfig("void negate(", "ECPOINT_NEGATE", "ECPoint_negate", 5, 0x75b0));
54 |
55 | generatePerfStopStrings(testList);
56 | }
57 |
58 |
59 |
60 | void generatePerfStopStrings(ArrayList testList) {
61 |
62 | for (PerfCodeConfig item : testList) {
63 | generatePerfTrapsStrings_TrapIDs(item.baseName, item.numStops, item.baseStopCode);
64 | System.out.println();
65 | }
66 | System.out.println("\n ------------------ \n");
67 | for (PerfCodeConfig item : testList) {
68 | generatePerfTrapsStrings_Mappings(item.baseName, item.numStops);
69 | System.out.println();
70 | }
71 | System.out.println("\n ------------------ \n");
72 |
73 | for (PerfCodeConfig item : testList) {
74 | generatePerfTrapsStrings_InitList(item.baseName, item.testName, item.numStops);
75 | }
76 | System.out.println("\n ------------------ \n");
77 |
78 | }
79 |
80 | static String generatePerfTrapsStrings_TrapIDs(String baseName, int numStops, int baseOffset) {
81 | String result = String.format(" public static final short %s = (short) 0x%s;\n", baseName, Integer.toHexString(baseOffset));
82 | for (int i = 1; i <= numStops; i++) {
83 | result += String.format(" public static final short %s_%d = (short) (%s + %d);\n", baseName, i, baseName, i);
84 | }
85 | result += String.format(" public static final short %s_COMPLETE = %s;\n", baseName, baseName);
86 |
87 | return result;
88 | }
89 |
90 | static String generatePerfTrapsStrings_Mappings(String baseName, int numStops) {
91 | String indent = " ";
92 | String result = "";
93 | for (int i = 1; i <= numStops; i++) {
94 | result += String.format("%sPERF_TRAPS_MAPPING.put(PMC.%s_%d, \"%s_%d\");\n", indent, baseName, i, baseName, i);
95 | }
96 | result += String.format("%sPERF_TRAPS_MAPPING.put(PMC.%s_COMPLETE, \"%s_COMPLETE\");\n", indent, baseName, baseName);
97 |
98 | return result;
99 | }
100 |
101 | static String generatePerfTrapsStrings_InitList(String baseName, String testName, int numStops) {
102 | String indent = " ";
103 | String sanitizedTestName = testName.replace(" ", "_").replace("(", "_").replace(")", "_");
104 | String result = String.format("%sshort[] PERFTRAPS_%s = {", indent, sanitizedTestName);
105 | for (int i = 1; i <= numStops; i++) {
106 | result += String.format("PMC.%s_%d, ", baseName, i);
107 | }
108 | result += String.format("PMC.%s_COMPLETE};\n", baseName);
109 | result += String.format("%scfg.perfStops = PERFTRAPS_%s;\n", indent, sanitizedTestName);
110 | result += String.format("%scfg.perfStopComplete = PMC.%s_COMPLETE;", indent, baseName);
111 |
112 | return result;
113 | }
114 |
115 | void insertPerfTraps(PerfCodeConfig cfg, String filePath) {
116 | try {
117 | BufferedReader br = new BufferedReader(new FileReader(filePath));
118 | String filePathTransform = filePath + ".perf";
119 |
120 | FileOutputStream fileOut = new FileOutputStream(filePathTransform);
121 | String strLine;
122 | String perfTrapLine = String.format("PerfMeasure.check(PerfMeasure.PERF_TEST_%s_0);\n", cfg.insBase);
123 | boolean bInsideTargetFunction = false;
124 | String methodNameEnd = String.format("end %s", cfg.methodName);
125 |
126 | // For every line of program insert generic performance trap
127 | while ((strLine = br.readLine()) != null) {
128 | if (bInsideTargetFunction) {
129 | if (strLine.contains(methodNameEnd)) {
130 | bInsideTargetFunction = false;
131 | }
132 | String strLineTrim = strLine.trim();
133 | if (strLineTrim.length() > 0) {
134 | int indentCount = strLine.indexOf(strLineTrim);
135 | String indent = strLine.substring(0, indentCount);
136 | // non-zero line detected, insert perf trap with proper indentation
137 | fileOut.write(indent.getBytes());
138 | fileOut.write(perfTrapLine.getBytes());
139 | }
140 | }
141 | else {
142 | if (strLine.contains(cfg.methodName)) {
143 | bInsideTargetFunction = true;
144 | }
145 | }
146 | // Insert original line (always)
147 | strLine += "\n";
148 | fileOut.write(strLine.getBytes());
149 | }
150 |
151 | br.close();
152 | fileOut.close();
153 | } catch (Exception e) {
154 | System.out.println(String.format("Failed to transform file %s ", filePath) + e);
155 | }
156 | }
157 |
158 | void generatePersonalizedProfiler(PerfCodeConfig baseCfg, String baseDirectory) throws IOException {
159 | ArrayList filesWithTraps = new ArrayList<>();
160 |
161 | //
162 | // Process all input files, try to find performance trap template and transform files with relevant traps
163 | //
164 | // make subdir for results
165 | String outputDirApplet = String.format("%s/target/profiler_applet/", baseDirectory);
166 | new File(outputDirApplet).mkdirs();
167 | String outputDirClient = String.format("%s/target/profiler_client/", baseDirectory);
168 | new File(outputDirClient).mkdirs();
169 | String baseAppletFilesDir = String.format("%s/templates/input_applet_files/", baseDirectory);
170 | File dir = new File(baseAppletFilesDir);
171 | String[] filesArray = dir.list();
172 | if ((filesArray != null) && (dir.isDirectory() == true)) {
173 |
174 | for (String fileName : filesArray) {
175 | String filePath = baseAppletFilesDir + fileName;
176 | File inputFile = new File(filePath);
177 | if (!inputFile.isDirectory()) {
178 | // Copy file from templates to target
179 | String targetFilePathOrig = outputDirApplet + fileName + ".orig";
180 | String targetFilePath = outputDirApplet + fileName;
181 | Files.copy(inputFile.toPath(), (new File(targetFilePathOrig)).toPath(), REPLACE_EXISTING);
182 |
183 | PerfCodeConfig cfg = new PerfCodeConfig(baseCfg);
184 | if (enumeratePerfTrapsFile(cfg, targetFilePathOrig, targetFilePath)) {
185 | filesWithTraps.add(cfg);
186 | }
187 | }
188 | }
189 | }
190 |
191 | //
192 | // Generate helper files for card-side profiler application
193 | //
194 | String templateAppletDir = String.format("%s/templates/template_profiler_applet/", baseDirectory);
195 | copy(new File(templateAppletDir), new File(outputDirApplet));
196 | personalizeTemplatesApplet(filesWithTraps, outputDirApplet); //=> PM, PMC
197 |
198 | //
199 | // Generate helper files for client-side profiler application
200 | //
201 | String templateClientDir = String.format("%s/templates/template_profiler_client/", baseDirectory);
202 | copy(new File(templateClientDir), new File(outputDirClient));
203 | ArrayList filesToCopy = new ArrayList<>();
204 | filesToCopy.add(String.format("%s/PMC.java", outputDirApplet));
205 | personalizeTemplatesClient(filesWithTraps, outputDirClient, filesToCopy); // JCProfiler_client
206 |
207 |
208 | System.out.println("\n\n#########################################");
209 | System.out.println(String.format("INFO: The personalized profiler generation is now finished."));
210 | System.out.println(String.format("Directory '%s' contains your applet's transformed files with numbered performance traps.\nNow you need to:", outputDirApplet));
211 | System.out.println("1. Copy applet files (together with PMC.java and PM.java) back to your applet structure.");
212 | System.out.println("2. Open PM.java and PMC.java and update package to your applet's package name.");
213 | System.out.println("3. Open PM.java and *move* specified part of code (INS_PERF_SETSTOP) at the end of file to process() method of your applet.");
214 | System.out.println("4. Convert your applet and upload to target card as usual.");
215 | System.out.println();
216 | System.out.println(String.format("Directory '%s' contains client-side code of the profiler.\nNow you need to:", outputDirClient));
217 | System.out.println("1. Open PerfTests.java and correct APPLET_CLA, APPLET_AID according to your applet.");
218 | System.out.println("2. Open PerfTests.java and set proper apdu APDU_TRIGGER which will trigger (let execute) the method you like to profile (method which now have 'PM.check(PMC.TRAP_' inserted).");
219 | System.out.println("3. (Optional) Set CARD_NAME to sensible string. If APDU_CLEANUP is set, this apdu is send to card after every measurement command (for 'cleaning').");
220 | System.out.println("4. Compile and run JCProfiler_client. Measurement apdu commands are send to card and resulting measurements are inserted as comment directly behind the correspoding performance trap.");
221 | System.out.println(String.format("5. Inspect console results and modified files which are copied into directory '%s/perf/unique_experiment_id'.", outputDirApplet));
222 | System.out.println();
223 |
224 |
225 | }
226 |
227 | void personalizeTemplatesApplet(ArrayList filesWithTraps, String outputDirApplet) throws IOException {
228 | //
229 | // Personalize PMC.java
230 | //
231 | String PLACEHOLDER_PMC_CONSTANTS = "//### PLACEHOLDER PMC CONSTANTS";
232 | String result = "";
233 | for (PerfCodeConfig item : filesWithTraps) {
234 | result += generatePerfTrapsStrings_TrapIDs(item.baseName, item.numStops, item.baseStopCode);
235 | }
236 | String inputFilePath = String.format("%sPMC.java", outputDirApplet);
237 | System.out.println(String.format("INFO: Transforming file '%s' for trapID constants.", inputFilePath));
238 | replaceStringInCopiedFile(inputFilePath, PLACEHOLDER_PMC_CONSTANTS, result, true);
239 | }
240 |
241 | void deleteFileNoExcept(String filePath) {
242 | try {
243 | Files.delete(new File(filePath).toPath());
244 | }
245 | catch (NoSuchFileException ignored) {}
246 | catch (IOException ignored) {}
247 | }
248 |
249 | void personalizeTemplatesClient(ArrayList filesWithTraps, String outputDirClient, ArrayList filesToCopy) throws IOException {
250 | //
251 | // Personalize PerfTests.java
252 | //
253 | String resultPerfTrapInit = "";
254 | String resultPerfTrapMappings = "";
255 | for (PerfCodeConfig item : filesWithTraps) {
256 | resultPerfTrapInit += generatePerfTrapsStrings_InitList(item.baseName, item.testName, item.numStops);
257 | resultPerfTrapMappings += generatePerfTrapsStrings_Mappings(item.baseName, item.numStops);
258 | }
259 | String inputFilePath = String.format("%ssrc/jcprofiler/PerfTests.java", outputDirClient);
260 |
261 | System.out.println(String.format("INFO: Transforming file '%s' for code with trapID to send.", inputFilePath));
262 | String PLACEHOLDER_PERFTRAPS_INIT = "//### PLACEHOLDER PERFTRAPS INIT";
263 | replaceStringInCopiedFile(inputFilePath, PLACEHOLDER_PERFTRAPS_INIT, resultPerfTrapInit, true);
264 |
265 | System.out.println(String.format("INFO: Transforming file '%s' for code with mapping between name and trapID.", inputFilePath));
266 | String PLACEHOLDER_PMC_MAPPINGS = "//### PLACEHOLDER PMC MAPPINGS";
267 | replaceStringInCopiedFile(inputFilePath, PLACEHOLDER_PMC_MAPPINGS, resultPerfTrapMappings, true);
268 |
269 | //
270 | // Copy required personalized files from applet into client (constants etc.)
271 | //
272 | for (String fileToCopy : filesToCopy) {
273 | File file = new File(fileToCopy);
274 | String localPath = String.format("%s/src/jcprofiler/%s", outputDirClient, file.getName());
275 | copy(new File(fileToCopy), new File(localPath));
276 | }
277 | }
278 |
279 | boolean enumeratePerfTrapsFile(PerfCodeConfig cfg, String inputFilePath, String outputFilePath) {
280 | boolean bSomeTrapFound = false;
281 | System.out.println(String.format("INFO: Processing file '%s'", inputFilePath));
282 |
283 | try {
284 | BufferedReader br = new BufferedReader(new FileReader(inputFilePath));
285 | String filePathTransform = outputFilePath;
286 | FileOutputStream fileOut = new FileOutputStream(filePathTransform);
287 | String strLine;
288 | String perfTrapLineTemplate = String.format("PM.check(PMC.TRAP_%s_0);", cfg.insBase);
289 | String perfTrapCounterTemplate = String.format("%s_0", cfg.insBase);
290 | int perfTrapCount = 1;
291 |
292 | // For every line of program insert generic performance trap
293 | while ((strLine = br.readLine()) != null) {
294 | if (strLine.contains(perfTrapLineTemplate)) {
295 | bSomeTrapFound = true; // We found at least one trap!
296 |
297 | // Replace by trap with counter
298 | String perfTrapCounter = String.format("%s_%d", cfg.insBase, perfTrapCount);
299 | perfTrapCount++;
300 | if (perfTrapCount > MAX_TRAPS_PER_METHOD) {
301 | System.out.println(" Too much traps templates found - try to decrease below " + MAX_TRAPS_PER_METHOD);
302 | }
303 |
304 | strLine = strLine.replaceFirst(perfTrapCounterTemplate, perfTrapCounter);
305 |
306 | }
307 | // Insert original or modified final line
308 | strLine += "\n";
309 | fileOut.write(strLine.getBytes());
310 | }
311 |
312 | br.close();
313 | fileOut.close();
314 |
315 | if (!bSomeTrapFound) {
316 | System.out.println(String.format(" No template performance traps found in file '%s'", inputFilePath));
317 | }
318 | else {
319 | System.out.println(String.format(" OK: Total '%d' traps found in file '%s'", perfTrapCount, inputFilePath));
320 | }
321 |
322 | cfg.numStops = perfTrapCount - 1;
323 | } catch (Exception e) {
324 | System.out.println(String.format("Failed to transform file %s ", inputFilePath) + e);
325 | }
326 |
327 | return bSomeTrapFound;
328 | }
329 |
330 | boolean replaceStringInCopiedFile(String targetFilePath, String stringToFind, String stringReplace, boolean bLeaveFind) {
331 | boolean bReplacePerformed = false;
332 | try {
333 | String inputFilePathTmp = String.format("%s.tmp", targetFilePath);
334 | // make local copy
335 | deleteFileNoExcept(inputFilePathTmp);
336 | new File(targetFilePath).renameTo(new File(inputFilePathTmp));
337 |
338 | // Transform file
339 | BufferedReader br = new BufferedReader(new FileReader(inputFilePathTmp));
340 | FileOutputStream fileOut = new FileOutputStream(targetFilePath);
341 | String strLine;
342 |
343 | while ((strLine = br.readLine()) != null) {
344 | if (strLine.contains(stringToFind)) {
345 | if (bLeaveFind) {
346 | strLine = strLine.replaceFirst(stringToFind, String.format("%s\n\n%s", stringToFind, stringReplace));
347 | }
348 | else {
349 | strLine = strLine.replaceFirst(stringToFind, stringReplace);
350 | }
351 | bReplacePerformed = true;
352 | }
353 | // Insert original or modified final line
354 | strLine += "\n";
355 | fileOut.write(strLine.getBytes());
356 | }
357 | br.close();
358 | fileOut.close();
359 |
360 | // Delete temp file
361 | deleteFileNoExcept(inputFilePathTmp);
362 |
363 | } catch (Exception e) {
364 | System.out.println(String.format(" Failed to transform file '%s' ", targetFilePath) + e);
365 | }
366 |
367 | if (!bReplacePerformed) {
368 | System.out.println(String.format(" Problem: no occurence of '%s' in file '%s'", stringToFind, targetFilePath));
369 | }
370 | else {
371 | System.out.println(String.format(" OK: '%s' found and replaced", stringToFind));
372 | }
373 |
374 | return bReplacePerformed;
375 | }
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 | public void copy(File sourceLocation, File targetLocation) throws IOException {
385 | if (sourceLocation.isDirectory()) {
386 | copyDirectory(sourceLocation, targetLocation);
387 | } else {
388 | copyFile(sourceLocation, targetLocation);
389 | }
390 | }
391 |
392 | private void copyDirectory(File source, File target) throws IOException {
393 | if (!target.exists()) {
394 | target.mkdir();
395 | }
396 |
397 | for (String f : source.list()) {
398 | copy(new File(source, f), new File(target, f));
399 | }
400 | }
401 |
402 | private void copyFile(File source, File target) throws IOException {
403 | try (
404 | InputStream in = new FileInputStream(source);
405 | OutputStream out = new FileOutputStream(target)) {
406 | byte[] buf = new byte[1024];
407 | int length;
408 | while ((length = in.read(buf)) > 0) {
409 | out.write(buf, 0, length);
410 | }
411 | }
412 | }
413 | }
414 |
--------------------------------------------------------------------------------