cleanup workflow
[YkNeoCR.git] / src / org / average / nfcauthcr / YkNeo.java
1 package org.average.nfcauthcr;
2
3 import java.io.IOException;
4 import java.util.Arrays;
5
6 import android.nfc.NfcAdapter;
7 import android.nfc.Tag;
8 import android.nfc.TagLostException;
9 import android.nfc.tech.IsoDep;
10
11 import org.average.nfcauthcr.CRException;
12
13 public class YkNeo {
14
15         // This is a CCID APDU, ISO 7816-4.
16         // 00 A4 04 00 xx AID - GlobalPlatform - SELECT
17         // Lc, send data = 07: A0 00 00 05 27 20 01
18         // Le, recv data = 00
19         private static final byte[] selectApdu =
20                 {0x00, (byte) 0xA4, 0x04, 0x00, 0x07, (byte) 0xA0,
21                  0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x00};
22
23         private static final byte SLOT_CHAL_HMAC1 = 0x30;
24         private static final byte SLOT_CHAL_HMAC2 = 0x38;
25
26         public static final byte[] doChallengeYubiKey(IsoDep isoTag, int slot,
27                                                 byte[] challenge)
28                                 throws CRException {
29                 try {
30                         isoTag.connect();
31                         byte[] resp = isoTag.transceive(selectApdu);
32                         int length = resp.length;
33                         if (resp[length - 2] != (byte)0x90 ||
34                             resp[length - 1] != 0x00) {
35                                 throw new CRException(
36                                 "NFC Error code in the response to select");
37                         }
38                         byte[] crApdu = new byte[69];
39                         crApdu[0] = 0x00; // CLA
40                         crApdu[1] = 0x01; // INS
41                         switch (slot) {
42                         case 1: crApdu[2] = SLOT_CHAL_HMAC1; break; // P1
43                         case 2: crApdu[2] = SLOT_CHAL_HMAC2; break; // P1
44                         }
45                         crApdu[3] = 0x00; // P2
46                         crApdu[4] = 63;   // Lc
47                         System.arraycopy(challenge, 0, crApdu, 5,
48                                                 challenge.length); // Payload
49                         crApdu[crApdu.length-1] = 22; // Le
50                         resp = isoTag.transceive(crApdu);
51                         length = resp.length;
52                         if (resp[length - 2] != (byte)0x90 ||
53                             resp[length - 1] != 0x00) {
54                                 throw new CRException(
55                                 "NFC Error code in the response to CR");
56                         }
57                         if (length != 22) {
58                                 throw new CRException(
59                                 "NFC wrong response size: " + (length-2));
60                         }
61                         return Arrays.copyOf(resp, length-2);
62                 } catch (TagLostException e) {
63                         throw new CRException("NFC connection lost", e);
64                 } catch (IOException e) {
65                         throw new CRException("NFC I/O error", e);
66                 }
67         }
68 }