1
0
mirror of https://github.com/moparisthebest/keepass2android synced 2025-03-02 02:01:43 -05:00

NfcChallenge code by Ben Rush

This commit is contained in:
Philipp Crocoll 2014-03-25 20:51:41 +01:00
parent 736bbd5ec3
commit dfe0716635
3 changed files with 122 additions and 8 deletions
src/keepass2android

@ -45,6 +45,7 @@ using MemoryStream = System.IO.MemoryStream;
using Object = Java.Lang.Object;
using Process = Android.OS.Process;
using String = System.String;
using KeeChallenge;
namespace keepass2android
{
@ -60,7 +61,9 @@ namespace keepass2android
None = 0,
KeyFile = 1,
Otp = 2,
OtpRecovery = 3
OtpRecovery = 3,
Chal = 4,
ChalRecovery = 5
}
public const String KeyDefaultFilename = "defaultFileName";
@ -76,9 +79,12 @@ namespace keepass2android
private const string ShowpasswordKey = "ShowPassword";
private const string KeyProviderIdOtp = "KP2A-OTP";
private const string KeyProviderIdOtpRecovery = "KP2A-OTPSecret";
private const string KeyProviderIdChallenge = "KP2A-Chal";
private const string KeyProviderIdChallengeRecovery = "KP2A-ChalSecret";
private const int RequestCodePrepareDbFile = 1000;
private const int RequestCodePrepareOtpAuxFile = 1001;
private const int RequestCodePrepareChalAuxFile = 1001;
private Task<MemoryStream> _loadDbTask;
@ -104,6 +110,10 @@ namespace keepass2android
return KeyProviders.Otp;
if (_keyFileOrProvider == KeyProviderIdOtpRecovery)
return KeyProviders.OtpRecovery;
if (_keyFileOrProvider == KeyProviderIdChallenge)
return KeyProviders.Chal;
if (_keyFileOrProvider == KeyProviderIdChallengeRecovery)
return KeyProviders.ChalRecovery;
return KeyProviders.KeyFile;
}
}
@ -113,6 +123,8 @@ namespace keepass2android
private bool _starting;
private OtpInfo _otpInfo;
private ChallengeInfo _chalInfo;
private byte[] _challengeResponse;
private readonly int[] _otpTextViewIds = new[] {Resource.Id.otp1, Resource.Id.otp2, Resource.Id.otp3, Resource.Id.otp4, Resource.Id.otp5, Resource.Id.otp6};
private const string OtpInfoKey = "OtpInfoKey";
private const string EnteredOtpsKey = "EnteredOtpsKey";
@ -120,6 +132,7 @@ namespace keepass2android
private const string PasswordKey = "PasswordKey";
private const string KeyFileOrProviderKey = "KeyFileOrProviderKey";
private ActivityDesign _design;
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
@ -130,7 +143,7 @@ namespace keepass2android
public PasswordActivity()
{
_design = new ActivityDesign(this);
_design = new ActivityDesign(this);
}
@ -259,12 +272,26 @@ namespace keepass2android
if (requestCode == RequestCodePrepareDbFile)
PerformLoadDatabase();
if (requestCode == RequestCodePrepareOtpAuxFile)
LoadOtpFile();
{
if (_keyFileOrProvider == KeyProviderIdChallenge)
{
if (!LoadChalFile()) break;
Intent chalIntent = new Intent(this, typeof(NfcChalActivity));
chalIntent.PutExtra("challenge", _chalInfo.Challenge);
StartActivityForResult(chalIntent, 0);
} else {
LoadOtpFile ();
}
}
break;
case NfcChalActivity.SUCCESS:
_challengeResponse = data.GetByteArrayExtra("chalresp");
break;
}
}
private void LoadOtpFile()
{
new LoadingDialog<object, object, object>(this, true,
@ -301,6 +328,33 @@ namespace keepass2android
).Execute();
}
private bool LoadChalFile()
{
try
{
IFileStorage fileStorage = App.Kp2a.GetOtpAuxFileStorage(_ioConnection);
IOConnectionInfo iocAux = fileStorage.GetFilePath(fileStorage.GetParentPath(_ioConnection),
fileStorage.GetFilenameWithoutPathAndExt(_ioConnection) + ".xml");
_chalInfo = ChallengeInfo.Load(iocAux);
}
catch (Exception e)
{
Kp2aLog.Log(e.ToString());
return false;
}
if (_chalInfo == null)
{
Toast.MakeText(this,
GetString(Resource.String.CouldntLoadChalAuxFile) + " " + GetString(Resource.String.CouldntLoadChalAuxFile_Hint)
, ToastLength.Long).Show();
return false;
}
return true;
}
private void ShowOtpEntry(IList<string> prefilledOtps)
{
FindViewById(Resource.Id.otpInitView).Visibility = ViewStates.Gone;
@ -585,6 +639,12 @@ namespace keepass2android
case 3:
_keyFileOrProvider = KeyProviderIdOtpRecovery;
break;
case 4:
_keyFileOrProvider = KeyProviderIdChallenge;
break;
case 5:
_keyFileOrProvider = KeyProviderIdChallengeRecovery;
break;
default:
throw new Exception("Unexpected position " + args.Position + " / " +
((ICursor) ((AdapterView) sender).GetItemAtPosition(args.Position)).GetString(1));
@ -592,10 +652,10 @@ namespace keepass2android
UpdateKeyProviderUiState();
};
FindViewById(Resource.Id.init_otp).Click += (sender, args) =>
{
App.Kp2a.GetOtpAuxFileStorage(_ioConnection)
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), _ioConnection,
RequestCodePrepareOtpAuxFile, false);
{
App.Kp2a.GetOtpAuxFileStorage(_ioConnection)
.PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), _ioConnection,
RequestCodePrepareOtpAuxFile, false);
};
}
else
@ -669,6 +729,12 @@ namespace keepass2android
case KeyProviders.OtpRecovery:
FindViewById(Resource.Id.pass_ok).Enabled = FindViewById<EditText>(Resource.Id.pass_otpsecret).Text != "" && _password != "";
break;
case KeyProviders.Chal:
FindViewById(Resource.Id.pass_ok).Enabled = true;
break;
case KeyProviders.ChalRecovery:
FindViewById(Resource.Id.pass_ok).Enabled = true;
break;
default:
throw new ArgumentOutOfRangeException();
}
@ -690,8 +756,14 @@ namespace keepass2android
{
FindViewById(Resource.Id.otps_pending).Visibility = _pendingOtps.Count > 0 ? ViewStates.Visible : ViewStates.Gone;
}
if (KeyProviderType == KeyProviders.Chal)
{
FindViewById (Resource.Id.otpView).Visibility = ViewStates.Visible;
}
UpdateOkButtonState();
}
private void PerformLoadDatabase()
{
@ -744,6 +816,29 @@ namespace keepass2android
return;
}
}
else if (KeyProviderType == KeyProviders.Chal)
{
byte[] secret = KeeChallenge.KeeChallengeProv.GetSecret(_chalInfo, _challengeResponse);
if (secret != null)
{
compositeKey.AddUserKey(new KcpCustomKey(KeeChallengeProv.Name, secret, true));
ChallengeInfo temp = KeeChallengeProv.Encrypt(secret);
IFileStorage fileStorage = App.Kp2a.GetOtpAuxFileStorage(_ioConnection);
IOConnectionInfo iocAux = fileStorage.GetFilePath(fileStorage.GetParentPath(_ioConnection),
fileStorage.GetFilenameWithoutPathAndExt(_ioConnection) + ".xml");
if(!temp.Save(iocAux))
{
Toast.MakeText(this, Resource.String.ErrorUpdatingChalAuxFile, ToastLength.Long).Show();
return;
}
Array.Clear(secret, 0, secret.Length);
}
else
{
Toast.MakeText(this, Resource.String.bad_resp, ToastLength.Long).Show();
return;
}
}
CheckBox cbQuickUnlock = (CheckBox) FindViewById(Resource.Id.enable_quickunlock);
App.Kp2a.SetQuickUnlockEnabled(cbQuickUnlock.Checked);

@ -491,6 +491,8 @@ Erstes öffentliches Release</string>
<item>Kennwort + Schlüsseldatei</item>
<item>Kennwort + OTP</item>
<item>Kennwort + OTP Secret (Recovery-Modus)</item>
<item>Password + Challenge-Response</item>
<item>Password + Challenge-Response secret (recovery mode)</item>
</string-array>
<string-array name="AcceptAllServerCertificates_options">
<item>Fehler bei Zertifikatsvalidierung ignorieren</item>

@ -381,7 +381,7 @@
<string name="error_adding_keyfile">Error while adding the keyfile!</string>
<string name="init_otp">Load OTP auxiliary file…</string>
<string name="init_otp">Load auxiliary file…</string>
<string name="otp_explanation">Enter the next One-time-passwords (OTPs). Swipe your Yubikey NEO at the back of your device to enter via NFC.</string>
<string name="otp_hint">OTP %1$d</string>
<string name="CouldntLoadOtpAuxFile">Could not load auxiliary OTP file!</string>
@ -396,6 +396,21 @@
<string name="ErrorUpdatingOtpAuxFile">Error updating OTP auxiliary file!</string>
<string name="SavingOtpAuxFile">Saving auxiliary OTP file…</string>
<string name="challenging">Challenging</string>
<string name="swipe">Please swipe your YubiKey NEO</string>
<string name="swipe_and_hold">Please swipe and hold your YubiKey NEO</string>
<string name="totp">Oath TOTP</string>
<string name="challenge_failed">Failed getting response, is the YubiKey configured in challenge-response mode?</string>
<string name="lost_tag">YubiKey NEO lost during operation</string>
<string name="tag_error">Error communication with YubiKey: </string>
<string name="nfc_off">NFC seems to be off, turn on?</string>
<string name="no_nfc">This device seems to not support NFC</string>
<string name="response_error">YubiKey Error</string>
<string name="bad_resp">The response from the YubiKey is incorrect</string>
<string name="CouldntLoadChalAuxFile">Could not load auxiliary challenge file!</string>
<string name="CouldntLoadChalAuxFile_Hint">Please use the KeeChallenge plugin in KeePass 2.x (PC) to configure your database for use with challenge-response!</string>
<string name="ErrorUpdatingChalAuxFile">Error updating OTP auxiliary file!</string>
<string name="loading">Loading…</string>
<string name="get_regular_version">Get more storage types</string>
@ -555,6 +570,8 @@ Initial public release
<item>Password + Key file</item>
<item>Password + OTP</item>
<item>Password + OTP secret (recovery mode)</item>
<item>Password + Challenge-Response</item>
<item>Password + Challenge-Response secret (recovery mode)</item>
</string-array>
<string-array name="AcceptAllServerCertificates_options">
<item>Ignore certificate validation failures</item>