예제 #1
0
        private async void OnStageChanged(object sender, SecondaryAuthenticationFactorAuthenticationStageChangedEventArgs e)
        {
            switch (e.StageInfo.Stage)
            {
            case SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation:
                // Show welcome message
                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                    "",
                    SecondaryAuthenticationFactorAuthenticationMessage.LookingForDevice);

                break;

            case SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential:
                // TODO Authenticate device
                await DiscoverDevice();

                break;

            case SecondaryAuthenticationFactorAuthenticationStage.CredentialAuthenticated:
                /*if (e.StageInfo.DeviceId == _deviceId)
                 * {
                 *  // TODO Show notification on device about PC unlock
                 * }*/
                break;

            case SecondaryAuthenticationFactorAuthenticationStage.StoppingAuthentication:
                // TODO Quit from background task.
                SecondaryAuthenticationFactorAuthentication.AuthenticationStageChanged -= OnStageChanged;
                _exitEvent.Set();
                break;

            case SecondaryAuthenticationFactorAuthenticationStage.SuspendingAuthentication:
                break;
            }
        }
예제 #2
0
        // WARNING: Test code
        // This code should be in background task
        async void OnStageChanged(Object sender, SecondaryAuthenticationFactorAuthenticationStageChangedEventArgs args)
        {
            //ShowToastNotification("In StageChanged!" + args.StageInfo.Stage.ToString());
            if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation)
            {
                ShowToastNotification("Stage = WaitingForUserConfirmation");
                // This event is happening on a ThreadPool thread, so we need to dispatch to the UI thread.
                // Getting the dispatcher from the MainView works as long as we only have one view.
                String deviceName = "DeviceSimulator.";
                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                    deviceName,
                    SecondaryAuthenticationFactorAuthenticationMessage.SwipeUpWelcome);
            }
            else if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential)
            {
                ShowToastNotification("Stage = CollectingCredential");

                PerformAuthentication();
            }
            else
            {
                if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.StoppingAuthentication)
                {
                    SecondaryAuthenticationFactorAuthentication.AuthenticationStageChanged -= OnStageChanged;
                    opCompletedEvent.Set();
                }

                SecondaryAuthenticationFactorAuthenticationStage stage = args.StageInfo.Stage;
            }
        }
예제 #3
0
        async void OnStageChanged(Object sender, SecondaryAuthenticationFactorAuthenticationStageChangedEventArgs args)
        {
            //ShowToastNotification("In StageChanged!" + args.StageInfo.Stage.ToString());
            if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.CheckingDevicePresence)
            {
                Task t = PresenceMonitor();
                t.Wait();
                opCompletedEvent.Set();
                deferral.Complete();
                return;
            }
            if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation)
            {
                //ShowToastNotification("Stage = WaitingForUserConfirmation");
                // This event is happening on a ThreadPool thread, so we need to dispatch to the UI thread.
                // Getting the dispatcher from the MainView works as long as we only have one view.

                IReadOnlyList <SecondaryAuthenticationFactorInfo> deviceList = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
                    SecondaryAuthenticationFactorDeviceFindScope.User);

                String deviceName = deviceList.ElementAt(deviceList.Count() - 1).DeviceFriendlyName;

                string str = "\"" + deviceName + "\"";

                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                    str,
                    SecondaryAuthenticationFactorAuthenticationMessage.SwipeUpWelcome);
            }
            else if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential)
            {
                //ShowToastNotification("Stage = CollectingCredential");
                System.Diagnostics.Debug.WriteLine("[OnStageChanged] Perform Auth / auth trigger");
                try
                {
                    Task  t = PerformAuthentication();;
                    await t;
                    t = writeConnectedRegisteredDevices();
                    await t;
                }
                catch (Exception ex)
                {
                }
                finally
                {
                    deferral.Complete();
                }
            }
            else
            {
                if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.StoppingAuthentication)
                {
                    SecondaryAuthenticationFactorAuthentication.AuthenticationStageChanged -= OnStageChanged;
                    opCompletedEvent.Set();
                }

                SecondaryAuthenticationFactorAuthenticationStage stage = args.StageInfo.Stage;
            }
        }
예제 #4
0
        private async Task DiscoverDevice()
        {
            var authStageInfo = await SecondaryAuthenticationFactorAuthentication.GetAuthenticationStageInfoAsync();

            if (authStageInfo.Stage != SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential)
            {
                return;                                                                                               // Bad status!
            }
            findAuth = true;
            var deviceList = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(SecondaryAuthenticationFactorDeviceFindScope.User);

            var db          = new DatabaseContext();
            var devicesInDb = db.Devices.ToList();

            db.Dispose();
            IPDiscover.DiscoverIP();

            foreach (var device in deviceList)
            {
                var deviceInDb = devicesInDb.Find(d => d.DeviceId.ToString() == device.DeviceId);
                if (deviceInDb == null)
                {
                    continue;
                }
                var session = new DeviceAuthSession
                {
                    LastIP     = deviceInDb.LastConnectedHost,
                    MACAddress = deviceInDb.DeviceMacAddress,
                    DeviceID   = device.DeviceId,
                    DeviceInDb = deviceInDb
                };
                deviceSessions.Add(session);
            }
            while (findAuth)
            {
                foreach (var session in deviceSessions)
                {
                    switch (session.Status)
                    {
                    case DeviceStatus.NotConnected:
                        var payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(session.DeviceID));
                        var data    = Encoding.UTF8.GetBytes(DeviceDiscoverPrefix + payload);
                        if (!string.IsNullOrWhiteSpace(session.LastIP))
                        {
                            try
                            {
                                UDPListener.Send(session.LastIP, data);
                            }
                            catch (Exception)
                            {
                                // ignored
                            }
                        }

                        var ips = session.FindIPs()?.ToList();
                        if ((ips == null || !ips.Any()) && string.IsNullOrWhiteSpace(session.MACAddress) && IPDiscover.IsDiscoveryCompleted)
                        {
                            session.Status = DeviceStatus.Unreachable;
                            continue;
                        }

                        if (ips != null)
                        {
                            foreach (var ip in ips)
                            {
                                try
                                {
                                    UDPListener.Send(ip, data);
                                }
                                catch (Exception)
                                {
                                    // ignored
                                }
                            }
                        }
                        await UDPListener.Send(UDPListener.DeviceMulticastGroupAddress, data);

                        break;

                    case DeviceStatus.Unreachable:
                        deviceSessions.Remove(session);
                        break;

                    case DeviceStatus.Established:
                        findAuth = false;
                        break;
                    }
                }
                Thread.Sleep(1000);
            }

            Auth(deviceSessions.FirstOrDefault(s => s.Status == DeviceStatus.Established));
            CurrentSession = null;
        }
예제 #5
0
        private async void Auth(DeviceAuthSession session)
        {
            if (session == null)
            {
                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync("",
                                                                                               SecondaryAuthenticationFactorAuthenticationMessage.Invalid);

                return;
            }

            var deviceInDb = session.DeviceInDb;
            await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(deviceInDb.DeviceFriendlyName,
                                                                                           SecondaryAuthenticationFactorAuthenticationMessage.ReadyToSignIn);

            IBuffer svcAuthNonce = CryptographicBuffer.GenerateRandom(256 / 8);

            SecondaryAuthenticationFactorAuthenticationResult authResult = await
                                                                           SecondaryAuthenticationFactorAuthentication.StartAuthenticationAsync(
                session.DeviceID,
                svcAuthNonce);

            if (authResult.Status != SecondaryAuthenticationFactorAuthenticationStatus.Started)
            {
                var message = SecondaryAuthenticationFactorAuthenticationMessage.Invalid;
                switch (authResult.Status)
                {
                case SecondaryAuthenticationFactorAuthenticationStatus.DisabledByPolicy:
                    message = SecondaryAuthenticationFactorAuthenticationMessage.DisabledByPolicy;
                    break;

                case SecondaryAuthenticationFactorAuthenticationStatus.InvalidAuthenticationStage:
                    break;

                default:
                    return;
                }
                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(null, message);

                return;
            }

            var auth = authResult.Authentication;

            CurrentSession = session;
            for (int retries = 0; retries < 3; retries++)
            {
                var svcAuthHmac  = auth.ServiceAuthenticationHmac;
                var deviceNonce  = auth.DeviceNonce;
                var sessionNonce = auth.SessionNonce;
                var arr          = new byte[3 + svcAuthHmac.Length + deviceNonce.Length + sessionNonce.Length];
                arr[0] = (byte)svcAuthHmac.Length;
                arr[1] = (byte)deviceNonce.Length;
                arr[2] = (byte)sessionNonce.Length;
                Array.Copy(svcAuthHmac.ToArray(), 0, arr, 3, svcAuthHmac.Length);
                Array.Copy(deviceNonce.ToArray(), 0, arr, 3 + svcAuthHmac.Length, deviceNonce.Length);
                Array.Copy(sessionNonce.ToArray(), 0, arr, 3 + svcAuthHmac.Length + deviceNonce.Length, sessionNonce.Length);
                var payload = Convert.ToBase64String(arr);
                UDPListener.Send(session.LastIP, Encoding.UTF8.GetBytes(DeviceDiscoverPrefix + payload));

                AuthResultReceivedEvent = new ManualResetEvent(false);
                try
                {
                    AuthResultReceivedEvent.WaitOne(20000);
                }
                catch (Exception)
                {
                    // ignored
                }

                var result = session.ResultBytes;
                if (result == null || result.Length <= 2 || result.Length != 2 + result[0] + result[1])
                {
                    return;

                    /*await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync("",
                     *  SecondaryAuthenticationFactorAuthenticationMessage.TryAgain);
                     * await auth.AbortAuthenticationAsync("No data got.");
                     * continue;*/
                }

                var deviceHmac  = new Buffer(result[0]);
                var sessionHmac = new Buffer(result[1]);
                result.CopyTo(2, deviceHmac, 0, result[0]);
                result.CopyTo(2 + result[0], sessionHmac, 0, result[1]);
                var status = await auth.FinishAuthenticationAsync(deviceHmac, sessionHmac);

                switch (status)
                {
                case SecondaryAuthenticationFactorFinishAuthenticationStatus.Completed:
                    // The credential data is collected and ready for unlock
                    CurrentSession = null;
                    return;

                default:
                    await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync("",
                                                                                                   SecondaryAuthenticationFactorAuthenticationMessage.TryAgain);

                    break;
                }
            }
            await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(deviceInDb.DeviceFriendlyName,
                                                                                           SecondaryAuthenticationFactorAuthenticationMessage.UnauthorizedUser);

            CurrentSession = null;
        }
예제 #6
0
        private async Task PerformAuthentication()
        {
            string NanosATR             = "3b00";
            bool   showNotificationFlag = true;

            string selector = SmartCardReader.GetDeviceSelector();

            selector += " AND System.Devices.DeviceInstanceId:~~\"Ledger\"";
            DeviceInformationCollection devices = await DeviceInformation.FindAllAsync(selector);

            foreach (DeviceInformation device in devices)
            {
                SmartCardReader reader = await SmartCardReader.FromIdAsync(device.Id);

                SmartCardReaderStatus readerstatus = await reader.GetStatusAsync();

                //System.Diagnostics.Debug.WriteLine("Reader : " + reader.Name + " status : " + readerstatus.ToString());
                IReadOnlyList <SmartCard> cards = await reader.FindAllCardsAsync();

                foreach (SmartCard card in cards)
                {
                    try
                    {
                        IBuffer ATR = await card.GetAnswerToResetAsync();

                        string ATR_str = CryptographicBuffer.EncodeToHexString(ATR);

                        if (ATR_str.Equals(NanosATR))
                        {
                            Task  t = AuthenticateWithSmartCardAsync(card);
                            await t;
                        }
                    }
                    catch (CompanionDeviceNotFoundException ex)
                    {
                        ex.DisplayError();
                        break;
                    }
                    catch (UnableTogetNonceFromDeviceException ex)
                    {
                        ex.DisplayError();
                        showNotificationFlag = false;
                        break;
                    }
                    catch (UnauthorizedUserException ex)
                    {
                        ex.DisplayError();
                        await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                            "",
                            SecondaryAuthenticationFactorAuthenticationMessage.UnauthorizedUser);

                        //ShowToastNotification("Wrong Response");
                        showNotificationFlag = false;
                        break;
                    }
                    catch (LogInDeniedByUserException ex)
                    {
                        ex.DisplayError();
                        await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                            "",
                            SecondaryAuthenticationFactorAuthenticationMessage.TryAgain);

                        showNotificationFlag = false;
                        break;
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine("[PerformAuthentication] Unhandled Exception / " + ex.Message);
                        showNotificationFlag = false;
                        return;
                    }
                    finally
                    {
                    }
                }
            }
            if (showNotificationFlag)
            {
                var loader = new Windows.ApplicationModel.Resources.ResourceLoader();
                var str    = loader.GetString("LookingForDevice");

                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                    str,
                    SecondaryAuthenticationFactorAuthenticationMessage.LookingForDevicePluggedin);
            }
            showNotificationFlag = true;
        }
예제 #7
0
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            deferral = taskInstance.GetDeferral();

            StorageFolder folder = ApplicationData.Current.LocalFolder;

            //StorageFile logsFile = await folder.CreateFileAsync("BGtask.txt", CreationCollisionOption.OpenIfExists);
            //string txt = "[RUN]: " + DateTime.Now.ToString() + Environment.NewLine;
            //await FileIO.WriteTextAsync(logsFile, txt);

            // This event is signaled when the operation completes
            opCompletedEvent = new ManualResetEvent(false);
            SecondaryAuthenticationFactorAuthentication.AuthenticationStageChanged += OnStageChanged;
            //ShowToastNotification("BG Task Hit!");


            if (taskInstance.TriggerDetails is DeviceWatcherTriggerDetails)
            {
                DeviceWatcherTriggerDetails triggerDetails = (DeviceWatcherTriggerDetails)taskInstance.TriggerDetails;

                foreach (DeviceWatcherEvent e in triggerDetails.DeviceWatcherEvents)
                {
                    switch (e.Kind)
                    {
                    case DeviceWatcherEventKind.Add:
                        Debug.WriteLine("[RUN] Add: " + e.DeviceInformation.Id);
                        deferral = taskInstance.GetDeferral();
                        try
                        {
                            SecondaryAuthenticationFactorAuthenticationStageInfo authStageInfo = await SecondaryAuthenticationFactorAuthentication.GetAuthenticationStageInfoAsync();

                            SecondaryAuthenticationFactorAuthenticationStage stage = authStageInfo.Stage;
                            //Debugger.Break();
                            if ((authStageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation) ||
                                (authStageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential))
                            {
                                System.Diagnostics.Debug.WriteLine("[RUN] Perform Auth / plug trigger");
                                Task  t = PerformAuthentication();
                                await t;
                            }
                            //Debugger.Break();
                            if (e.DeviceInformation.Name.Contains("Ledger"))
                            {
                                Task  t = writeConnectedRegisteredDevices();
                                await t;
                            }
                        }
                        catch (Exception ex)
                        {
                        }
                        finally
                        {
                            deferral.Complete();
                        }
                        break;

                    //case DeviceWatcherEventKind.Update:
                    //    Debug.WriteLine("[RUN] Update: " + e.DeviceInformationUpdate.Id);
                    //    deferral = taskInstance.GetDeferral();
                    //
                    //    try
                    //    {
                    //        Task i = writeConnectedRegisteredDevices();
                    //        await i;
                    //    }
                    //    catch (Exception ex)
                    //    {
                    //        Debugger.Break();
                    //    }
                    //    finally
                    //    {
                    //        deferral.Complete();
                    //    }
                    //    break;

                    case DeviceWatcherEventKind.Remove:
                        Debug.WriteLine("[RUN] Remove: " + e.DeviceInformationUpdate.Id);
                        deferral = taskInstance.GetDeferral();
                        try
                        {
                            List <dLock> pluggedRegisteredDeviceListBeforeRemove = await readConnectedRegisteredDevices();

                            List <Tuple <string, bool, bool> > pluggedRegisteredDeviceListBeforeRemove_tuple = new List <Tuple <string, bool, bool> >();
                            foreach (dLock device in pluggedRegisteredDeviceListBeforeRemove)
                            {
                                Tuple <string, bool, bool> newElem = new Tuple <string, bool, bool>(device.DeviceId, device.isDlockEnabled, device.isUsedForLastLogin);
                                pluggedRegisteredDeviceListBeforeRemove_tuple.Add(newElem);
                            }

                            IReadOnlyList <SecondaryAuthenticationFactorInfo> registeredDeviceList_removeEvent = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
                                SecondaryAuthenticationFactorDeviceFindScope.User);

                            List <SecondaryAuthenticationFactorInfo> pluggedRegisteredDeviceListAfterRemove = await getConnectedRegisteredDeviceList(registeredDeviceList_removeEvent);

                            foreach (SecondaryAuthenticationFactorInfo deviceToCheck in pluggedRegisteredDeviceListAfterRemove)
                            {
                                foreach (dLock device in pluggedRegisteredDeviceListBeforeRemove)
                                {
                                    if (deviceToCheck.DeviceId == device.DeviceId)
                                    {
                                        var t = pluggedRegisteredDeviceListBeforeRemove_tuple.FirstOrDefault(i => i.Item1 == device.DeviceId);
                                        if (t != null)
                                        {
                                            // delete
                                            pluggedRegisteredDeviceListBeforeRemove_tuple.Remove(t);
                                        }
                                    }
                                }
                            }

                            bool   lockDevice = true;
                            string deviceId   = "";
                            for (int i = 0; i < pluggedRegisteredDeviceListBeforeRemove_tuple.Count(); i++)
                            {
                                deviceId = pluggedRegisteredDeviceListBeforeRemove_tuple[i].Item1;
                                if ((!pluggedRegisteredDeviceListBeforeRemove_tuple[i].Item2) || (!pluggedRegisteredDeviceListBeforeRemove_tuple[i].Item3))
                                {
                                    lockDevice = false;
                                }
                            }
                            if (lockDevice)
                            {
                                Task  t = LockDevice(deviceId);
                                await t;
                            }
                            await writeConnectedRegisteredDevices();
                        }
                        catch (Exception ex)
                        {
                        }
                        finally
                        {
                            deferral.Complete();
                        }
                        break;
                    }
                }
            }
            else
            {
                Debug.WriteLine("[RUN] Unknown trigger");
                deferral = taskInstance.GetDeferral();
                //try
                //{
                //    Task t = writeConnectedRegisteredDevices();
                //    await t;
                //}
                //catch (ConnectedRegisteredDevicesListTxtFileEmpty Ex)
                //{

                //}
                //finally
                //{
                //    deferral.Complete();
                //}
            }
            // Wait until the operation completes
            opCompletedEvent.WaitOne();

            deferral.Complete();
        }
예제 #8
0
        private async Task AuthenticateWithSmartCardAsync(SmartCard card)
        {
            var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;

            String m_selectedDeviceId           = localSettings.Values["SelectedDevice"] as String;
            string m_selectedDeviceFriendlyName = string.Empty;
            string m_selectedDeviceAddDate      = string.Empty;
            string deviceConfigString           = string.Empty;

            char[] deviceConfigCharArray;
            byte[] deviceIdArray    = new byte[16];
            byte[] deviceDlockState = new byte[1];

            bool foundCompanionDevice = false;

            byte[] response = { 0 };
            string sw1sw2   = null;

            SecondaryAuthenticationFactorAuthenticationStageInfo authStageInfo = await SecondaryAuthenticationFactorAuthentication.GetAuthenticationStageInfoAsync();

            if ((authStageInfo.Stage != SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential) && (authStageInfo.Stage != SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation))
            {
                throw new Exception("Unexpected! Stage: " + authStageInfo.Stage);
            }
            //ShowToastNotification("Post Collecting Credential");
            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Post Collecting Credential");
            IReadOnlyList <SecondaryAuthenticationFactorInfo> deviceList = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
                SecondaryAuthenticationFactorDeviceFindScope.AllUsers);

            if (deviceList.Count == 0)
            {
                //ShowToastNotification("Unexpected exception, device list = 0");
                throw new Exception("Unexpected exception, device list = 0");
            }

            SmartCardConnection connection = await card.ConnectAsync();

            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Connection");

            response = await Apdu.TransmitApduAsync(connection, Apdu.getDeviceGuidCmdApdu);

            sw1sw2        = Apdu.ApduResponseParser(response, out response);
            deviceIdArray = response;
            string deviceId = BitConverter.ToString(response).Replace("-", "");

            response = await Apdu.TransmitApduAsync(connection, Apdu.getDlockStateCmdApdu);

            sw1sw2           = Apdu.ApduResponseParser(response, out response);
            deviceDlockState = response;

            //string deviceFriendlyName = null;

            byte[]  deviceConfigDataArray = new byte[18]; //16 bytes for GUID and 1 byte for dLockstate
            IBuffer deviceConfigData;

            byte[] deviceConfigurationDataArray;
            //List<byte[]> deviceConfigList = new List<byte[]>();



            foreach (SecondaryAuthenticationFactorInfo device in deviceList)
            {
                CryptographicBuffer.CopyToByteArray(device.DeviceConfigurationData, out deviceConfigurationDataArray);
                //deviceConfigList.Add(deviceConfigurationDataArray);

                //deviceFriendlyName = device.DeviceFriendlyName;
                if (device.DeviceId == deviceId)
                {
                    m_selectedDeviceId           = deviceId;
                    m_selectedDeviceFriendlyName = device.DeviceFriendlyName;
                    deviceConfigString           = CryptographicBuffer.ConvertBinaryToString(0, device.DeviceConfigurationData);
                    //deviceConfigCharArray = new char[deviceConfigString.Count()];
                    //deviceConfigCharArray = deviceConfigString.ToCharArray();
                    int count = device.DeviceFriendlyName.Count();
                    m_selectedDeviceAddDate = deviceConfigString.Substring(35 + 1 + count + 1 + 1);
                    foundCompanionDevice    = true;
                    //continue;
                }
            }
            //Debugger.Break();
            if (!foundCompanionDevice)
            {
                throw new CompanionDeviceNotFoundException();
            }
            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Start Nonce APDU sending");
            response = await Apdu.TransmitApduAsync(connection, Apdu.getNonceCmdApdu);

            sw1sw2 = Apdu.ApduResponseParser(response, out response);
            if (sw1sw2 != "9000")
            {
                throw new UnableTogetNonceFromDeviceException();
            }
            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Nonce APDU recieved without error");

            string  nonce    = BitConverter.ToString(response).Replace("-", "");
            IBuffer svcNonce = CryptographicBuffer.DecodeFromHexString(nonce);

            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Start Authentication");
            SecondaryAuthenticationFactorAuthenticationResult authResult = await SecondaryAuthenticationFactorAuthentication.StartAuthenticationAsync(
                m_selectedDeviceId, svcNonce);

            if (authResult.Status != SecondaryAuthenticationFactorAuthenticationStatus.Started)
            {
                //ShowToastNotification("Unexpected! Could not start authentication!");
                throw new Exception("Unexpected! Could not start authentication! Status: " + authResult.Status);
            }

            byte[] devNonce  = { 0 };
            byte[] svcHmac   = { 0 };
            byte[] sessNonce = { 0 };

            CryptographicBuffer.CopyToByteArray(authResult.Authentication.ServiceAuthenticationHmac, out svcHmac);
            CryptographicBuffer.CopyToByteArray(authResult.Authentication.SessionNonce, out sessNonce);
            CryptographicBuffer.CopyToByteArray(authResult.Authentication.DeviceNonce, out devNonce);

            byte[] cmd = new byte[Apdu.challengeCmdApdu.Length + svcHmac.Length + sessNonce.Length + devNonce.Length];
            System.Buffer.BlockCopy(Apdu.challengeCmdApdu, 0, cmd, 0, Apdu.challengeCmdApdu.Length);
            System.Buffer.BlockCopy(svcHmac, 0, cmd, Apdu.challengeCmdApdu.Length, svcHmac.Length);
            System.Buffer.BlockCopy(sessNonce, 0, cmd, Apdu.challengeCmdApdu.Length + svcHmac.Length, sessNonce.Length);
            System.Buffer.BlockCopy(devNonce, 0, cmd, Apdu.challengeCmdApdu.Length + svcHmac.Length + sessNonce.Length, devNonce.Length);

            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Send Challenge");

            string str = "\"" + m_selectedDeviceFriendlyName + "\"";

            await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                str,
                SecondaryAuthenticationFactorAuthenticationMessage.DeviceNeedsAttention);

            response = await Apdu.TransmitApduAsync(connection, cmd);

            sw1sw2 = Apdu.ApduResponseParser(response, out response);

            if (sw1sw2 == "6985")
            {
                throw new UnauthorizedUserException();
            }
            else if (sw1sw2 == "6984")
            {
                //ShowToastNotification("Log-in denied by user");
                throw new LogInDeniedByUserException();
            }

            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Response recieved");
            byte[] HMACdk = new byte[32];
            byte[] HMACsk = new byte[32];
            System.Buffer.BlockCopy(response, 0, HMACdk, 0, 32);
            System.Buffer.BlockCopy(response, 32, HMACsk, 0, 32);

            IBuffer deviceHmac  = CryptographicBuffer.CreateFromByteArray(HMACdk);
            IBuffer sessionHmac = CryptographicBuffer.CreateFromByteArray(HMACsk);

            SecondaryAuthenticationFactorFinishAuthenticationStatus authStatus = await authResult.Authentication.FinishAuthenticationAsync(deviceHmac,
                                                                                                                                           sessionHmac);

            if (authStatus != SecondaryAuthenticationFactorFinishAuthenticationStatus.Completed)
            {
                //ShowToastNotification("Unable to complete authentication!");
                System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Unable to complete authentication");
                throw new Exception("Unable to complete authentication!");
            }

            deviceConfigString = "";
            if (deviceDlockState[0] == 0)
            {
                deviceConfigString = deviceId + "-0-1-" + m_selectedDeviceFriendlyName + "-" + m_selectedDeviceAddDate;
            }
            else
            {
                deviceConfigString = deviceId + "-1-1-" + m_selectedDeviceFriendlyName + "-" + m_selectedDeviceAddDate;
            }
            deviceConfigCharArray = new char[deviceConfigString.Count()];
            deviceConfigString.CopyTo(0, deviceConfigCharArray, 0, deviceConfigString.Count()); // because deviceConfigString is readonly
            deviceConfigCharArray[35] = '1';                                                    // to indicate that device was not used for last login
            string deviceConfigStringNew = new string(deviceConfigCharArray);

            //Debugger.Break();
            deviceConfigData = CryptographicBuffer.ConvertStringToBinary(deviceConfigStringNew, 0);
            await SecondaryAuthenticationFactorRegistration.UpdateDeviceConfigurationDataAsync(deviceId, deviceConfigData); //update deviceConfigData

            foreach (SecondaryAuthenticationFactorInfo device in deviceList)
            {
                if (device.DeviceId != deviceId)
                {
                    deviceConfigString    = CryptographicBuffer.ConvertBinaryToString(0, device.DeviceConfigurationData);
                    deviceConfigCharArray = new char[deviceConfigString.Count()];
                    deviceConfigString.CopyTo(0, deviceConfigCharArray, 0, deviceConfigString.Count()); // decause deviceConfigString is readonly
                    deviceConfigCharArray[35] = '0';                                                    // to indicate that device was not used for last login
                    deviceConfigStringNew     = new string(deviceConfigCharArray);
                    deviceConfigData          = CryptographicBuffer.ConvertStringToBinary(deviceConfigStringNew, 0);
                    //Debugger.Break();
                    await SecondaryAuthenticationFactorRegistration.UpdateDeviceConfigurationDataAsync(device.DeviceId, deviceConfigData); //update deviceConfigData
                }
            }
            System.Diagnostics.Debug.WriteLine("[AuthenticateWithSmartCardAsync] Auth completed");
            connection.Dispose();
        }
예제 #9
0
        async void PerformAuthentication()
        {
            ShowToastNotification("Performing Auth!");

            //Get the selected device from app settings
            var    localSettings      = Windows.Storage.ApplicationData.Current.LocalSettings;
            String m_selectedDeviceId = localSettings.Values["SelectedDevice"] as String;

            SecondaryAuthenticationFactorAuthenticationStageInfo authStageInfo = await SecondaryAuthenticationFactorAuthentication.GetAuthenticationStageInfoAsync();

            if (authStageInfo.Stage != SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential)
            {
                ShowToastNotification("Unexpected!");
                throw new Exception("Unexpected!");
            }

            ShowToastNotification("Post Collecting Credential");

            IReadOnlyList <SecondaryAuthenticationFactorInfo> deviceList = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
                SecondaryAuthenticationFactorDeviceFindScope.AllUsers);

            if (deviceList.Count == 0)
            {
                ShowToastNotification("Unexpected exception, device list = 0");
                throw new Exception("Unexpected exception, device list = 0");
            }

            ShowToastNotification("Found companion devices");

            SecondaryAuthenticationFactorInfo deviceInfo = deviceList.ElementAt(0);

            m_selectedDeviceId = deviceInfo.DeviceId;

            ShowToastNotification("Device ID: " + m_selectedDeviceId);

            //a nonce is an arbitrary number that may only be used once - a random or pseudo-random number issued in an authentication protocol to ensure that old communications cannot be reused in replay attacks.
            IBuffer svcNonce = CryptographicBuffer.GenerateRandom(32);  //Generate a nonce and do a HMAC operation with the nonce


            //In real world, you would need to take this nonce and send to companion device to perform an HMAC operation with it
            //You will have only 20 second to get the HMAC from the companion device
            SecondaryAuthenticationFactorAuthenticationResult authResult = await SecondaryAuthenticationFactorAuthentication.StartAuthenticationAsync(
                m_selectedDeviceId, svcNonce);

            if (authResult.Status != SecondaryAuthenticationFactorAuthenticationStatus.Started)
            {
                ShowToastNotification("Unexpected! Could not start authentication!");
                throw new Exception("Unexpected! Could not start authentication!");
            }

            ShowToastNotification("Auth Started");

            //
            // WARNING: Test code
            // The HAMC calculation SHOULD be done on companion device
            //
            byte[] combinedDataArray;
            CryptographicBuffer.CopyToByteArray(authResult.Authentication.DeviceConfigurationData, out combinedDataArray);

            byte[] deviceKeyArray = new byte[32];
            byte[] authKeyArray   = new byte[32];
            for (int index = 0; index < deviceKeyArray.Length; index++)
            {
                deviceKeyArray[index] = combinedDataArray[index];
            }
            for (int index = 0; index < authKeyArray.Length; index++)
            {
                authKeyArray[index] = combinedDataArray[deviceKeyArray.Length + index];
            }
            // Create device key and authentication key
            IBuffer deviceKey = CryptographicBuffer.CreateFromByteArray(deviceKeyArray);
            IBuffer authKey   = CryptographicBuffer.CreateFromByteArray(authKeyArray);

            // Calculate the HMAC
            MacAlgorithmProvider hMACSha256Provider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);

            CryptographicKey deviceHmacKey = hMACSha256Provider.CreateKey(deviceKey);
            IBuffer          deviceHmac    = CryptographicEngine.Sign(deviceHmacKey, authResult.Authentication.DeviceNonce);

            // sessionHmac = HMAC(authKey, deviceHmac || sessionNonce)
            IBuffer sessionHmac;

            byte[] deviceHmacArray = { 0 };
            CryptographicBuffer.CopyToByteArray(deviceHmac, out deviceHmacArray);

            byte[] sessionNonceArray = { 0 };
            CryptographicBuffer.CopyToByteArray(authResult.Authentication.SessionNonce, out sessionNonceArray);

            combinedDataArray = new byte[deviceHmacArray.Length + sessionNonceArray.Length];
            for (int index = 0; index < deviceHmacArray.Length; index++)
            {
                combinedDataArray[index] = deviceHmacArray[index];
            }
            for (int index = 0; index < sessionNonceArray.Length; index++)
            {
                combinedDataArray[deviceHmacArray.Length + index] = sessionNonceArray[index];
            }

            // Get a Ibuffer from combinedDataArray
            IBuffer sessionMessage = CryptographicBuffer.CreateFromByteArray(combinedDataArray);

            // Calculate sessionHmac
            CryptographicKey authHmacKey = hMACSha256Provider.CreateKey(authKey);

            sessionHmac = CryptographicEngine.Sign(authHmacKey, sessionMessage);

            ShowToastNotification("Before finish auth");

            SecondaryAuthenticationFactorFinishAuthenticationStatus authStatus = await authResult.Authentication.FinishAuthenticationAsync(deviceHmac,
                                                                                                                                           sessionHmac);

            if (authStatus != SecondaryAuthenticationFactorFinishAuthenticationStatus.Completed)
            {
                ShowToastNotification("Unable to complete authentication!");
                throw new Exception("Unable to complete authentication!");
            }

            ShowToastNotification("Auth completed");
        }