I need to load a simple applet to my USIM card. Authentication is OK.
I'm using OTA SMS-DELIVER via SmartCard to install CAP file.
Using these:
https://github.com/simhacks/hello-stk.git
https://github.com/martinpaljak/ant-javacard
I couldnt find the right spec explaining "C482XXYY" in Header.cap, how it should be calculated,
this answer below helped me navigate, but for Method.cap loading - it still fails
https://community.oracle.com/tech/developers/discussion/1753814/globalpaltform-load-command-data-field
I've written this loader:
https://pastebin.com/pSXeDYyS
Every component in CAP file is in separate APDU with LOAD instruction.
First 5 is loaded successfully with DATA=00, SW=9000, however on Method it fails.
As you can see from my script, I've fixed Descriptor size to 0000 in Directory field.
And in Header C482xxyy, where xxyy is calculated properly, which is a sum of
all size fields in Directory, e.g.
016a = 0011+001f+000c+001e+0042+0018+006d+0032+0017+0000+0000
Question: Can't figure out why Method LOAD fails? By checking GP 2.1 spec, it doesnt
help me understand the problem. Concatenated components to < 255 block size also fails,
only separate components work for LOAD.
[+] Install for load
>> 80e602001207d07002ca449001000006ef04c60201850000c0000000
<< 009000
[+] LOAD - Header
>> 80e8000018c482016a010011decaffed010204000107d07002ca44900100c0000000
<< 009000
[+] LOAD - Directory
>> 80e800012202001f0011001f000c001e00420018006d003200170000000000040002002202010000c0000000
<< 009000
[+] LOAD - Import
>> 80e800022104001e02000107a0000000620101060210a0000000090003ffffffff891071000200c0000000
<< 009000
[+] LOAD - Applet
>> 80e800030f03000c0108d07002ca44900101002000c0000000
<< 009000
[+] LOAD - Class
>> 80e800041b06001843800301ff0007020000002f00398002008101010881000000c0000000
<< 009000
[!!!!] LOAD - Method (FAILED)
>> 80e800057007006d000911188c00048d00012c18197b0002037b00029210240303038b000388007a02318f00053d8c00062e1b8b00077a0120188b000860037a7a02228d00092d1d10076b101a8b000a321fae006b06188c000b7a06118d000c2c1903077b000d037b000d928b000e198b000f3b7a00c0000000
<< 9000 (should be 009000)
[-] LOAD - StaticField (FAILED due to last failed LOAD)
>> 80e80006350800.....
<< 6A86 (because prev. p2=05 is not loaded)
Applet source code:
package com.github.mrlnc.HelloSTK2;
import javacard.framework.*;
import sim.toolkit.*;
/*
Originally from: https://git.osmocom.org/sim/hello-stk/tree/hello-stk/src/org/toorcamp/HelloSTK/HelloSTK.java
*/
public class HelloSTK2 extends Applet implements ToolkitInterface, ToolkitConstants {
// DON'T DECLARE USELESS INSTANCE VARIABLES! They get saved to the EEPROM,
// which has a limited number of write cycles.
private byte helloMenuItem;
private HelloSTK2() {
// This is the interface to the STK applet registry (which is separate
// from the JavaCard applet registry!)
ToolkitRegistry reg = ToolkitRegistry.getEntry();
byte[] menuItemText = new byte[] { 'H', 'e', 'l', 'l', 'o'};
// Define the applet Menu Entry
helloMenuItem = reg.initMenuEntry(menuItemText, (short)0, (short)menuItemText.length,
PRO_CMD_SELECT_ITEM, false, (byte)0, (short)0);
}
// This method is called by the card when the applet is installed. You must
// instantiate your applet and register it here.
public static void install(byte[] bArray, short bOffset, byte bLength) {
HelloSTK2 applet = new HelloSTK2();
applet.register();
}
// This processes APDUs sent directly to the applet. For STK applets, this
// interface isn't really used.
public void process(APDU arg0) throws ISOException {
// ignore the applet select command dispached to the process
if (selectingApplet())
return;
}
// This processes STK events.
public void processToolkit(byte event) throws ToolkitException {
EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();
if (event == EVENT_MENU_SELECTION) {
byte selectedItemId = envHdlr.getItemIdentifier();
if (selectedItemId == helloMenuItem) {
byte[] welcomeMsg = new byte[] { 'W', 'e', 'l', 'c', 'o', 'm', 'e' };
ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
proHdlr.initDisplayText((byte)0, DCS_8_BIT_DATA, welcomeMsg, (short)0,
(short)(welcomeMsg.length));
proHdlr.send();
}
}
}
}
UPDATE:
Raw CAP bytes in order (Header, Directory, Import, Applet, Class, Method, StaticField, ConstantPool, RefLocation, Descriptor)
['01000fdecaffed010204000105d07002ca44',
'02001f000f001f000c00280036001800aa000a001200000003000000000000030100', '04002803030107a0000000620101060210a0000000090003ffffffff8910710002000107a0000000620001',
'03000c0108d07002ca449001010039',
'06001843800301ff00070200000048005280020081010108810000', '0700aa000912188c00038d00012c08900b3d031048383d041065383d05106c383d06106c383d07106f382d18191a031a9210240303038b000288007a02318f00043d8c00052e1b8b00067a0120188b000760037a7a06248d00082d1d10076b4e1a8b0009321fae006b441007900b3d031057383d041065383d05106c383d061063383d07106f383d08106d383d100610653828048d000a2805150503071504031504928b000b15058b000c3b7a',
'08000a00000000000000000000', '050036000d02000000068109000381090b0680030001000000060000010380030103800303068108000381080c06810a0003810a1303810a16',
'0900120002372d000c05032c08040507090a330f05',
'0b0003000000']
UPDATE 2:
I'm sending via ENVELOPE commands. KIC1,KID1 encryptions are used. They work with RFM and some RAM commands like GET STATUS etc. Here is the code for INSTALL (for load) command:
def install_for_load(self, caps, exe_aid):
# 11.5.2.3.7 INSTALL Command Parameters, page 174
cap_data = "".join(caps)
apdu = "".join([
"80", # CLS
"e6", # INSTR
"02", # p1 0b000000_1_0 ; for load
"00", # p2
"%02x", # p3 ; Lc
])
# sec_aid = "a000000003000000" # GP211 Security Domain AID
data = "".join([
"%02x" % int(len(exe_aid)/2),
exe_aid,
"00", # security domain aid (same domain)
# "%02x" % int(len(sec_aid)/2), # security domain aid (same domain)
# sec_aid,
"00", # load file data block hash
"%02x", # load params length
])
load_params_tl = "".join([
"ef", # Load Parameters: System Specific Parameters tag
"%02x", # length of load_params
])
load_params_v = "".join([
"c6", # Non-volatile code Minimum Memory requirement. load params (mandatory)
"02", # length
"%04x" % int(len(cap_data)/2), # code size HelloSTK2.cap size.
# "c7", # volatile data minimum memory required (ram) - optional
# "02", # length
# "00ff",
# "c8", # non-volatile data minimum memory required - optional
# "02",
# "00ff"
])
load_params = load_params_tl % int(len(load_params_v)/2) + load_params_v
data = data % int(len(load_params)/2) + load_params
data += "00" # load token
apdu = apdu % int(len(data)/2) + data
apdu += "00c0000000" # C-MAC + Le
return apdu
You can have a look into the GlobalPlatform project loader.
It is LPGL, so directly using it as C code in other non LGPL projects is not possible.
[!!!!] LOAD - Method (FAILED)
80e800057007006d000911188c00048d00012c18197b0002037b00029210240303038b000388007a02318f00053d8c00062e1b8b00077a0120188b000860037a7a02228d00092d1d10076b101a8b000a321fae006b06188c000b7a06118d000c2c1903077b000d037b000d928b000e198b000f3b7a00c0000000
<< 9000 (should be 009000)
I assume that the log is the unwrapped logged before the commands are prepared for SCP80. A response of 9000 in OTA means usually "I received the command, but I don't know what to do with it". Is this 9000 command from the ENVELOPE response on the card? Are you sending the data over an SMPP connection?
Can you try your loading code with a simple HelloWorld Applet without any STK? It could be that your card is not supporting a version you are linking against, e.g. different ETSI releases. Then some method might not be supported and the loading fails.
When I run gatsby build I get this error:
failed Building static HTML for pages - 10.179s
ERROR #95313
Building static HTML failed
See our docs page for more info on this error: https://gatsby.dev/debug-html
343 | for (c = []; b < a; ++b) {
344 | for (var n = 0; n < m; ++n) {
> 345 | c[v++] = Z(d[n] + ' ', h[b], e).trim();
| ^
346 | }
347 | }
348 |
WebpackError: The module '/node_modules/canvas/build/Release/canvas.node'
- stylis.esm.js:345
node_modules/#emotion/stylis/dist/stylis.esm.js:345:1
- stylis.esm.js:151
node_modules/#emotion/stylis/dist/stylis.esm.js:151:1
- stylis.esm.js:175
node_modules/#emotion/stylis/dist/stylis.esm.js:175:1
- stylis.esm.js:286
node_modules/#emotion/stylis/dist/stylis.esm.js:286:1
- stylis.esm.js:151
node_modules/#emotion/stylis/dist/stylis.esm.js:151:1
- stylis.esm.js:175
node_modules/#emotion/stylis/dist/stylis.esm.js:175:1
- stylis.esm.js:286
node_modules/#emotion/stylis/dist/stylis.esm.js:286:1
- stylis.esm.js:151
How to solve? When run gatsby develop there is no error.
Update gatsby-config.js to contain the plugin gatsby-plugin-emotion:
module.exports = {
plugins: [
`gatsby-plugin-emotion`,
],
}
This needs a restart of the gatsby development process.
Add this snippet in the gatsby-node.js:
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /canvas/,
use: loaders.null(),
},
],
},
})
}
}
There's a package that is trying to access global objects such as window or document in your SSR (Server-Side Rendering) where obviously is not defined (it even exist) because gatsby-build occurs in the Node server while gatsby develop occurs in the browser-side, where the window exists and the compilation time. With the snippet above, you are adding a null loader to the offending module when webpack transpile the code.
The rule test is a regular expression (hence the braces, /) that matches the folder name inside node_modules. The output error shows a canvas issue but you may need to change it to /stylis/
My use-case is this:
I have a static library which I want to be available for some profiles (e.g. "gcc", "arm-gcc", "mips-gcc").
I also have an application which links to this library, but this applications should only build using a specific profile (e.g. "arm-gcc").
For this I am modifying the app-and-lib QBS example.
The lib.qbs file:
import qbs 1.0
Product {
qbs.profiles: ["gcc", "arm-gcc", "mips-gcc"] //I added only this line
type: "staticlibrary"
name: "mylib"
files: [
"lib.cpp",
"lib.h",
]
Depends { name: 'cpp' }
cpp.defines: ['CRUCIAL_DEFINE']
Export {
Depends { name: "cpp" }
cpp.includePaths: [product.sourceDirectory]
}
}
The app.qbs file:
import qbs 1.0
Product {
qbs.profiles: ["arm-gcc"] //I added only this line
type: "application"
consoleApplication: true
files : [ "main.cpp" ]
Depends { name: "cpp" }
Depends { name: "mylib" }
}
The app build fails. Qbs wrongly tries to link to the "gcc" version of the library instead of the "arm-gcc" version, as you can see in the log:
Build graph does not yet exist for configuration 'default'. Starting from scratch.
Resolving project for configuration default
Setting up build graph for configuration default
Building for configuration default
compiling lib.cpp [mylib {"profile":"gcc"}]
compiling lib.cpp [mylib {"profile":"arm-gcc"}]
compiling lib.cpp [mylib {"profile":"mips-gcc"}]
compiling main.cpp [app]
creating libmylib.a [mylib {"profile":"gcc"}]
creating libmylib.a [mylib {"profile":"mips-gcc"}]
creating libmylib.a [mylib {"profile":"arm-gcc"}]
linking app [app]
ERROR: /usr/bin/arm-linux-gnueabihf-g++ -o /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/app.7d104347/app /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/app.7d104347/3a52ce780950d4d9/main.cpp.o /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/mylib.eyJwcm9maWxlIjoiZ2NjIn0-.792f47ec/libmylib.a
ERROR: /home/user/programs/qbs/usr/local/share/qbs/examples/app-and-lib/default/mylib.eyJwcm9maWxlIjoiZ2NjIn0-.792f47ec/libmylib.a: error adding symbols: File format not recognized
collect2: error: ld returned 1 exit status
ERROR: Process failed with exit code 1.
The following products could not be built for configuration default:
app
The build fails only when selecting one profile in the app.qbs file, and this profile should not be the first profile in the qbs.profiles line in the lib.qbs file.
When selecting two or more profiles - the build succeeds.
My analysis:
I think this problem is related to multiplexing:
The lib.qbs contains more than one profile. This turns on multiplexing when building the library, which, in turn, adds additional 'multiplexConfigurationId' to the build-directory name (moduleloader.cpp).
The app.lib contains only one profile, so multiplexing is not turned on and the build-directory name does not get the extra string.
The problem can be solved by changing the code (moduleloader.cpp) so that multiplexing is turned even if there is only one profile i.e. with the following patch:
--- moduleloader.cpp 2018-10-24 16:17:43.633527397 +0300
+++ moduleloader.cpp.new 2018-10-24 16:18:27.541370544 +0300
## -872,7 +872,7 ##
= callWithTemporaryBaseModule<const MultiplexInfo>(dummyContext,
extractMultiplexInfoFromProduct);
- if (multiplexInfo.table.size() > 1)
+ if (multiplexInfo.table.size() > 0)
productItem->setProperty(StringConstants::multiplexedProperty(), VariantValue::trueValue());
VariantValuePtr productNameValue = VariantValue::create(productName);
## -891,7 +891,7 ##
const QString multiplexConfigurationId = multiplexInfo.toIdString(row);
const VariantValuePtr multiplexConfigurationIdValue
= VariantValue::create(multiplexConfigurationId);
- if (multiplexInfo.table.size() > 1 || aggregator) {
+ if (multiplexInfo.table.size() > 0 || aggregator) {
multiplexConfigurationIdValues.push_back(multiplexConfigurationIdValue);
item->setProperty(StringConstants::multiplexConfigurationIdProperty(),
multiplexConfigurationIdValue);
This worked for my use case. I don't know if it make sense in a broader view.
Finally, the questions:
Does it all make sense?
Is this a normal behavior?
Is this use-case simply not supported?
Is there a better solution?
Thanks in advance.
Yes, the default behavior with multiplexing is that the a non-multiplexed product depends on all variants of the dependency. In general, there is no way for a user to change that behavior, but there should be.
However, luckily for you, profiles are special:
Depends { name: "mylib"; profiles: "arm-gcc" }
This should fix your problem.
I'm working on a image processing application and I use this code
Camera {
id: cam
viewfinder.resolution: "640x480"
viewfinder.minimumFrameRate: 5
captureMode: Camera.CaptureStillImage
imageCapture {
resolution: "640x480"
onReadyChanged: {
imageDecoder.reset() // my decoder class
cam.imageCapture.capture()
}
onImageCaptured: {
console.log(requestId, preview)
imageDecoder.decodeQmlPreview(preview)
}
}
imageProcessing {
contrast: 0.60
}
}
VideoOutput {
id: output
fillMode: VideoOutput.PreserveAspectCrop
anchors.fill: parent
source: cam
}
I see that all these captured images (preview) are stored on the hard drive and are never being deleted. How to delete these images? I have very limited hard disk space available.
# ls -lh | grep IMG
-rw-r--r-- 1 root root 10.5K Jan 1 00:40 IMG_00000001.jpg
-rw-r--r-- 1 root root 12.2K Jan 1 00:45 IMG_00000002.jpg
-rw-r--r-- 1 root root 15.6K Jan 1 00:48 IMG_00000003.jpg
-rw-r--r-- 1 root root 15.6K Jan 1 00:49 IMG_00000004.jpg
-rw-r--r-- 1 root root 11.4K Jan 1 01:05 IMG_00000005.jpg
QML has a rather implicit relation to the FS - its internal functionality will read and sometimes write, but it doesn't seem to have a defined API for the user to interact directly with the FS.
Which means you will have to implement that functionality in C++, and expose it to QML.
My practice is to create a class System : public QObject and put all the necessary stuff inside, and then in main.cpp:
System s(&engine);
engine.rootContext()->setContextProperty("Sys", &s);
Then from QML you can simply Sys.doYourStuff(). In your case you need the static function bool QFile::remove(const QString &fileName).
My application contains a class which inherits QWebView. The problem is that I get a crash every time I try to type something in this view! Here's my code :
void QViewSupport::setupSupport(QWidget * widget)
{
QUrl startURL = QUrl("http://www.google.fr");
load(startURL);
}
So basically whenever I try to type something in the google search bar, it crashes at the first character...
Here's the output :
ASSERTION FAILED: ICU could not open a break iterator:
U_MISSING_RESOURCE_ERROR (2)
U_SUCCESS(openStatus)
c:\work\build\qt5_workdir\w\s\qtwebkit\source\webcore\platform\text\TextBreakIteratorICU.cpp(45) : WebCore::setUpIterator
1 02426EF7
2 018F0F40
3 018F0CA0
4 018F0E1A
5 0207D7D3
6 0207CE91
7 014F1470
8 01CDBBF5
9 013EEEAC
10 013A45BE
11 01392CA7
12 013A4076
13 0134C062
14 0136166A
15 0144F19A
16 014562E3
17 014205E5
18 0141D9A6
19 017DCE6C
20 0134C82C
21 014EA80F
22 014F1525
23 013EEEAC
24 013A45BE
25 01392CA7
26 013A4076
27 0134C062
28 0136166A
29 017DCE25
30 014202C3
31 0100D627
First chance exception at 0x02426ef7 (Qt5WebKitd.dll) in myApp.exe : 0xC0000005: Access violation writing location 0xbbadbeef.
Unhandled exception à 0x02426ef7 (Qt5WebKitd.dll) in myApp.exe : 0xC0000005: Access violation writing location 0xbbadbe
Am I missing something? I searched the Internet and couldn't find something close to this problem. Thanks in advance if you have the solution!
Edit : As asked, here's the class :
class QViewSupport : public QWebView
{
Q_OBJECT
public:
QViewSupport(QWidget *parent);
~QViewSupport();
private:
void setupSupport(QWidget *Form);
};
And in the .cpp file :
#include "qviewsupport.h"
QViewSupport::QViewSupport(QWidget *parent)
: QWebView(parent)
{
setupSupport(this);
}
void QViewSupport::setupSupport(QWidget * widget)
{
QUrl startURL = QUrl("http://www.google.fr");
load(startURL);
}
QViewSupport::~QViewSupport()
{
}
Edit : The call to this function is done in Setup.cpp (see below), and pViewSupport is a private member define in the Setup class : QViewSupport* pViewSupport;.
Setup::Setup(QWidget *parent)
: QDialog(parent)
{
setupUi(this);
}
void Setup::setupUi(QWidget * widget)
{
// plenty of other things
pViewSupport = new QViewSupport(this);
// same
}
Ok, the problem came from the ICU dlls from Qt, I just replaced them and it worked.