handle multivalue challenges
authorEugene Crosser <crosser@average.org>
Fri, 10 May 2013 11:38:41 +0000 (15:38 +0400)
committerEugene Crosser <crosser@average.org>
Fri, 10 May 2013 11:38:41 +0000 (15:38 +0400)
res/values/strings.xml
src/org/average/nfcauthcr/Enroll.java
src/org/average/nfcauthcr/QueryCrToken.java
src/org/average/nfcauthcr/YkNeo.java

index 9b83033a34b46ddea8dcdfed17c166eb584e2fa8..83cb008ef2b061bbb9d92bb4d5664a9dd8c38773 100644 (file)
@@ -2,8 +2,24 @@
 <resources>
        <string name="app_name">YkNeo CR</string>
        <string name="info"><![CDATA[
-You need to specify the slot number of the Yubikey Neo to use for
-Challenge-Response.
+<center>
+<h1>Challenge-Response Provider</h1>
+<h2>using Yubico\'s <em>Yubikey Neo</em> NFC token</h2>
+</center>
+<p>
+You need to set up a slot in the <em>Neo</em> to use with CHAL-HMAC
+mode, like this:
+</p>
+<pre>
+  ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible
+</pre>
+<p>
+This application does not do anything itself, it provides a way for other
+applications to use the NFC token for encryption and authentication purposes.
+</p>
+<p>
+The slot number used for the above command must be selected below:
+</p>
        ]]>
        </string>
        <string name="enroll">Set Slot</string>
index d8e623df72135802f896d7f8a2a797e79663df15..3e012d29de524df8834ae1b129c2a025245592a6 100644 (file)
@@ -10,8 +10,10 @@ import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.content.DialogInterface;
+import android.text.Html;
 import android.util.Log;
 import android.view.View;
+import android.widget.TextView;
 import android.widget.RadioButton;
 
 import org.average.ykneocr.QueryCrToken;
@@ -36,6 +38,8 @@ public class Enroll extends Activity {
        protected void onResume() {
                super.onResume();
                setContentView(R.layout.main);
+               TextView tv = (TextView)findViewById(R.id.info);
+               tv.setText(Html.fromHtml(getString(R.string.info)));
                slot = prefs.getInt("slot_number", -1);
                Log.v(TAG, "found saved slot value " + slot);
                RadioButton btn = null;
index 8e5c4632a1f2594db141cfc8910657ec875c04a5..68a8d0e9762e1a04d71a7e948c7d7f56cd5eb749 100644 (file)
@@ -39,6 +39,14 @@ public class QueryCrToken extends Activity {
                super.onResume();
                Log.v(TAG, "Starting the work");
 
+               setResult(RESULT_CANCELED);
+               int slot = prefs.getInt("slot_number", -1);
+               if (slot != 1 && slot != 2) {
+                       Log.e(TAG, "Slot " + slot + " cannot be used");
+                       Toast.makeText(this, R.string.need_slot,
+                                               Toast.LENGTH_LONG).show();
+                       finish();
+               }
                new AlertDialog.Builder(this)
                        .setTitle(R.string.challenging)
                        .setMessage(R.string.swipe)
@@ -54,9 +62,7 @@ public class QueryCrToken extends Activity {
                Intent intent = getIntent();
                ArrayList<String> challenge =
                                intent.getStringArrayListExtra("challenge");
-               int slot = prefs.getInt("slot_number", -1);
                intent.putExtra("yubikey_neo_slot", slot);
-               setResult(RESULT_CANCELED);
                if (challenge != null) {
                        dispatch.onResume(challenge);
                } else {
index 864e7b07d9bf5a58cf757a490545fedad46f76ac..96f3e0fbb53b776a02444b17f07c8608ca80935f 100644 (file)
@@ -4,6 +4,7 @@ import java.io.IOException;
 import java.lang.String;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 
 import android.nfc.NfcAdapter;
 import android.nfc.Tag;
@@ -43,12 +44,6 @@ public class YkNeo {
        public static ArrayList<String> doChalResp(IsoDep isoTag, int slot,
                                        ArrayList<String> cset)
                        throws IOException, CRException {
-               byte[] challenge = unhex(cset.get(0));
-               if (challenge.length > 127) {
-                       throw new CRException(String.format(
-                       "NFC challenge size too big: %d",
-                       challenge.length));
-               }
                if (slot != 1 && slot != 2) {
                        throw new CRException(String.format(
                        "NFC Yubikey slot is %d, can be 1 or 2",
@@ -62,33 +57,44 @@ public class YkNeo {
                        "NFC select error code: %02x:%02x",
                        resp[length - 2], resp[length - 1]));
                }
-               byte[] crApdu = new byte[6+challenge.length];
-               crApdu[0] = 0x00; // CLA
-               crApdu[1] = 0x01; // INS
-               switch (slot) {
-               case 1: crApdu[2] = SLOT_CHAL_HMAC1; break; // P1
-               case 2: crApdu[2] = SLOT_CHAL_HMAC2; break; // P1
-               }
-               crApdu[3] = 0x00; // P2
-               crApdu[4] = (byte)challenge.length; // Lc
-               System.arraycopy(challenge, 0, crApdu, 5,
-                                       challenge.length); // Payload
-               crApdu[5+challenge.length] = 22; // Le
-               resp = isoTag.transceive(crApdu);
-               length = resp.length;
-               if (resp[length - 2] != (byte)0x90 ||
-                   resp[length - 1] != 0x00) {
-                       throw new CRException(String.format(
-                       "NFC CR error code: %02x:%02x",
-                       resp[length - 2], resp[length - 1]));
-               }
-               if (length <= 2) {
-                       throw new CRException(String.format(
-                       "NFC wrong response size: only %d bytes",
-                       length-2));
-               }
                ArrayList<String> rset = new ArrayList<String>();
-               rset.add(hex(Arrays.copyOf(resp, length-2)));
+
+               Iterator itr = cset.iterator();
+               while (itr.hasNext()) {
+                       byte[] challenge = unhex((String)itr.next());
+                       if (challenge.length > 127) {
+                               throw new CRException(String.format(
+                               "NFC challenge size too big: %d",
+                               challenge.length));
+                       }
+                       byte[] crApdu = new byte[6+challenge.length];
+                       crApdu[0] = 0x00; // CLA
+                       crApdu[1] = 0x01; // INS
+                       switch (slot) {
+                       case 1: crApdu[2] = SLOT_CHAL_HMAC1; break; // P1
+                       case 2: crApdu[2] = SLOT_CHAL_HMAC2; break; // P1
+                       }
+                       crApdu[3] = 0x00; // P2
+                       crApdu[4] = (byte)challenge.length; // Lc
+                       System.arraycopy(challenge, 0, crApdu, 5,
+                                               challenge.length); // Payload
+                       crApdu[5+challenge.length] = 22; // Le
+                       resp = isoTag.transceive(crApdu);
+                       length = resp.length;
+                       if (resp[length - 2] != (byte)0x90 ||
+                           resp[length - 1] != 0x00) {
+                               throw new CRException(String.format(
+                               "NFC CR error code: %02x:%02x",
+                               resp[length - 2], resp[length - 1]));
+                       }
+                       if (length <= 2) {
+                               throw new CRException(String.format(
+                               "NFC wrong response size: only %d bytes",
+                               length-2));
+                       }
+                       rset.add(hex(Arrays.copyOf(resp, length-2)));
+               }
+
                return rset;
        }