read/write SLE4442 memory card with WinSCard API in c# - c#

A bit of background information:
Inorder to read/write to SLE4442 memory cards, my app is currently using an Omnikey Cardman 3021 USB card reader, a Sumbsembly Smartcard API (external dll) which is capable of wrapping CT-API calls (directed to omnikey's dll) so that I can read/write the memory card in my c# app.
The only problem here is that Omnikey only provides a 32-bit dll of their CT-API. I asked if they are going to produce a 64-bit version, but they couldn't be bothered.
Current situation:
Inorder to make my application 64-bit capable, I must rewrite it using Windows WinSCard API. The problem here is that there are no specific examples on the web how to do it. Also getting hold of working APDU commands is nearly impossible, but I've managed to aquire two slightly different versions that sort of work.
I have googled this a hundred times over many months and with what I have managed to gobble together I can finally read the SLE4442 memory card. But for the life of me I can't get writing to work.
The code:
I'm not going to post the entire code into this first post (if need be I can do it later or provide a link to the source code).
But I'll outline the basic steps.
1) SCardEstablishContext
2) Get the reader name via SCardListReaders
3) SCardConnect
4) Read entire memory with SCardTransmit and APDU new byte[] { 0xFF, 0xB0, 0, 0, 0 };
5) Verify pin with SCardTransmit and APDU new byte[] { 0xFF, 0x20, 0, 0, 3, 0xFF, 0xFF, 0xFF }; (Note that this does return 0x90;0x00 as a response, which means the verification should have been succesful)
6) Try to write with ScardTransmit and APDU new byte[] { 0xFF, 0xD6, 0, 0, 50, 1 }; (try to write value 1 at memory position 50) - I have also tried using an APDU with the first parameter being 0x00 and/or the second byte being 0xD0. The response has never been 0x90;0x00 so I assume there is an error during writing, but I haven't been able to find any meaning to the error codes returned.
Possible causes:
Because I can read a memory card with the WinSCard API then it must be possible to also write to one (side note - the memory card(s) that I try to write to are in in working condition, I haven't locked them down by failing to verify the PIN 3 times).
1) Maybe the write APDU command is wrong. Could be that the instruction byte (second byte) is incorrect, or the memory location uses some sort of an extended coding scheme.
2) Maybe the verify command didn't actually verify. As in the command itself is fine, which is why 0x90 was returned, but I must call or setup something first.
3) Just a hunch, but I think that this is the real culprit. While googling I did find some vague references to having to call the SCardControl method with parameter IOCTL_SMARTCARD_SET_CARD_TYPE and setting the card type to SLE4442. But again no working examples anywhere and my trial-and-error testing resulted in failures. I got "One or more of the supplied parameters could not be properly interpreted." and some other error messages as well, can't remember what they all were. Assuming the code I copy-pasted from google code has the right descriptions for the error codes.
What I need:
What I need is someone to post or direct me to a site that has full+working code in c# for read/write SLE4442 using WinSCard API and it must work in both 32-bit and 64-bit enviroments.
The code doesn't have to be foolproof - eg. handling every possible error situation nicely. I should be able to do that myself. But if it is (including the APDU command result descriptions - eg. 0x90;0x00 is success, but 0x6B;0x4D is... etc...) then all the better.

APDU for writing to card, in your example, should be:
FF D6 00 50 01 01

Our Omnikey (3121) terminal writes data on SLE4442/SLE4442 cards perfectly, try this APDU:
FF D6 00 04 10 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E AA
see also:
http://acs.com.hk/drivers/eng/API_ACR122U.pdf, chapter 5.4

FF,D2,00,01,03,01,02,03 (new pin = 1,2,3) does not work (also after verifying existing PIN:
6D,00,FF,20,00,00 03,FF,FF,FF) - It returns error code 6D00.
For us (yet) not a huge problem, as we code our cards now with the Xiring XiMax terminal (programmable terminal with it's own SDK, the terminal can store data in flash memory).
However, we need to find a solution soon. I am interested in your (future) findings.
Do you have the Omnikey SDK? We can send you working examples in C++ that can change PSC (pin) and data on SLE4442/5542 cards.
This week (so not tomorrow, as previously stated, we have many things going on and are constantly ) we will test the (so far) working code with the Omnikey 1021). Hope to help you out.
We always have 50+ Omnikey 3121 readers on stock and we can offer you these (1+) for a far batter price. Let me know if you are interested.
I am also interested what where you are located and what applications you are developing.

Related

Read or Write from AT88SC1608 Memory card with dcic32.dll

I'm trying to work with AT88SC1608 smart card with a card reader which works with dcic32.dll in a C# app
some functions like IC_CheckCard or IC_InitComm or IC_DevBeep works prefectly
but when read memory like below :
IC_ReadConfigZone(int idComDev, short Offset, short len, byte[] RDataBuff);
I don't know how it's work because related to this document(AT88SC1608 datasheet) - 4 bytes from 12 to 15 is for card code manufacture but when i try it for 3 different cards all values were same for example :
RDataBuff = new byte[] { 126, 97, 164, 82}
now I don't know how to use this data or
even write on a user zone or verify password ?
anyone can help or has experience ?
Note: the AT88SC1608 is not a smart chip but a memory chip communicating via the two-wire protocol (not command APDUs according to ISO 7816-4) with similar capabilities as Infineon SLE44xx/SLE55xx, for which we have a couple of related questions here.
The reader may or may not support that kind of chip, but if it does, you have to check its documentation how the reading is supposed to work - most likely it will be some kind of APDUs too, but with 0xFF as first (i.e. CLA byte).
I note, that all the commands, which work in your set-up are commands handled by the reader itself, so no successful card communication took place yet, and what you get as response (in hex for easier reference: 7E 61 A4 52) is likely some kind of error code.

Read EMV data from Mastercard/VISA Debit/Credit Card [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am trying to build an application to read/encode data on Cards, information like PAN, expiry, customer name, PIN etc, So far I could figure out that I need to send APDU commands to read data from Card but there seems to be no clear documentation available as to what commands are used for what purpose and in what particular sequence, I couldn't find out specifications from Mastercard/VISA. Is there some documentation that can be referred to?
Thanks,
Null
Extending the other answer:
SELECT PSE:
T-->C - 00A404000E315041592E5359532E444446303100 # select PSE
T<--C - response with FCI
T-->C - 00B2010C00
T<--C - reponse with record from selected file, read records starting from 1 until receive 6A83 (optional step in your case)
SELECT application DF with AID received in step 1):
T-->C - 00A4040007A000000003101000 # as example, Visa AID
T<--C - response with application DF FCI
GET PROCESSING OPTIONS - initialize transaction:
T-->C - 80A8000002830000 # check if PDOL presents on card, if not, only 8300 should be added to DATA filed of APDU
T<--C - 771282023C00940C0802020010010300180102019000 # just example reswponse, it will differ on different cards
The response on GET PROCESSING OPTIONS above is TLV encoded:
77 12 - response templait, containing response data
82 02 3C00 - AUC
94 0C 080202001001030018010201 - AFL
9000 - SW (Status Word), response ofapplication, telling you, that no errors occured
Note, that response to GET PROCESSING OPTIONS may be returned as 80 template, in that case, you must parse it yourelf:
80 0E - response templait, containing response data
3C00 - AUC (always 2 bytes long)
080202001001030018010201 - AFL
9000 - SW (Status Word), response ofapplication, telling you, that no errors
You are interesting in AFL, which points you, where to read data from (files and record numbers):
94 0C
08020200
08 - SFI (Short File Identifier)
02 - first record in file
02 - last record in file
00 - no of records to be added to Static Data Authentication
10010300
10 - SFI
01 - first record in file
03 - last record in file (respectively, 3 records to be read - 01, 02, 03)
00 - no of records to be added to Static Data Authentication
18010201
18 - SFI
01 - first record in file
03 - last record of file
01 - count of records from first record to be used for Static Data Authentication (01 record must be used)
SFI is encoded as follows:
08 = 0000 1000 - first 5 bits are real SFI, it equals to 01, last 3 bits are always set to 0
READ APPLICATION DATA - for precize READ APPLICATION DATA command coding check 3rd EMV Book:
T-->C - 00B2020C00 # SFI = 01, record = 02
T<--C - response with record
T-->C - 00B2021400 # SFI = 02, record = 01
T<--C - response with record
T-->C - 00B2031400 # SFI = 02, record = 02
T<--C - response with record
etc until you process last AFL record...
PAN, expiry, effective date, track 2 equivalent data, etc... usually is located in records which are set to be used in Sighed Data Authentication in AFL.
The example above is for T=1 protocol. If card runs T=0 protocol, in response to each APDU which assumes R-APDU (Response APDU) to contain Data field, card will return byte count ready to be read and you should issue GET RESPONSE commands which is described in Book 1 of EMV specification.
Hope it helps.
You must check EMV ICC card specifications to understand, how to read data from ICC, specifications are freely available to download. Specification is splitted into 4 parts (4 books). You are interested in 1st and 3rd books to read application.
The sequence of APDUs to read application data is the following:
1) SELECT PSE (Payment System Environment file), it contains a list of Application DFs installed on smart card. DFs are named by AID (Application ID), which you will use to create a list of available applications (candidate list) for selection, if you want it, or just find AID with the most less Application Priority Indicator (check EMV Book 1 for more information). This is optional step, you can start from step 2) and try to select both Visa and MasterCard AIDs to check which of them is available on ICC.
2) SELECT application which you want to run using correct AID from list you have got in step 1). AIDs of Visa and MasterCard:
A0000000041010 - MasterCard
A0000000031010 - Visa
It will return FCI (File Control Information) of Application file and make Application SELECTED on ICC itself (Check EMV Book 1 for more information).
3) GET PROCESSING OPTIONS - initiate transaction on ICC. This APDU increments ATC (Application Transaction Counter) and returns AUC (Application Usage Control) and AFL (Application File Locator), which must be used to read data you need (Check EMV Book 3 for info).
4) READ APPLICATION DATA - using AFL returned in 3) you can read Application data. AFL is constructed from several parts: containing information about file (SFI - Short File Identifier), first record number, last record number and count of records used in Signed Data Authentication:
1st byte - SFI
2nd byte - First record ID
3rd byte - Last record ID
4th byte - Count of records in file to be used in Signing Data Authentication
It contains 4 byte long information on every file with records to be read during transaction. Just run over AFL and read records from every SFI from first to last records, that is all (consult book 3 for more information).
You will be unable to read PIN from card, PIN is personalized in records, which are not available to read from outside. ICC uses PIN only inside using VERIFY command, and ICC just returns PIN verification result and PIN try counter if PIN was wrong.
EMV Book 1,also, describes 2 used data transmission protocols, T=0 and T=1. To work with ICCs it is essential to understand a difference between these protocols.
Each step above starts from APDU name to make you easier find information into EMV Books 1 and 3.
To encode data to different card - it is completely different story. You should check EMV CPS (Common Personalization Specification) and GlobalPlatorm specifications. Personalization process is much more complex.

How to print exponential number "m³" using ESC/POS printer with C#?

I'm trying to print a ticket, and need to print out m³ as unit of measurement using a serial printer. And the following is what I have tried so far:
if (!printer.IsOpen)
printer.Open();
printer.WriteLine(string.Format("{0} m{1}", "2.34", Convert.ToChar(0xB3)));
printer.Close();
When I tried to debug and view the value using the text visualizer the text is correct which is "2.34 m³". But when it comes to printing, the text changed to "2.34 m?", where the expected output should be "2.34 m³".
I've been trying to figure this out for days. Please help. Thanks.
It seems as if your printer does not support the '³' character natively.
Therefore you need the printer manufacturer's technical manual. There, you must identify a control character sequence for superscript mode and put it in from of a (normal) character '3'. After it, you must switch off superscript mode again.This control codes are printer specific, and you need, therefore you must have this information from the printer manufacturer.
Assuming "Superscript on" is ESC 0x4e and "Superscript off" is ESC 0x4f, then your cde would look like this:
printer.WriteLine(string.Format("{0} m{1}3{2}", "2.34", "\x1b\x4e", "\x1b\x4f" );
What font are you using? I think the font you're using doesn't support that character, which is why it put a ?. During debug it shows the right character because visual studio is using a font that does support that character. Try choosing a different font and see if that helps.
I don't know C# well enough to comment on the code in your question, but it's absolutely possible to print the ³ character in ESC/POS by sending "\x1B\x74\x02\xFC".
Here is a picture of a receipt from an Epson TM-T20:
I printed this by using a PHP library which understands how to convert UTF-8 into the available code pages of ESC/POS printers. A similar library exists for python, and you would be well advised to use a C# equivalent if it exists!
<?php
require __DIR__ . '/vendor/autoload.php';
use Mike42\Escpos\Printer;
use Mike42\Escpos\PrintConnectors\FilePrintConnector;
use Mike42\Escpos\CapabilityProfile;
$connector = new FilePrintConnector("php://stdout");
$profile = CapabilityProfile::load("default");
$printer = new Printer($connector, $profile);
$printer -> text("2.43 m³\n");
$printer -> cut();
$printer -> close();
This corresponds to the following hexdump.
$ php superscript-demo.php | hexdump -C
00000000 1b 40 32 2e 34 33 20 6d 1b 74 02 fc 0a 1d 56 41 |.#2.43 m.t....VA|
00000010 03 |.|
00000011
All of the commands here are:
ESC # - set formatting and character encoding settings back to their defaults.
ESC t 2 - select code page 2.
LF - line break
ESC V 65 3 - a cut command
The magic here is ESC t 2. The code page numbered 2 on Epson printers is legacy code page 850 on Epson printers. Other vendors may be different, but the manual for your printer also shows CP850 at the same position.
Your default code page (CP437) does not contain the character you want, while in code page 850, ³ is represented by 0xFC. Once you change code pages, the change is active until you either reset the printer, or issue ESC #.
To save time finding special characters individually, you can select a code page which contains everything you plan to use, and then lean on your programming language standard library to encode strings with that code page.

Issues modifying file attachment streams with Outlook .OFT files

I'm attempting to programmatically replace an embedded image within an OFT file (An Outlook message template), which is in Compound File Binary Format (because using anything human readable would make my life too easy).
To work with this file, I'm using OpenMCDF.
Since embedded images are basically file attachments, I can get the stream for the image like so:
static string FOOTER_IMG = "__substg1.0_37010102"; //Stream ID for embedded JPEG footer image
static string ATTACHMENT2 = "__attach_version1.0_#00000001"; //Storage ID for attached footer image
// ...
CFStream imgStream2 = file.RootStorage.GetStorage(ATTACHMENT2).GetStream(FOOTER_IMG);
I can then update that stream with the bytes from my desired image like so:
byte[] img2 = File.ReadAllBytes(footerimgFile); // New file
imgStream2.SetData(img2);
However, when I load the .OFT file in Outlook, the image no longer loads and I get a red X saying the image could not be loaded. I spent hours analyzing every bit of that OFT file, and the only thing that changed between the original template and the new template is that one stream that I replaced.
Here's where things get weird:
I noticed I could replace the bytes with the same exact bytes I had before and save it, so my saving mechanism is working. I thought maybe the OFT template stores some sort of hash of the image which has to match up. So I modified a few random bytes, and the image still loads (sometimes with some funky colors). Eventually, I realized it only breaks if the new image contains fewer bytes than the original image. I can replace the image with a larger image, and that works! I can also just pad a smaller image with trailing zeros at the end of the stream, and it still works.
This led me to come up with a true hackerific masterpiece:
if (img2.Length < 5585) img2 = img2.Concat(new byte[5585 - img2.Length]).ToArray();
Basically, if img2 is too small, I pad on enough bytes to make it the same size as the original image (5585 bytes to be exact). So this works. But.. yea.
My Question:
Does the Microsoft OFT file format store the byte count for attachments in some other stream or some other CDF container? If this was a standard property of CDF, you'd think OpenMCDF would update this count. This leads me to believe this is a property of the OFT file format, which OpenMCDF would of course know nothing about.
Why would writing a smaller stream corrupt the file, where writing a larger stream work?
Update:
From what I've read so far, the __properties_version1.0 stream contains a list of pointers (offsets?) to mark where various other streams are. I'm guessing something in here needs to be updated. Currently, I have these streams in the attachment container:
From what I can tell __properties_version1.0 doesn't change hardly at all between the first attachment (a 36,463 byte file) and the second attachment (a 5,585 byte file). The __properties_version1.0 for the second attachment is:
There's only a set of 8 bytes that change between those two attachments. In attachment 1 we have:
6F 8E 00 00 03 00 2D 00
In attachment 2 (pictured above) we have:
D1 15 00 00 03 00 6F 08
Are those offsets? Doesn't seem to be a range, or the numbers would go up. Those numbers are also way too big to be file sizes. Plus, it seems redundant to store file sizes in here anyway. So, I'm once again at a loss as to why changing the size of the 0x37010102 stream causes the image to no longer load.
Another thing that makes zero sense. I can change the size of the first attachment with either larger or smaller files, and nothing breaks. However, there's absolutely no difference between any stream in those two containers except the data in the 0x37010102 stream. Why does this approach work in one attachment and not the other?
Update 2:
I have noticed the two differences in the __properties_version1.0 stream between the two attachments do correspond to the file sizes:
6F 8E 00 00 03 00 2D 00 // Attachment 1
D1 15 00 00 03 00 6F 08 // Attachment 2
6F 8E seems to be a little-Endian representation of the file size, as 8E6F in decimal would be 36463, which is the number of bytes in the first attachment. 15D1 in decimal is 5585, the size of the second attachment. So, this stream definitely is storing file sizes. Now to see if I fix those bytes if the file becomes uncorrupted.
Update 3:
So, changing those bytes fixes a previously corrupted file, so that's the key! Now just to find a way to do this programmatically.
Are you working with embedded HTML images (which are just regular image attachments) or embedded RTF images (which OLE storage)?
Do you simply truncate a particular stream without adjusting any other properties?
Well, it's times like this I feel like an uber nerd. Here's the code that fixes the problem. Note, the byte offsets in propBytes might be different if you had other properties in the attachment.
// Fix file size on prop stream
var propStream = file.RootStorage.GetStorage(ATTACHMENT2).GetStream("__properties_version1.0");
var propBytes = propStream.GetData();
propBytes[0xb0] = (byte)(img2.Length & 0xFF);
propBytes[0xb1] = (byte)(img2.Length >> 8);
propStream.SetData(propBytes);
However, I like this solution better than padding extra zeros.
I think the real solution would be to use a third party library that deals with .MSG format, however I could not find any that don't make you install Outlook or Exchange on the server (which we can't do) or that are free (we have zero budget for this).

Differences in length in TagLib# (C#) and TagLib (C++)

I am currently in the process of moving my C# application over to Qt / C++. I'm running into problems with lengths from TagLib. I find it odd that TagLib# returns audio durations in milliseconds, while TagLib returns its (incorrect) durations in seconds. TagLib just returns zero for the length values, while TagLib# remains correct.
Here is my source in C# / TagLib#...
TagLib.File tagfile = TagLib.File.Create(path);
uint milliseconds = (uint)tagfile.Properties.Duration.TotalMilliseconds;
And here is what should be nearly equivalent in C++ / TagLib. I've even forced it to read accurately. No success.
TagLib::FileName fn(path);
TagLib::FileRef fr(fn, true, TagLib::AudioProperties::Accurate);
uint length = fr.audioProperties()->length();
It works as expected for a good majority of my media files. However, a select few audio files fail to return any audio properties (the rest of the tag information reads fine!). The exact same audio properties are returned with no issues on TagLib#.
Any ideas are appreciated. Thanks.
Does anyone have any more ideas before the bounty ends?
Hi there is a patch to taglib that calculate the length in milliseconds, this guy added a method (lengthMilliseconds()) that return the length in milliseconds, maybe that could be useful for you:
http://web.archiveorange.com/archive/v/sF3Pjr01lSQjsqjrAC7L
A lot has changed in TagLib#'s parsing of audio files since it was originally ported, so its hard to say where exactly the difference would occur. You may check your C++ program for debug messages.
My guess is that the difference is in how the two libraries react to invalid headers. It appears that if the first frame header it finds is invalid, TagLib won't calculate any audio property values. TagLib#, on the other hand, looks for the first valid header in the first 16KiB of the audio part of the file. If the first header it encounters is corrupt, it will scan for the next one. If I remember correctly, an incorrectly saved ID3v2 tag could result in 0xFF FF FF FF appearing in the beginning of the audio section of the file. This would trigger the type of failure described above.
The problem is at line 166 of taglib/mpeg/mpegproperties.cpp. This could be solved using the same approach as lines 171 to 191, but you would want to update the code to give up after a point in case it really isn't an MP3 file.
As of this writing, TagLib 1.11 BETA 2 natively supports getting the length of audio in milliseconds. You can do so with the following code:
TagLib::FileRef f(path);
int lengthInMillis = f.audioProperties()->lengthInMilliseconds();

Categories

Resources