From: Eugene Crosser Date: Fri, 10 May 2013 11:38:41 +0000 (+0400) Subject: handle multivalue challenges X-Git-Url: http://www.average.org/gitweb/?p=YkNeoCR.git;a=commitdiff_plain;h=edfc8d9f2aad0bd7c0810d9f67a67e3db4b266c0 handle multivalue challenges --- diff --git a/res/values/strings.xml b/res/values/strings.xml index 9b83033..83cb008 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2,8 +2,24 @@ YkNeo CR +

Challenge-Response Provider

+

using Yubico\'s Yubikey Neo NFC token

+ +

+You need to set up a slot in the Neo to use with CHAL-HMAC +mode, like this: +

+
+  ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible
+
+

+This application does not do anything itself, it provides a way for other +applications to use the NFC token for encryption and authentication purposes. +

+

+The slot number used for the above command must be selected below: +

]]>
Set Slot diff --git a/src/org/average/nfcauthcr/Enroll.java b/src/org/average/nfcauthcr/Enroll.java index d8e623d..3e012d2 100644 --- a/src/org/average/nfcauthcr/Enroll.java +++ b/src/org/average/nfcauthcr/Enroll.java @@ -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; diff --git a/src/org/average/nfcauthcr/QueryCrToken.java b/src/org/average/nfcauthcr/QueryCrToken.java index 8e5c463..68a8d0e 100644 --- a/src/org/average/nfcauthcr/QueryCrToken.java +++ b/src/org/average/nfcauthcr/QueryCrToken.java @@ -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 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 { diff --git a/src/org/average/nfcauthcr/YkNeo.java b/src/org/average/nfcauthcr/YkNeo.java index 864e7b0..96f3e0f 100644 --- a/src/org/average/nfcauthcr/YkNeo.java +++ b/src/org/average/nfcauthcr/YkNeo.java @@ -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 doChalResp(IsoDep isoTag, int slot, ArrayList 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 rset = new ArrayList(); - 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; }