Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | * |
| 16 | * Test program to select the CardManager and request the card production |
| 17 | * lifcycle data (CPLC). |
| 18 | */ |
| 19 | |
| 20 | #include <stdint.h> |
| 21 | #include <stdio.h> |
| 22 | #include <unistd.h> |
| 23 | |
| 24 | #include <ese/ese.h> |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 25 | ESE_INCLUDE_HW(ESE_HW_NXP_PN80T_NQ_NCI); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 26 | |
| 27 | /* APDU: CLA INS P1-P2 Lc Data Le */ |
| 28 | struct Apdu { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 29 | uint32_t length; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 30 | const uint8_t *bytes; |
| 31 | const char *desc; |
| 32 | }; |
| 33 | |
| 34 | struct ApduSession { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 35 | uint32_t count; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 36 | const char *desc; |
| 37 | const struct Apdu *apdus[]; |
| 38 | }; |
| 39 | |
| 40 | const uint8_t kSelectCardManagerBytes[] = {0x00, 0xA4, 0x04, 0x00, 0x00}; |
| 41 | /* Implicitly selects the ISD at A0 00 00 01 51 00 00 */ |
| 42 | const struct Apdu kSelectCardManager = { |
| 43 | .length = sizeof(kSelectCardManagerBytes), |
| 44 | .bytes = &kSelectCardManagerBytes[0], |
| 45 | .desc = "SELECT CARD MANAGER", |
| 46 | }; |
| 47 | |
| 48 | const uint8_t kGetCplcBytes[] = {0x80, 0xCA, 0x9F, 0x7F, 0x00}; |
| 49 | const struct Apdu kGetCplc = { |
| 50 | .length = sizeof(kGetCplcBytes), |
| 51 | .bytes = &kGetCplcBytes[0], |
| 52 | .desc = "GET CPLC", |
| 53 | }; |
| 54 | |
| 55 | const struct ApduSession kGetCplcSession = { |
| 56 | .count = 2, |
| 57 | .desc = "GET-CPLC", |
| 58 | .apdus = |
| 59 | { |
| 60 | &kSelectCardManager, &kGetCplc, |
| 61 | }, |
| 62 | }; |
| 63 | |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 64 | const struct ApduSession kEmptySession = { |
Will Drewry | 2c8c5d5 | 2017-04-17 10:12:03 -0500 | [diff] [blame] | 65 | .count = 0, .desc = "Empty session (hw close only)", .apdus = {}, |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 66 | }; |
| 67 | |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 68 | /* Define the loader service sessions here! */ |
| 69 | const uint8_t kSelectJcopIdentifyBytes[] = { |
| 70 | 0x00, 0xA4, 0x04, 0x00, 0x09, 0xA0, 0x00, |
| 71 | 0x00, 0x01, 0x67, 0x41, 0x30, 0x00, 0xFF, |
| 72 | }; |
| 73 | const struct Apdu kSelectJcopIdentify = { |
| 74 | .length = sizeof(kSelectJcopIdentifyBytes), |
| 75 | .bytes = &kSelectJcopIdentifyBytes[0], |
| 76 | .desc = "SELECT JCOP IDENTIFY", |
| 77 | }; |
| 78 | |
| 79 | const struct ApduSession *kSessions[] = { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 80 | &kGetCplcSession, &kEmptySession, |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 81 | }; |
| 82 | |
| 83 | int main() { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 84 | struct EseInterface ese = ESE_INITIALIZER(ESE_HW_NXP_PN80T_NQ_NCI); |
| 85 | void *ese_hw_open_data = NULL; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 86 | size_t s = 0; |
| 87 | for (; s < sizeof(kSessions) / sizeof(kSessions[0]); ++s) { |
| 88 | int recvd; |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 89 | uint32_t apdu_index = 0; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 90 | uint8_t rx_buf[1024]; |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 91 | if (ese_open(&ese, ese_hw_open_data) < 0) { |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 92 | printf("Cannot open hw\n"); |
| 93 | if (ese_error(&ese)) |
| 94 | printf("eSE error (%d): %s\n", ese_error_code(&ese), |
| 95 | ese_error_message(&ese)); |
| 96 | return 1; |
| 97 | } |
| 98 | printf("Running session %s\n", kSessions[s]->desc); |
| 99 | for (; apdu_index < kSessions[s]->count; ++apdu_index) { |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 100 | uint32_t i; |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 101 | const struct Apdu *apdu = kSessions[s]->apdus[apdu_index]; |
Will Drewry | de2cad7 | 2017-03-10 15:53:34 -0600 | [diff] [blame] | 102 | printf("Sending APDU %u: %s\n", apdu_index, apdu->desc); |
| 103 | printf("Sending %u bytes to card\n", apdu->length); |
Will Drewry | d4ae528 | 2017-01-03 22:06:26 -0600 | [diff] [blame] | 104 | printf("TX: "); |
| 105 | for (i = 0; i < apdu->length; ++i) |
| 106 | printf("%.2X ", apdu->bytes[i]); |
| 107 | printf("\n"); |
| 108 | |
| 109 | recvd = ese_transceive(&ese, (uint8_t *)apdu->bytes, apdu->length, rx_buf, |
| 110 | sizeof(rx_buf)); |
| 111 | if (ese_error(&ese)) { |
| 112 | printf("An error (%d) occurred: %s", ese_error_code(&ese), |
| 113 | ese_error_message(&ese)); |
| 114 | return -1; |
| 115 | } |
| 116 | if (recvd > 0) { |
| 117 | int i; |
| 118 | printf("Read %d bytes from card\n", recvd); |
| 119 | printf("RX: "); |
| 120 | for (i = 0; i < recvd; ++i) |
| 121 | printf("%.2X ", rx_buf[i]); |
| 122 | printf("\n"); |
| 123 | } |
| 124 | usleep(1000); |
| 125 | } |
| 126 | printf("Session completed\n\n"); |
| 127 | ese_close(&ese); |
| 128 | } |
| 129 | return 0; |
| 130 | } |