I am running this (http://www.linux-usb.org/gadget/usb.c) Gadget FS user mode driver on an embedded device.
When I connect it to Windows, these are the GET_DESCRIPTOR setup requests I receive:
80 06 03 03 09 04 ff 00
80 06 00 03 00 00 ff 00
80 06 02 03 09 04 ff 00
80 06 03 03 09 04 ff 00
80 06 00 03 00 00 ff 00
80 06 02 03 09 04 ff 00
`bmRequestType`: 0x80 Device-to-host transfer direction
`bRequest`: 0x06 GET_DESCRIPTOR
`wValueH` : 0x03 Descriptor Type 'String'
`wValueL` : Descriptor Index
`wIndex` : 0x04 0x09 Language ID "US-English" for Descriptor Types "String", 0x00 for others
`wLength` : Length of the requested descriptor
These are the setup requests coming from the Linux host when i connect the device.
80 06 00 03 00 00 ff 00
80 06 02 03 09 04 ff 00
80 06 01 03 09 04 ff 00
80 06 03 03 09 04 ff 00
80 06 ee 03 00 00 00 04
The last one makes my GadgetFS implementation STALL. The Descriptor Type is 3, meaning a Descriptor of type "String" is requested but in wIndex no Language ID is provided (0x00 0x00). Also, the Descriptor Index is 0xEE, but why would you have 238 String Descriptors for a device?
Notice also the length of the requested descriptor: 0x0400 (1024).
This is a code excerpt from the driver implementation I use (linux-usb.org) that handles the setup requests:
case USB_REQ_GET_DESCRIPTOR: //0x06
if (setup->bRequestType != USB_DIR_IN) //USB_DIR_IN = 0x80
goto stall;
switch (value >> 8) // wValueH: Descriptor Type
{
case USB_DT_STRING: // 0x03 Type = "String"
{
tmp = value & 0x0ff; // wValueL : Descriptor Index
struct usb_gadget_strings strings = {
0x0409, /* "en-us" */
m_aUsbStringtab
};
index = 0x0409
if (tmp != 0 && index != strings.language) //This makes it STALL when connected to a linux
goto stall;
I'd really appreciate it, if someone could help me!
So appearently on linux, the setup request with a descriptor index of 0xEE and a length of 1024 is not sent by libusb on linux but by mtp-probe (part of libmtp, media transfer protocol).
Related
When inserting an UICC in an iPhone SE2 and recording the APDU messages between the modem and the UICC I see a sequence opening a logical channel and trying to select an application. I could not find any reference to this application. What is it?
01 a4 04 0c 10 a0 00 00 00 09 02 03 ff ff ff ff 89 01 00 00 ff
The RID a0 00 00 00 09 is registered for the ETSI.
I'm trying to connect a Newport AGILIS AG-UC8 controller to my Linux via USB.
Internally, this controller has an FT232R usb-to-serial chip, that should accept simple text commands, such as "VE\r\n" to print the version.
This works fine when using the provided windows driver and software, but on Linux (tested with pyserial and others), the chip doesn't answer. Basically I initialized the device with the values that the Windows device manager showed and then just sent the command.
ser = serial.Serial(port='/dev/ttyUSB0', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
ser.write("VE\r\n")
I did some debugging with wireshark USB captures:
Windows packet (working, from the provided software):
0000 1b 00 20 9a 40 55 8a ad ff ff 00 00 00 00 09 00 .. .#U..........
0010 00 01 00 03 00 02 03 04 00 00 00 56 45 0d 0a ...........VE..
Linux packet (not working, from pyserial):
0000 80 dd 35 82 e5 99 ff ff 53 03 02 08 02 00 2d 00 ..5.....S.....-.
0010 b6 08 41 60 00 00 00 00 3a 6f 00 00 8d ff ff ff ..A`....:o......
0020 04 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 ................
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0040 56 45 0d 0a VE..
As you can see, the packet on windows is much smaller, and does not contain the padding zeros. These zeros follow immediately after the data-length field (04), so I am wondering whether they pose the problem to the controller.
Is there a way to send the data without zero padding? Preferably in pyserial, but for now I'd be happy with any solution that lets me speak to my device.
Answering your question, but not necessarily solving your problem: those extra zeros are due to the sniffer capturing traffic between the kernel and libusb. It is also the reason why your capture looks different between environments.
Specifically they are the values stuffed into the pcap_usb_setup structure that sits after urb and data length. There's no particular way or reason to try to eliminate them.
/*
* Header prepended by linux kernel to each event.
* Appears at the front of each packet in DLT_USB_LINUX captures.
*/
typedef struct _usb_header {
uint64_t id;
uint8_t event_type;
uint8_t transfer_type;
uint8_t endpoint_number;
uint8_t device_address;
uint16_t bus_id;
char setup_flag;/*if !=0 the urb setup header is not present*/
char data_flag; /*if !=0 no urb data is present*/
int64_t ts_sec;
int32_t ts_usec;
int32_t status;
uint32_t urb_len;
uint32_t data_len; /* amount of urb data really present in this event*/
pcap_usb_setup setup;
} pcap_usb_header;
/*
* USB setup header as defined in USB specification.
* Appears at the front of each Control S-type packet in DLT_USB captures.
*/
typedef struct _usb_setup {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} pcap_usb_setup;
lakhal#lakhal-ThinkPad-T430s:~$ hexdump -C /dev/bus/usb/003/014
00000000 12 01 00 02 e0 00 00 40 e8 04 63 68 ff ff 02 03 |.......#..ch....|
00000010 04 01 09 02 4b 00 02 01 00 c0 30 08 0b 00 02 e0 |....K.....0.....|
00000020 01 03 07 09 04 00 00 01 e0 01 03 05 05 24 00 10 |.............$..|
00000030 01 05 24 01 00 01 04 24 02 00 05 24 06 00 01 07 |..$....$...$....|
00000040 05 83 03 08 00 09 09 04 01 00 02 0a 00 00 06 07 |................|
00000050 05 81 02 00 02 00 07 05 02 02 00 02 00 |.............|
0000005d
The file allows you to read certain USB descriptors from the device. The USB device descriptor, which is defined by the USB specification, is located at the beginning of the file.
For more details, see the file usb/core/devio.c in the source code of your kernel. In particular, look at the function usbdev_read, which implements the kernel side of the read system call for these special files. I cannot find official documentation at the moment.
I believe some parts of the file are "holes", meaning that you won't be able to read any data from them, and you might get meaningless data depending on whether the program you uses initializes the buffers it uses for reading from the file.
I wrote the below program to generate random numbers of different lengths, using two different algorithms (ALG_SECURE_RANDOM and ALG_PSEUDO_RANDOM).
P1 and P2 in the APDU command specify the algorithm and the random length in order.
P1 = 0X01 : ALG_SECURE_RANDOM
P1 = 0X02 : ALG_PSEUDO_RANDOM
P2 = Random number length
public class RandGen extends Applet {
byte[] generatedArray;
byte[] generatedRandom;
RandomData randomDataSecure = RandomData
.getInstance(RandomData.ALG_SECURE_RANDOM);
RandomData randomDataPseudo = RandomData
.getInstance(RandomData.ALG_PSEUDO_RANDOM);
private RandGen() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new RandGen().register();
}
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
generatedArray = JCSystem.makeTransientByteArray(
(short) buffer[ISO7816.OFFSET_P2], JCSystem.CLEAR_ON_DESELECT);
switch (buffer[ISO7816.OFFSET_P1]) {
case (0x01):
generatedRandom = secureRandomGenerator(apdu);
break;
case (0x02):
generatedRandom = pseudoRandomGenerator(apdu);
break;
default:
return;
}
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) ISO7816.OFFSET_P2);
apdu.setOutgoingAndSend((short) 0, (short) ISO7816.OFFSET_P2);
}
public byte[] secureRandomGenerator(APDU apdu) {
byte[] buffer = apdu.getBuffer();
randomDataSecure.generateData(generatedArray, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
return generatedArray;
}
public byte[] pseudoRandomGenerator(APDU apdu) {
byte[] buffer = apdu.getBuffer();
randomDataPseudo.generateData(generatedArray, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
return generatedArray;
}
}
The CAP file generated and uploaded on the card successfully, but when I send APDU commands to the card, I receive the 0X6F00 status word :
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000202
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 02
Received (SW1=0x90, SW2=0x00)
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000102
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 02
Received (SW1=0x6F, SW2=0x00)
Is there something wrong in my applet?
Update:
Based on dear #Vojta's answer, I replace
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) ISO7816.OFFSET_P2);
apdu.setOutgoingAndSend((short) 0, (short) ISO7816.OFFSET_P2);
With following lines in process() method :
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
apdu.setOutgoingAndSend((short) 0, (short) buffer[ISO7816.OFFSET_P2]);
Now I have a weird output in OpenSC-Tool output :
Secure random generator :
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000110
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 10
Received (SW1=0x90, SW2=0x00):
B8 1F 80 25 A2 8E 25 30 F8 22 F8 40 0F AE B0 6C ...%..%0.".#...l
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 .....
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000110
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 10
Received (SW1=0x6F, SW2=0x00)
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000110
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 01 10
Received (SW1=0x90, SW2=0x00):
F6 45 A9 0C 0C 3B 3A 5A 5F DC A8 36 .E...;:Z_..6
Pseudo random generator :
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000210
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 10
Received (SW1=0x90, SW2=0x00):
37 FD FC 67 EB 9E 21 00 6B E9 44 A7 21 3F 31 9A 7..g..!.k.D.!?1.
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 .......
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000210
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 10
Received (SW1=0x6F, SW2=0x00)
OSC: opensc-tool.exe -s 00a404000b0102030405060708090000 -s 00000210
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 0B 01 02 03 04 05 06 07 08 09 00 00
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 02 10
Received (SW1=0x90, SW2=0x00):
72 FE 48 1B 9A A0 BD 2D DF F9 E7 F8 58 CF B7 C0 r.H....-....X...
00 00 00 00 00 00 00 00 00 00 00 ...........
Why I have different output for a single command?
There is a little bug in your code. You want
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
instead of
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) ISO7816.OFFSET_P2);
General rule: ALWAYS surround the content of your process method with a try-catch block and set status words according to the type and reason of the exception. Otherwise you get only 6F00 and you do not know what really happened. If you followed this rule, you would know that ArrayIndexOutOfBoundsException was thrown.
Answer to update:
Weird output is caused by the fact, that
Util.arrayCopyNonAtomic(generatedRandom, (short) 0, buffer, (short) 0,
(short) buffer[ISO7816.OFFSET_P2]);
apdu.setOutgoingAndSend((short) 0, (short) buffer[ISO7816.OFFSET_P2]);
overwrites the buffer[ISO7816.OFFSET_P2] with some random value and then this value is used on the next line. You should store buffer[ISO7816.OFFSET_P2] in RAM in the beginning of the process method:
final byte p2 = buffer[ISO7816.OFFSET_P2];
Answer to comment below:
You have troubles for P2 >= 0x80, because of casting byte to short. Unfortunately, JavaCard handles byte as signed, that is why your length for P2 >= 0x80 is negative. You could easily avoid this by:
final short outputLen = (short) (buffer[ISO7816.OFFSET_P2] & 0xFF);
command not supported
You have the wrong instruction joining together.
i have a file with .raw extension (raw image format), but i cannot open it. i tried to analyze it with the commands file filename.raw, exiv2 print, exiftool, ufraw, dcraw. since it appears to be a binary file, i tried to extract information using strings filename.raw, hexdump and xxd. it is surprising that the file does not appear to have any metadata. i suspect the file extension to be wrong, and the file to be manipulated.
how else can i determine the type? how can i extract any information?
thank you very much for any suggestions.
EDIT: a sample file can be downloaded
here.
Hmm... well,
//Judging from the number of bytes in the file:
// 1447600
//This number is exactly.
// 3 x 499 x 967
//Which is very odd, but it means if this is an image, then it must be 3 bytes per pixel and either 499 x 967 or 967 x 499
EDIT: resolution is wrong. Probably bits per channel as well, this is what I get for using bc in the middle of the night instead of WA.
Actual factors are 2^4*5^2*7*11*47, which means it cannot be 3 Bytes per pixel. There might be some stream compression going on? But probably not, the number is too nice.
Looking at some of the data, most of it is quite noisy, which fits with a camera with a noisy digital sensor:
00000000 0e 08 06 02 04 06 00 02 00 04 01 04 0e 03 05 01 |................|
00000010 03 01 06 04 00 03 01 05 01 00 02 00 06 02 04 01 |................|
00000020 00 07 0c 0d 05 01 0a 0d 03 08 11 08 0c 03 06 06 |................|
00000030 08 02 07 04 01 01 07 02 05 06 10 04 07 01 04 02 |................|
00000040 02 01 0c 09 07 02 05 01 0d 04 00 05 0e 01 00 07 |................|
00000050 00 02 04 0a 11 04 07 04 01 00 0d 07 0f 06 03 02 |................|
00000060 06 04 0a 0b 03 08 02 0c 00 08 00 04 06 09 03 03 |................|
00000070 04 00 0a 04 01 06 00 00 02 08 0a 07 04 09 01 0b |................|
00000080 01 0c 0d 04 03 03 05 00 02 11 09 00 07 08 08 05 |................|
00000090 04 07 02 0c 00 13 01 06 07 02 08 0a 07 05 02 01 |................|
This area, at the beginning of the file, is likely to be close to all black.
So, of the common 3 bytes per pixel formats, you have BGR24, RGB24 or YUV24.
Because it's simpler to deal with RGB or BGR formats, let's whip up some short code to dump this to a png, using libpng.
First try:
#include <png.h>
#include <exception>
#include <memory>
int main() {
FILE * fpout;
FILE * fpin;
png_structp png_ptr = nullptr;
png_infop info_ptr = nullptr;
const unsigned width = 499;
const unsigned height = 967;
const unsigned channels = 3;
fpin = fopen("sample.raw", "rb");
if (!fpin)
throw std::exception();
std::unique_ptr<char[]> data(new char[width*height*channels]);
fread(data.get(), width*height*channels, 1, fpin);
fclose(fpin);
fpout = fopen("output.png", "wb");
if (!fpout)
throw std::exception();
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr) {
fclose (fpout);
throw std::exception();
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_write_struct(&png_ptr, nullptr);
fclose (fpout);
throw std::exception();
}
if (setjmp(png_jmpbuf (png_ptr))) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose (fpout);
throw std::exception();
}
png_set_IHDR(png_ptr,
info_ptr,
width,
height,
8,
PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
/* Initialize rows of PNG. */
std::unique_ptr<png_bytep[]> row_ptrs(new png_bytep[height]);
size_t stride = width * 8 * channels / 8;
for (size_t i = 0; i < height; ++i) {
size_t q = i * stride;
row_ptrs[i] = (png_bytep)data.get() + q;
}
/* Write the image data to "fp". */
png_init_io(png_ptr, fpout);
png_set_rows(png_ptr, info_ptr, row_ptrs.get());
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose (fpout);
}
Gives us:
http://i.imgur.com/Iwi3M.jpg
This is heartening, because it seems that we merely have the resolution wrong. So examining the image, it looks like the bar repeats itself every 467 pixels or there abouts. However, it does not look like there is anything interesting in the data. So it's likely not simple RBG or BGR or YUV encoding, otherwise, it would look nicer.
Raw Therapee doesn't recognize it. So, I'm asking you now. What camera did you use to make this?