Renamed classes
authorEugene Crosser <crosser@average.org>
Fri, 3 May 2013 08:21:41 +0000 (12:21 +0400)
committerEugene Crosser <crosser@average.org>
Fri, 3 May 2013 08:21:41 +0000 (12:21 +0400)
AndroidManifest.xml
src/org/average/nfcauthcr/Check.java [new file with mode: 0644]
src/org/average/nfcauthcr/Enroll.java [new file with mode: 0644]
src/org/average/nfcauthcr/NFCAuthCRCheck.java [deleted file]
src/org/average/nfcauthcr/NFCAuthCREnroll.java [deleted file]
src/org/average/nfcauthcr/NFCAuthCRYubiNeo.java [deleted file]
src/org/average/nfcauthcr/YkNeo.java [new file with mode: 0644]

index efcae302e317cf8b84de6846edc2ea315e6202a1..684cae96aabbb3512ba68c17805408f19c89b823 100644 (file)
                  android:allowBackup="true"
                  android:theme="@style/AppTheme">
 
                  android:allowBackup="true"
                  android:theme="@style/AppTheme">
 
-        <activity android:name=".NFCAuthCREnroll"
+        <activity android:name=".Enroll"
                   android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
                   android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name=".NFCAuthCRCheck"
+        <activity android:name=".Check"
                   android:label="@string/app_name">
         </activity>
 
                   android:label="@string/app_name">
         </activity>
 
diff --git a/src/org/average/nfcauthcr/Check.java b/src/org/average/nfcauthcr/Check.java
new file mode 100644 (file)
index 0000000..c3738f7
--- /dev/null
@@ -0,0 +1,122 @@
+package org.average.nfcauthcr;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.nfc.TagLostException;
+import android.nfc.tech.IsoDep;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.average.nfcauthcr.YkNeo;
+
+public class Check extends Activity {
+
+       private final String TAG = getClass().getName();
+
+       private AlertDialog swipeDialog;
+       private PendingIntent tagIntent;
+
+       @Override
+       protected void onResume() {
+               super.onResume();
+               Log.v(TAG, "Starting the work");
+
+               Intent intent = getIntent();
+               setResult(RESULT_CANCELED);
+               if (swipeDialog != null) {
+                       swipeDialog.dismiss();
+                       swipeDialog = null;
+               }
+               int slot = intent.getIntExtra("slot", -1);
+               if (slot > 0) {
+                       swipeDialog = makeDialog();
+                       swipeDialog.show();
+                       enableDispatch(slot);
+               }
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+               Log.v(TAG, "Finished the work");
+
+               if(swipeDialog != null) {
+                       swipeDialog.dismiss();
+                       swipeDialog = null;
+               }
+               disableDispatch();
+       }
+
+       public void onNewIntent(Intent intent) {
+               Log.v(TAG, "NFC Intent arrived");
+               int slot = intent.getIntExtra("slot", -1);
+               byte[] challenge = intent.getByteArrayExtra("challenge");
+               if (slot <= 0) return;
+               Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
+               if (tag == null) return;
+               IsoDep isoTag = IsoDep.get(tag);
+               byte[] response = YkNeo.doChallengeYubiKey(
+                                               isoTag, slot, challenge);
+               if (response != null) {
+                       Intent data = getIntent();
+                       data.putExtra("response", response);
+                       setResult(RESULT_OK, data);
+               }
+               finish();
+       }
+
+       private AlertDialog makeDialog() {
+               AlertDialog.Builder builder = new AlertDialog.Builder(this);
+               builder.setTitle(R.string.challenging);
+               builder.setMessage(R.string.swipe);
+               builder.setOnCancelListener(
+                               new DialogInterface.OnCancelListener() {
+                       public void onCancel(DialogInterface dialog) {
+                               finish();
+                       }
+               });
+               return builder.create();
+       }
+
+       private void enableDispatch(int slot) {
+               Intent intent = getIntent();
+               intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+               intent.putExtra("slot", slot);
+               tagIntent = PendingIntent.getActivity(this, 0, intent, 0);
+               IntentFilter iso =
+                       new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
+               NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
+               if (adapter == null) {
+                       Toast.makeText(this, R.string.no_nfc,
+                                               Toast.LENGTH_LONG).show();
+                       finish();
+                       return;
+               }
+               if (! adapter.isEnabled()) {
+                       Toast.makeText(this, R.string.nfc_disabled,
+                                               Toast.LENGTH_LONG).show();
+                       finish();
+                       return;
+               }
+               adapter.enableForegroundDispatch(
+                       this, tagIntent, new IntentFilter[] {iso},
+                       new String[][] {new String[] {IsoDep.class.getName()}});
+       }
+
+       private void disableDispatch() {
+               if (tagIntent != null) {
+                       tagIntent.cancel();
+                       tagIntent = null;
+               }
+               NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
+               if (adapter != null) {
+                       adapter.disableForegroundDispatch(this);
+               }
+       }
+}
diff --git a/src/org/average/nfcauthcr/Enroll.java b/src/org/average/nfcauthcr/Enroll.java
new file mode 100644 (file)
index 0000000..9f9d535
--- /dev/null
@@ -0,0 +1,143 @@
+package org.average.nfcauthcr;
+
+import java.util.Random;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.preference.PreferenceManager;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.DialogInterface;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.RadioButton;
+
+import org.average.nfcauthcr.Check;
+
+public class Enroll extends Activity {
+
+       private final String TAG = getClass().getName();
+
+       private static boolean waitingForResult = false;
+       private static SharedPreferences prefs;
+       private static int slot;
+
+       @Override
+       protected void onCreate(Bundle savedInstanceState)
+       {
+               super.onCreate(savedInstanceState);
+               Log.v(TAG, "Starting");
+               prefs = PreferenceManager.getDefaultSharedPreferences(this);
+       }
+
+       @Override
+       protected void onResume() {
+               super.onResume();
+               setContentView(R.layout.main);
+               slot = prefs.getInt("slot_number", -1);
+               Log.v(TAG, "found saved slot value " + slot);
+               RadioButton btn = null;
+               switch (slot) {
+               case 1: btn = (RadioButton)findViewById(R.id.slot_1);
+                       break;
+               case 2: btn = (RadioButton)findViewById(R.id.slot_2);
+                       break;
+               }
+               if (btn != null) btn.setChecked(true);
+       }
+
+       @Override
+       protected void onPause() {
+               super.onPause();
+               Log.v(TAG, "Going inactive, try to stop");
+               if (!waitingForResult) { finish(); }
+       }
+
+       @Override
+       protected void onStop() {
+               super.onStop();
+               Log.v(TAG, "Stop requested");
+       }
+
+       public void onSlotSelectionClicked(View view) {
+               Log.v(TAG, "Radio Button selected");
+               if (! ((RadioButton) view).isChecked()) return;
+               switch(view.getId()) {
+               case R.id.slot_1: slot=1; break;
+               case R.id.slot_2: slot=2; break;
+               }
+               Editor editor = prefs.edit();
+               editor.putInt("slot_number", slot);
+               editor.commit();
+               Log.v(TAG, "stored slot number " + slot);
+       }
+
+       public void onEnrollClicked(View view) {
+               Log.v(TAG, "Enroll clicked");
+               if (slot > 0) {
+                       runEnrollment(slot);
+               } else {
+                       showEnrollResult("Must specify which slot to use");
+               }
+       }
+
+       public void onActivityResult(int requestCode, int resultCode,
+                                       Intent intent) {
+               Log.v(TAG, "Got activity result");
+               waitingForResult = false;
+
+               if (resultCode != RESULT_OK) {
+                       Log.v(TAG, "Error result code " + resultCode);
+                       return;
+               }
+               byte[] challenge = intent.getByteArrayExtra("challenge");
+               Log.v(TAG, "Challenge is \"" + hex(challenge) + "\"");
+               byte[] response = intent.getByteArrayExtra("response");
+               Log.v(TAG, "Response is  \"" + hex(response) + "\"");
+               Editor editor = prefs.edit();
+               editor.putString("challenge", hex(challenge));
+               editor.putString("response", hex(response));
+               editor.commit();
+               Log.v(TAG, "stored new challenge and response");
+       }
+
+       private void showEnrollResult(final String msg) {
+               Log.v(TAG, "Show result: \"" + msg + "\"");
+
+               AlertDialog.Builder builder = new AlertDialog.Builder(this);
+               builder.setTitle(R.string.enrollresult);
+               builder.setMessage(msg);
+               builder.setPositiveButton(android.R.string.ok,
+                               new DialogInterface.OnClickListener() {
+                       public void onClick(DialogInterface dialog, int which) {
+                               dialog.dismiss();
+                               if (!waitingForResult) { finish(); }
+                       }
+               });
+               AlertDialog dialog = builder.create();
+               dialog.show();
+       }
+
+       private void runEnrollment(int slot) {
+               Random rng = new Random();
+               byte[] challenge = new byte[63];
+               rng.nextBytes(challenge);
+               Log.v(TAG, "Random challenge: " + hex(challenge));
+               Log.v(TAG, "Launching challenging activity");
+               Intent crIntent = new Intent(this, NFCAuthCRCheck.class);
+               crIntent.putExtra("slot", slot);
+               crIntent.putExtra("challenge", challenge);
+               this.startActivityForResult(crIntent, 0);
+               waitingForResult = true;
+       }
+
+       private String hex(byte[] a) {
+               StringBuilder sb = new StringBuilder();
+               if (a == null) return "<null>";
+               for (byte b: a) sb.append(String.format("%02x", b&0xff));
+               return sb.toString();
+       }
+}
diff --git a/src/org/average/nfcauthcr/NFCAuthCRCheck.java b/src/org/average/nfcauthcr/NFCAuthCRCheck.java
deleted file mode 100644 (file)
index ea37128..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.average.nfcauthcr;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.PendingIntent;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.TagLostException;
-import android.nfc.tech.IsoDep;
-import android.util.Log;
-import android.widget.Toast;
-
-import org.average.nfcauthcr.NFCAuthCRYubiNeo;
-
-public class NFCAuthCRCheck extends Activity {
-
-       private final String TAG = getClass().getName();
-
-       private AlertDialog swipeDialog;
-       private PendingIntent tagIntent;
-
-       @Override
-       protected void onResume() {
-               super.onResume();
-               Log.v(TAG, "Starting the work");
-
-               Intent intent = getIntent();
-               setResult(RESULT_CANCELED);
-               if (swipeDialog != null) {
-                       swipeDialog.dismiss();
-                       swipeDialog = null;
-               }
-               int slot = intent.getIntExtra("slot", -1);
-               if (slot > 0) {
-                       swipeDialog = makeDialog();
-                       swipeDialog.show();
-                       enableDispatch(slot);
-               }
-       }
-
-       @Override
-       protected void onPause() {
-               super.onPause();
-               Log.v(TAG, "Finished the work");
-
-               if(swipeDialog != null) {
-                       swipeDialog.dismiss();
-                       swipeDialog = null;
-               }
-               disableDispatch();
-       }
-
-       public void onNewIntent(Intent intent) {
-               Log.v(TAG, "NFC Intent arrived");
-               int slot = intent.getIntExtra("slot", -1);
-               byte[] challenge = intent.getByteArrayExtra("challenge");
-               if (slot <= 0) return;
-               Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
-               if (tag == null) return;
-               IsoDep isoTag = IsoDep.get(tag);
-               byte[] response = NFCAuthCRYubiNeo.doChallengeYubiKey(
-                                               isoTag, slot, challenge);
-               if (response != null) {
-                       Intent data = getIntent();
-                       data.putExtra("response", response);
-                       setResult(RESULT_OK, data);
-               }
-               finish();
-       }
-
-       private AlertDialog makeDialog() {
-               AlertDialog.Builder builder = new AlertDialog.Builder(this);
-               builder.setTitle(R.string.challenging);
-               builder.setMessage(R.string.swipe);
-               builder.setOnCancelListener(
-                               new DialogInterface.OnCancelListener() {
-                       public void onCancel(DialogInterface dialog) {
-                               finish();
-                       }
-               });
-               return builder.create();
-       }
-
-       private void enableDispatch(int slot) {
-               Intent intent = getIntent();
-               intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
-               intent.putExtra("slot", slot);
-               tagIntent = PendingIntent.getActivity(this, 0, intent, 0);
-               IntentFilter iso =
-                       new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
-               NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
-               if (adapter == null) {
-                       Toast.makeText(this, R.string.no_nfc,
-                                               Toast.LENGTH_LONG).show();
-                       finish();
-                       return;
-               }
-               if (! adapter.isEnabled()) {
-                       Toast.makeText(this, R.string.nfc_disabled,
-                                               Toast.LENGTH_LONG).show();
-                       finish();
-                       return;
-               }
-               adapter.enableForegroundDispatch(
-                       this, tagIntent, new IntentFilter[] {iso},
-                       new String[][] {new String[] {IsoDep.class.getName()}});
-       }
-
-       private void disableDispatch() {
-               if (tagIntent != null) {
-                       tagIntent.cancel();
-                       tagIntent = null;
-               }
-               NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
-               if (adapter != null) {
-                       adapter.disableForegroundDispatch(this);
-               }
-       }
-}
diff --git a/src/org/average/nfcauthcr/NFCAuthCREnroll.java b/src/org/average/nfcauthcr/NFCAuthCREnroll.java
deleted file mode 100644 (file)
index 50933cb..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.average.nfcauthcr;
-
-import java.util.Random;
-
-import android.os.Bundle;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.preference.PreferenceManager;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.content.DialogInterface;
-import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-import android.widget.RadioButton;
-
-import org.average.nfcauthcr.NFCAuthCRCheck;
-
-public class NFCAuthCREnroll extends Activity {
-
-       private final String TAG = getClass().getName();
-
-       private static boolean waitingForResult = false;
-       private static SharedPreferences prefs;
-       private static int slot;
-
-       @Override
-       protected void onCreate(Bundle savedInstanceState)
-       {
-               super.onCreate(savedInstanceState);
-               Log.v(TAG, "Starting");
-               prefs = PreferenceManager.getDefaultSharedPreferences(this);
-       }
-
-       @Override
-       protected void onResume() {
-               super.onResume();
-               setContentView(R.layout.main);
-               slot = prefs.getInt("slot_number", -1);
-               Log.v(TAG, "found saved slot value " + slot);
-               RadioButton btn = null;
-               switch (slot) {
-               case 1: btn = (RadioButton)findViewById(R.id.slot_1);
-                       break;
-               case 2: btn = (RadioButton)findViewById(R.id.slot_2);
-                       break;
-               }
-               if (btn != null) btn.setChecked(true);
-       }
-
-       @Override
-       protected void onPause() {
-               super.onPause();
-               Log.v(TAG, "Going inactive, try to stop");
-               if (!waitingForResult) { finish(); }
-       }
-
-       @Override
-       protected void onStop() {
-               super.onStop();
-               Log.v(TAG, "Stop requested");
-       }
-
-       public void onSlotSelectionClicked(View view) {
-               Log.v(TAG, "Radio Button selected");
-               if (! ((RadioButton) view).isChecked()) return;
-               switch(view.getId()) {
-               case R.id.slot_1: slot=1; break;
-               case R.id.slot_2: slot=2; break;
-               }
-               Editor editor = prefs.edit();
-               editor.putInt("slot_number", slot);
-               editor.commit();
-               Log.v(TAG, "stored slot number " + slot);
-       }
-
-       public void onEnrollClicked(View view) {
-               Log.v(TAG, "Enroll clicked");
-               if (slot > 0) {
-                       runEnrollment(slot);
-               } else {
-                       showEnrollResult("Must specify which slot to use");
-               }
-       }
-
-       public void onActivityResult(int requestCode, int resultCode,
-                                       Intent intent) {
-               Log.v(TAG, "Got activity result");
-               waitingForResult = false;
-
-               if (resultCode != RESULT_OK) {
-                       Log.v(TAG, "Error result code " + resultCode);
-                       return;
-               }
-               byte[] challenge = intent.getByteArrayExtra("challenge");
-               Log.v(TAG, "Challenge is \"" + hex(challenge) + "\"");
-               byte[] response = intent.getByteArrayExtra("response");
-               Log.v(TAG, "Response is  \"" + hex(response) + "\"");
-               Editor editor = prefs.edit();
-               editor.putString("challenge", hex(challenge));
-               editor.putString("response", hex(response));
-               editor.commit();
-               Log.v(TAG, "stored new challenge and response");
-       }
-
-       private void showEnrollResult(final String msg) {
-               Log.v(TAG, "Show result: \"" + msg + "\"");
-
-               AlertDialog.Builder builder = new AlertDialog.Builder(this);
-               builder.setTitle(R.string.enrollresult);
-               builder.setMessage(msg);
-               builder.setPositiveButton(android.R.string.ok,
-                               new DialogInterface.OnClickListener() {
-                       public void onClick(DialogInterface dialog, int which) {
-                               dialog.dismiss();
-                               if (!waitingForResult) { finish(); }
-                       }
-               });
-               AlertDialog dialog = builder.create();
-               dialog.show();
-       }
-
-       private void runEnrollment(int slot) {
-               Random rng = new Random();
-               byte[] challenge = new byte[63];
-               rng.nextBytes(challenge);
-               Log.v(TAG, "Random challenge: " + hex(challenge));
-               Log.v(TAG, "Launching challenging activity");
-               Intent crIntent = new Intent(this, NFCAuthCRCheck.class);
-               crIntent.putExtra("slot", slot);
-               crIntent.putExtra("challenge", challenge);
-               this.startActivityForResult(crIntent, 0);
-               waitingForResult = true;
-       }
-
-       private String hex(byte[] a) {
-               StringBuilder sb = new StringBuilder();
-               if (a == null) return "<null>";
-               for (byte b: a) sb.append(String.format("%02x", b&0xff));
-               return sb.toString();
-       }
-}
diff --git a/src/org/average/nfcauthcr/NFCAuthCRYubiNeo.java b/src/org/average/nfcauthcr/NFCAuthCRYubiNeo.java
deleted file mode 100644 (file)
index 67596e6..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.average.nfcauthcr;
-
-import java.io.IOException;
-import java.util.Arrays;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.TagLostException;
-import android.nfc.tech.IsoDep;
-import android.util.Log;
-
-import org.average.nfcauthcr.NFCAuthCRYubiNeo;
-
-public class NFCAuthCRYubiNeo {
-
-       private static final String TAG = "NFCAuthCRYubiNeo";
-
-       // Is it CCID APDU? ISO 7816-4?
-
-       // 00 A4 04 00 xx AID - GlobalPlatform - SELECT
-       // Le send data = 07: A0 00 00 05 27 20 01
-       // Le recv data = 00
-       private static final byte[] selectCommand =
-               {0x00, (byte) 0xA4, 0x04, 0x00, 0x07, (byte) 0xA0,
-                0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x00};
-
-       private static final byte[] crCommand =
-               {0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00};
-
-       private static final byte SLOT_CHAL_HMAC1 = 0x30;
-       private static final byte SLOT_CHAL_HMAC2 = 0x38;
-
-       public static final byte[] doChallengeYubiKey(IsoDep isoTag, int slot,
-                                               byte[] challenge) {
-               try {
-                       isoTag.connect();
-                       byte[] resp = isoTag.transceive(selectCommand);
-                       int length = resp.length;
-                       Log.v(TAG, "response to select length is " + length);
-                       if (resp[length - 2] != (byte)0x90 ||
-                           resp[length - 1] != 0x00) {
-                               Log.v(TAG, "Wrong response to select");
-                               //Toast.makeText(this, R.string.tag_error,
-                               //              Toast.LENGTH_LONG).show();
-                               return null;
-                       }
-                       byte[] apdu = new byte[69];
-                       apdu[0] = 0x00; // CLA
-                       apdu[1] = 0x01; // INS
-                       switch (slot) {
-                       case 1: apdu[2] = SLOT_CHAL_HMAC1; break; // P1
-                       case 2: apdu[2] = SLOT_CHAL_HMAC2; break; // P1
-                       }
-                       apdu[3] = 0x00; // P2
-                       apdu[4] = 63;   // Lc
-                       System.arraycopy(challenge, 0, apdu, 5,
-                                                       challenge.length);
-                       apdu[apdu.length-1] = 22;
-                       resp = isoTag.transceive(apdu);
-                       length = resp.length;
-                       if (resp[length - 2] != (byte)0x90 ||
-                           resp[length - 1] != 0x00) {
-                               Log.v(TAG, "Wrong response to challenge");
-                               //Toast.makeText(this, R.string.tag_error,
-                               //              Toast.LENGTH_LONG).show();
-                               return null;
-                       }
-                       Log.v(TAG, "response to challenge length is " + length);
-                       return Arrays.copyOf(resp, length-2);
-               } catch (TagLostException e) {
-                       Log.v(TAG, e.getMessage());
-                       //Toast.makeText(this,
-                       //      R.string.tag_lost, Toast.LENGTH_LONG).show();
-               } catch (IOException e) {
-                       Log.v(TAG, e.getMessage());
-                       //Toast.makeText(this,
-                       //      getText(R.string.tag_error) +
-                       //      e.getMessage(),
-                       //      Toast.LENGTH_LONG).show();
-               }
-               return null;
-       }
-}
diff --git a/src/org/average/nfcauthcr/YkNeo.java b/src/org/average/nfcauthcr/YkNeo.java
new file mode 100644 (file)
index 0000000..a291eab
--- /dev/null
@@ -0,0 +1,75 @@
+package org.average.nfcauthcr;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.nfc.TagLostException;
+import android.nfc.tech.IsoDep;
+//import android.util.Log;
+
+public class YkNeo {
+
+       // This is a CCID APDU, ISO 7816-4.
+       // 00 A4 04 00 xx AID - GlobalPlatform - SELECT
+       // Lc, send data = 07: A0 00 00 05 27 20 01
+       // Le, recv data = 00
+       private static final byte[] selectApdu =
+               {0x00, (byte) 0xA4, 0x04, 0x00, 0x07, (byte) 0xA0,
+                0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x00};
+
+       private static final byte SLOT_CHAL_HMAC1 = 0x30;
+       private static final byte SLOT_CHAL_HMAC2 = 0x38;
+
+       public static final byte[] doChallengeYubiKey(IsoDep isoTag, int slot,
+                                               byte[] challenge) {
+               try {
+                       isoTag.connect();
+                       byte[] resp = isoTag.transceive(selectApdu);
+                       int length = resp.length;
+                       //Log.v(TAG, "response to select length is " + length);
+                       if (resp[length - 2] != (byte)0x90 ||
+                           resp[length - 1] != 0x00) {
+                               //Log.v(TAG, "Wrong response to select");
+                               //Toast.makeText(this, R.string.tag_error,
+                               //              Toast.LENGTH_LONG).show();
+                               return null;
+                       }
+                       byte[] crApdu = new byte[69];
+                       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] = 63;   // Lc
+                       System.arraycopy(challenge, 0, crApdu, 5,
+                                               challenge.length); // Payload
+                       crApdu[crApdu.length-1] = 22; // Le
+                       resp = isoTag.transceive(crApdu);
+                       length = resp.length;
+                       if (resp[length - 2] != (byte)0x90 ||
+                           resp[length - 1] != 0x00) {
+                               //Log.v(TAG, "Wrong response to challenge");
+                               //Toast.makeText(this, R.string.tag_error,
+                               //              Toast.LENGTH_LONG).show();
+                               return null;
+                       }
+                       //Log.v(TAG, "response to challenge length is " + length);
+                       return Arrays.copyOf(resp, length-2);
+               } catch (TagLostException e) {
+                       //Log.v(TAG, e.getMessage());
+                       //Toast.makeText(this,
+                       //      R.string.tag_lost, Toast.LENGTH_LONG).show();
+               } catch (IOException e) {
+                       //Log.v(TAG, e.getMessage());
+                       //Toast.makeText(this,
+                       //      getText(R.string.tag_error) +
+                       //      e.getMessage(),
+                       //      Toast.LENGTH_LONG).show();
+               }
+               return null;
+       }
+}