Привет Гиктаймс!
После общей информации, описанной в первой части, сегодня поговорим об APDU в формате, описанном в стандарте ISO7816-4.
APDU (application protocol data unit) — это формат общения карты и терминала. Терминал посылает Command APDU (C-APDU), а карта отвечает с Response APDU (R-APDU).
C-APDU
Формат C-APDU таков:
Header | Body |
---|---|
CLA INS P1 P2 | [Lc field] [Data field] [Le field] |
Каждый элемент заголовка (header) сохранен на одном байте и является обязательным. К заголовку вернемся чуть позже, сейчас поговорим о body команды.
Элементы body следующие:
- Lc: длина элемента Data в байтах.
- Data: данные команды.
- Le: ожидаемая длина данных ответа в байтах, исключая длину Status Word.
Lc и Le, если присутствуют, могут занимать 1 (Short Length) или 3 байта (Extended Length) каждый. При Short Length кодируются значения от 1 до 256. Длина данных на 256 байтов записывается как «00». При Extended Length кодируются значения от 1 до 65536. Первый байт всегда «00» и остальные 2 байта — номер в формате Big Endian. Когда Lc или Le — «00 00 00», то длина данных — 65536 байтов.
В зависимости от присутствия или отсутствия элементы body команды можно разделить на 4 категории:
- Case 1: Body полностью отсутсвует, то есть команда не содержит в себе никаких данных и не ожидается получение каких либо данных от карты при ответе.
- Case 2: В body присутствует только Le, то есть команда не содержит в себе никаких данных, но при этом ожидается получение данных от карты.
- Case 3: В body присутствуют Lc и Data, то есть команда содержит в себе данные, но при этом не ожидается получение данных от карты.
- Case 4: В body присутствуют все элементы, а значит команда содержит в себе данные и ожидается получение данных от карты.
Примеры команд я покажу позже. Сейчас вернемся к header.
Элемент | Значение |
---|---|
CLA | Class байт. Содержит метаданные команды (логический канал, Secure Messaging и т.д.). |
INS | Instruction байт. Код инструкции. Это шестандцатеричное число, старший ниббл которого не может быть 6 или 9. При этом младший ниббл всегда является четным числом. |
P1 | Первый параметр команды. Если он не нужен, то его значение «00». |
P2 | Второй параметр команды. Если он не нужен, то его значение также «00». |
Так как серия моих статей нацелена на рассмотрение в подробностях Global Platform, то значение CLA я буду описывать в контексте Global Platform.
CLA байт с логическим каналом от 0 до 3
b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Значение |
---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | - | - | - | - | Команда из стандарта ISO7816-4 |
1 | 0 | 0 | 0 | - | - | - | - | Команда из спецификации Global Platform |
- | 0 | 0 | 0 | 0 | 0 | - | - | Нет Secure Messaging |
- | 0 | 0 | 0 | 0 | 1 | - | - | Secure Messaging по Global Platform |
- | 0 | 0 | 0 | 1 | 0 | - | - | Secure Messaging по ISO7816-4 без C-MAC |
- | 0 | 0 | 0 | 1 | 1 | - | - | Secure Messaging по ISO7816-4 с C-MAC |
- | 0 | 0 | 0 | - | - | X | X | Логический канал |
CLA байт с логическим каналом от 4 до 19
b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Значение |
---|---|---|---|---|---|---|---|---|
0 | 1 | - | 0 | - | - | - | - | Команда из стандарта ISO7816-4 |
1 | 1 | - | 0 | - | - | - | - | Команда из спецификации Global Platform |
- | 1 | 0 | 0 | - | - | - | - | Нет Secure Messaging |
- | 1 | 1 | 0 | - | - | - | - | Secure Messaging по Global Platform или ISO7816-4 |
- | 1 | - | 0 | X | X | X | X | Логический канал |
b7 определяет, если формат CLA как в первой или как во второй таблице. Когда логический канал находится в промежутке от 0 до 3, то его значение записывается в битах 1 и 2. Иначе, число записанное в битах 1-4 кодирует номер от 4 до 19 (0 = 4, 1 = 5, ..., 15 = 19).
b5 в стандарте ISO7816-4 обозначает Command Chaining. В Global Platform не используется.
R-APDU
Формат R-APDU таков:
Body | Trailer |
---|---|
[Data field] | SW1 SW2 |
Body присутствует при успешном исполнении (с замечаниями или без них) команд из категории Case 2 и Case 4. Его содержание зависит от конкретной команды. Trailer есть всегда и содержит так называемый Status Word, то есть код результата, положительного или отрицательного. Статус может быть одним из следующих:
SW1SW2 | Значение |
---|---|
Успешное исполнение | |
9000 | ОК. |
61ХХ | ОК, но есть еще ХХ байтов данных. |
Исполнение завершилось с замечаниями | |
62ХХ | SW2 уточняет причины замечания. Постоянная память не была изменена. |
63ХХ | SW2 уточняет причины замечания. Постоянная память была изменена. |
Ошибки при исполнении команды | |
6400 | Команда не была исполнена. Постоянная память не была изменена. |
65ХХ | Команда не была исполнена. Постоянная была изменена. |
66ХХ | Команда не была исполнена по причинам безопасности. |
Ошибки, связанные с форматом команды | |
6700 | Неправилная длина команды. |
6881 | Карта не поддерживает указанный логический канал. |
6882 | Карта не поддерживает указанный вид Secure Messaging. |
69XX | Команда не разрешена. |
6AХХ | Неправильные параметры команды. |
6B00 | Неправильные параметры команды. |
6CXX | Неправильный Le. |
6D00 | Неизвестный INS. |
6E00 | Неизвестный CLA. |
6F00 | Ошибка без описания. |
Ошибки из серии 69ХХ и 6АХХ часто используются в Global Platform и будут описаны в подробностях в частях статьи, посвященных Global Platform.
Статусы из серии 61ХХ и 6CXX требуют особенного внимания. Код 61ХХ возможен, когда карта исполнила команду из категории Case 2 или Case 4 и послала неполный ответ. В этом случае, SW2 кодирует длину остатка ответа («00» = 256). В ответ терминал может отправить команду GET RESPONSE для того, чтобы получить оставшиеся данные. Эта процедура может повторяться несколько раз, до тех пор, пока карта не отправит полный ответ. Настоящий Status Word — это статус, содержащийся в последнем ответе на команду GET RESPONSE. Подобная ситуация встречается преимущественно, когда APDU передается через протокол ISO7816-3 T=0 ввиду особенности передачи команд из категории Case 4 (об этом поговорим чуть позже). Код 6CXX встречается, когда указанный Le не соответствует действительной длине ответа. Стоит отметить, что при этом карта не посылает никаких данных в R-APDU, а требует, чтобы терминал повторил команду с Le равным числу, закодированному в SW2.
Особенности передачи команд в категории Case 4 через протокол Т=0
Протокол T=0 очень распространен, так как он используется в SIMках. Его особенность заключается в том, что header всегда состоит из 5 байтов: CLA, INS, P1, P2, P3. P3 может быть использован для кодировки Lc либо Le. Получается, что он, будет лишним для команд Case 1, подходит для команд Case 2 и Case 3, но недостаточен для команд Case 4, где нужны как Lc, так и Le. Как можно решить эту проблему?
Следующим образом. Команды Case 4 передаются с P3=Lc, как будто это команда Case 3. Тогда карта, при успешном исполнении команды, отвечает без данных, но со статусом 61ХХ. В свою очередь терминал посылает команду GET RESPONSE (из категории Case 2), а затем карта посылает настоящий ответ.
GET RESPONSE
Элемент | Значение |
---|---|
CLA | как предыдущая команда, но без Secure Messaging и бит8 = 0 (хотя карты принимают и бит8 = 1) |
INS | C0 |
P1 | 00 |
P2 | 00 |
Lc | - |
Data | - |
Le | XX (обычно SW2 предыдущего ответа) |
Примеры общения с картой
Наконец-то, мы подошли к самой интересной части статьи — примеры.
GET DATA (Card Production Life Cycle)
C-APDU => 80 CA 9F 7F 00
R-APDU <= 6C 2D
C-APDU => 80 CA 9F 7F 2D
R-APDU <= 9F 7F 2A 47 90 50 40 47 91 81 02 31 00 83 58 00 11 68 91 45 81 48 12 83 65 00 00 00 00 01 2F 31 30 31 31 36 38 00 00 00 00 00 00 00 00 90 00
Команда GET DATA (Case 2) читает информацию с карты. Какую именно — определяется параметрами P1 и P2. Ответ в формате BER-TLV (субъект следующей части статьи). Здесь мы видим как в начале команда была отправлена с неправильным Le и карта, в свою очередь, ответила со статусом 6C 2D. После повтора команды с Le = 2D, карта отправила ответ и конечный статус 9000, обозначающий успешное исполнение.
GET STATUS через Т=1
C-APDU => 80 F2 40 00 08 4F 06 31 32 33 34 35 36 09
R-APDU <= 06 31 32 33 34 35 36 07 00 90 00
Команда GET STATUS (Case 4) дает информацию о жизненном цикле карты и приложений. В данном примере Lc = 8, Data = 4F 06 31 32 33 34 35 36 и Le = 9. На данном этапе не буду углубляться в объяснение значения этих данных, поскольку это не так важно. Карта в ответ посылает данные 06 31 32 33 34 35 36 07 00 и статус 9000. Ниже посмотрим точно такую же команду, только отправленную через протокол Т=0.
GET STATUS через Т=0
C-APDU => 80 F2 40 00 08 4F 06 31 32 33 34 35 36
R-APDU => 61 09
C-APDU => 00 C0 00 00 09
R-APDU <= 06 31 32 33 34 35 36 07 00 90 00
Здесь мы видим, что GET STATUS отправляется без Le. Протокол не позволяет нам этого, поскольку в P3 указан Lc. В ответ карта скажет нам длину данных, которые мы должны получить. Затем мы отправляем команду GET RESPONSE с Le = 9. После этого карта, наконец, посылает нам соответствующий ответ.
Итак мы подошли к концу этой части. Если у кого-то будут вопросы, вы можете написать их в комментариях. Следующая часть статьи будет о BER-TLV, так как этот формат кодирования данных используется практически для всего, что связано со смарт-картами.
Автор: brainnolo