예제 #1
0
        private void CheckIfReaderRemoved()
        {
            if (LoadedBChips != null)
            {
                if (Monitor.TryEnter(readLock))
                {
                    try
                    {
                        string readerName = LoadedBChips.ReaderName;

                        string[] readers = GetReaderNames();
                        foreach (string reader in readers)
                        {
                            if (readerName == reader)
                            {
                                return;
                            }
                        }

                        // Card pulled with reader
                        LoadedBChips = null;
                        ChangePageUi(PageToShow.NoCard, null);
                        StopMonitoring();
                    }
                    finally
                    {
                        Monitor.Exit(readLock);
                    }
                }
            }
        }
예제 #2
0
        private void _monitor_CardInserted(object sender, CardStatusEventArgs e)
        {
            if (e.State == SCRState.Present)
            {
                try
                {
                    BChipSmartCard insertedCard =
                        new BChipSmartCard(e.ReaderName)
                    {
                        ATR           = e.Atr,
                        LastConnected = DateTime.Now,
                        IsConnected   = true
                    };

                    if (insertedCard.Type() == CardType.BChip)
                    {
                        ScanAndLoadConnectedCards(insertedCard);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Log(ex);
                }
            }
        }
예제 #3
0
 private void _monitor_CardRemoved(object sender, CardStatusEventArgs e)
 {
     if (LoadedBChips != null)
     {
         if (LoadedBChips.ReaderName == e.ReaderName)
         {
             ChangePageUi(PageToShow.NoCard, null);
             // single card only.
             // bchip.IsConnected = false;
             LoadedBChips = null;
         }
     }
 }
예제 #4
0
        public PageToShow AnalyzeCardData(BChipSmartCard bChipSmartCard)
        {
            if (!bChipSmartCard.IsConnected)
            {
                return(PageToShow.NoCard);
            }

            if (bChipSmartCard.Type() != CardType.BChip || bChipSmartCard.SmartCardData == null)
            {
                return(PageToShow.Unsupported);
            }

            // Analyze card
            try
            {
                BChipMemoryLayout_BCHIP cardMemory = (BChipMemoryLayout_BCHIP)bChipSmartCard.SmartCardData;

                if (cardMemory.IsFormatted)
                {
                    WalletTypeComboBox.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        WalletTypeComboBox.SelectedItem = null;
                    }));
                    return(PageToShow.NotInitialized);
                }

                if (!cardMemory.IsChecksumValid())
                {
                    return(PageToShow.CrcError);
                }

                // All seems good
                return(PageToShow.Ready);
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }

            return(PageToShow.Error);
        }
예제 #5
0
        private async void FormatCardAsync()
        {
            try
            {
                DispatcherUpdater(FormatingViewGrid, Visibility.Visible);

                using (var context = _contextFactory.Establish(SCardScope.System))
                {
                    using (var isoReader = new IsoReader(context, LoadedBChips.ReaderName, SCardShareMode.Shared, SCardProtocol.Any))
                    {
                        if (LoadedBChips.AdpuInterface.RequiresInit)
                        {
                            Response initResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.InitCard());
                            if (initResponse.SW1 != 0x90)
                            {
                                Logger.Log("Error initializing smart card reader");
                            }
                        }
                        var unlockResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.UnblockCard());
                        Logger.Log($"ADPU response from pin request: {unlockResponse.StatusWord:X}");
                        var writeResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.FormatCard(CardType.BChip));
                        Logger.Log($"ADPU response from format request: {unlockResponse.StatusWord:X}");
                    }
                }

                LoadedBChips = null;
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
            finally
            {
                DispatcherUpdater(FormatingViewGrid, Visibility.Collapsed);
                ScanAndLoadConnectedCards();
            }
        }
예제 #6
0
        private void ProvisionCardButton_Click(object sender, RoutedEventArgs e)
        {
            CreateKeyErrorLabel.Content = "";
            CreatingKeyLabel.Content    = "";

            if (passphrase.Password.Length == 0 || passphraseConfirmation.Password.Length == 0)
            {
                CreateKeyErrorLabel.Content = "A passphrase was not entered.";
                return;
            }

            if (passphrase.Password != passphraseConfirmation.Password)
            {
                CreateKeyErrorLabel.Content = "Passphrases entered did not match.";
                return;
            }

            if (PrivateKeyTextBox.Text.Length == 0)
            {
                CreateKeyErrorLabel.Content = "No private key data to store.";
                return;
            }

            if (CardPkType == PKType.BTC || CardPkType == PKType.BTC_TestNet)
            {
                // Check if we are importing a user's wif or mnemonic, update public key field
                // to allow the user to confirm
                if (CardGeneratedKey.GetBitcoinSecret(Network).ToWif() != PrivateKeyTextBox.Text)
                {
                    try
                    {
                        NBitcoin.Key importedKey    = null;
                        int          spacesDetected = PrivateKeyTextBox.Text.Count(a => a == ' ');
                        // Check for mnemonic
                        if (spacesDetected >= 11)
                        {
                            NBitcoin.Mnemonic mnemonic = new NBitcoin.Mnemonic(PrivateKeyTextBox.Text);
                            // Force bitcoin and first address
                            importedKey = mnemonic.DeriveExtKey().Derive(KeyPath.Parse("m/44'/0'/0'/0/0")).PrivateKey;
                        }
                        else
                        {
                            // Check for wif
                            importedKey = NBitcoin.Key.Parse(PrivateKeyTextBox.Text);
                        }

                        // Replace CardGeneratedKey with imported key. Only valid for bitcoin addresses.
                        CardGeneratedKey         = importedKey;
                        PublicKeyTextBox.Text    = importedKey.PubKey.GetAddress(Network).ToString();
                        PrivateKeyTextBox.Text   = importedKey.GetBitcoinSecret(Network).ToWif();
                        CreatingKeyLabel.Content = "Key data imported, ready to setup your bChip.";
                        return;
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(ex);
                        CreateKeyErrorLabel.Content = "Failed to automatically parse private key data.";
                        return;
                    }
                }
            }

            byte[] privateKeyToEncrypt = null;
            byte[] publicKeyData       = null;

            if (CardGeneratedKey != null)
            {
                // Users can optionally remove the public key portion, so we'll skip saving it.
                if (PublicKeyTextBox.Text.Length > 0)
                {
                    publicKeyData = CardGeneratedKey.PubKey.ToBytes();
                }
                byte[] privateKeyBytes = CardGeneratedKey.GetWif(Network.Main).ToBytes();
                // Always seem to get an extra bit at the end...
                if (privateKeyBytes.Length == 33 && privateKeyBytes[32] == 0x1)
                {
                    privateKeyToEncrypt = privateKeyBytes.Take(32).ToArray();
                }
                else
                {
                    privateKeyToEncrypt = privateKeyBytes;
                }
            }
            else
            {
                if (PublicKeyTextBox.Text.Length > 0)
                {
                    publicKeyData = CryptographicBuffer.ConvertStringToBinary(PublicKeyTextBox.Text, BinaryStringEncoding.Utf8).ToArray();
                }

                privateKeyToEncrypt = CryptographicBuffer.ConvertStringToBinary(PrivateKeyTextBox.Text, BinaryStringEncoding.Utf8).ToArray();
            }

            if (privateKeyToEncrypt.Length > BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA)
            {
                CreateKeyErrorLabel.Content =
                    $"Private key was {PrivateKeyTextBox.Text.Length} bytes, {Math.Abs(PrivateKeyTextBox.Text.Length - BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA)} bytes over the limit.";
                return;
            }

            if (publicKeyData != null)
            {
                if (publicKeyData.Length > BChipMemoryLayout_BCHIP.PUBKEY_MAX_DATA)
                {
                    CreateKeyErrorLabel.Content =
                        $"Public key was {PublicKeyTextBox.Text.Length} bytes, {Math.Abs(PublicKeyTextBox.Text.Length - BChipMemoryLayout_BCHIP.PUBKEY_MAX_DATA)} bytes over the limit.";
                    return;
                }
            }

            string friendlyName = FriendlyNameTextBox.Text;

            ProvisionNewKeysViewGrid.Dispatcher.BeginInvoke(new Action(() =>
            {
                ProvisionNewKeysViewGrid.IsEnabled = false;
            }));

            Task.Run(new Action(() =>
            {
                try
                {
                    UpdateTextLabel(CreatingKeyLabel, "Setting up bChip! Do not remove card.");

                    // Encrypt data
                    BChipMemoryLayout_BCHIP bchip = LoadedBChips.SmartCardData as BChipMemoryLayout_BCHIP;
                    bchip.EncryptPrivateKeyData(CardPkType, passphrase.Password, privateKeyToEncrypt, publicKeyData);
                    bchip.SetFriendlyName(friendlyName);

                    using (var context = _contextFactory.Establish(SCardScope.System))
                    {
                        using (var isoReader = new IsoReader(context, LoadedBChips.ReaderName, SCardShareMode.Shared, SCardProtocol.Any))
                        {
                            if (LoadedBChips.AdpuInterface.RequiresInit)
                            {
                                Response initResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.InitCard());
                                if (initResponse.SW1 != 0x90)
                                {
                                    Logger.Log("Error initializing smart card reader");
                                }
                            }

                            var unlockResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.UnblockCard());
                            Logger.Log($"ADPU response from pin request: {unlockResponse.StatusWord:X}");
                            if (unlockResponse.SW1 != 0x90)
                            {
                                UpdateTextLabel(CreatingKeyLabel, "");
                                UpdateTextLabel(CreateKeyErrorLabel, "Could not be unlock bchip for writing.");
                                return;
                            }
                            var writeResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.WriteCard(bchip));
                            Logger.Log($"ADPU response from write card data: {unlockResponse.StatusWord:X}");
                            if (writeResponse.StatusWord != 0x00009000)
                            {
                                UpdateTextLabel(CreatingKeyLabel, "");
                                UpdateTextLabel(CreateKeyErrorLabel, "Failure writing data to the bchip.");
                                return;
                            }
                        }
                    }

                    UpdateTextLabel(CreatingKeyLabel, string.Empty);
                    ClearTextBox(FriendlyNameTextBox);

                    // Done? clear loaded card, reload card
                    LoadedBChips = null;
                    ChangePageUi(PageToShow.NoCard, null);
                    ScanAndLoadConnectedCards();
                }
                catch (Exception ex)
                {
                    Logger.Log(ex);
                }
                finally
                {
                    ProvisionNewKeysViewGrid.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        ProvisionNewKeysViewGrid.IsEnabled = true;
                    }));
                }
            }));
        }
예제 #7
0
        private void ScanAndLoadConnectedCards(BChipSmartCard insertedCard = null)
        {
            using (var context = _contextFactory.Establish(SCardScope.System))
            {
                if (insertedCard == null)
                {
                    List <string> readerNames = GetReaderNames().ToList();
                    foreach (string curReader in readerNames)
                    {
                        try
                        {
                            using (var reader =
                                       context.ConnectReader(curReader, SCardShareMode.Shared, SCardProtocol.Any))
                            {
                                insertedCard = new BChipSmartCard(curReader)
                                {
                                    ATR           = reader.GetAttrib(SCardAttribute.AtrString),
                                    LastConnected = DateTime.Now,
                                    IsConnected   = true
                                };
                            }
                            if (insertedCard.Type() != CardType.BChip)
                            {
                                Logger.Log($"Card type was not an expected BChip and skipped ({insertedCard.Type()})");
                                continue;
                            }
                        }
                        // We try to check for an inserted card, eat errors.
                        catch (Exception ex)
                        {
                            if ((uint)ex.HResult == 0x80131500)
                            {
                                // ignore card removed
                                continue;
                            }
                        }
                    }
                }

                if (insertedCard == null)
                {
                    ChangePageUi(PageToShow.NoCard, null);
                }

                if (insertedCard != null)
                {
                    using (var isoReader = new IsoReader(context, insertedCard.ReaderName, SCardShareMode.Shared, SCardProtocol.Any))
                    {
                        try
                        {
                            if (insertedCard.AdpuInterface.RequiresInit)
                            {
                                Response initResponse = isoReader.Transmit(insertedCard.AdpuInterface.InitCard());
                                if (initResponse.SW1 != 0x90)
                                {
                                    Logger.Log("Error initializing smart card reader");
                                }
                            }

                            Response response = isoReader.Transmit(insertedCard.AdpuInterface.ReadCard());
                            if (response.HasData)
                            {
                                byte[] data     = response.GetData();
                                byte[] mlvi     = data.Skip(0x20).Take(BChipMemoryLayout_BCHIP.MLVI_MAX_DATA).ToArray();
                                byte[] carddata = data.Skip(0x28).ToArray();

                                // At this stage, the card has not yet been validated/parsed. Another thread should handle cleanup/de-dupes
                                insertedCard.SmartCardData = new BChipMemoryLayout_BCHIP(mlvi, carddata, PKStatus.NotValidated);
                                LoadedBChips = insertedCard;

                                ChangePageUi(AnalyzeCardData(insertedCard), insertedCard);
                            }
                            else
                            {
                                Logger.Log("Card added had no data to download");
                                // TODO: Add card data could not be loaded (not CRC error)
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Log(ex);
                        };
                    }
                }
            }
        }
예제 #8
0
        public void ChangePageUi(PageToShow pageToShow, BChipSmartCard bChipSmartCard)
        {
            Visibility noCardVisibility                    = Visibility.Collapsed;
            Visibility readyVisibility                     = Visibility.Collapsed;
            Visibility confirmFormatVisibility             = Visibility.Collapsed;
            Visibility passphraseDialogVisibility          = Visibility.Collapsed;
            Visibility notInitializedWizardVisibility      = Visibility.Collapsed;
            Visibility crcErrorViewGridVisibility          = Visibility.Collapsed;
            Visibility unsupportedDialogVisibility         = Visibility.Collapsed;
            Visibility provisionNewKeysViewGridVisibility  = Visibility.Collapsed;
            Visibility provisionMnemonicViewGridVisibility = Visibility.Collapsed;
            Visibility showPrivateKeyViewGridVisibility    = Visibility.Collapsed;

            ClearPasswordBox(PassphraseEntryBox);
            ClearPasswordBox(passphrase);
            ClearPasswordBox(passphraseConfirmation);
            ClearPasswordBox(Mnemonicpassphrase);
            ClearPasswordBox(MnemonicpassphraseConfirmation);
            ClearTextBox(MnemonicEntryTextBox);

            // Clear last error if set
            UpdateTextLabel(ErrorMessageLabel, "");

            switch (pageToShow)
            {
            case PageToShow.ProvisionMnemonic:
                provisionMnemonicViewGridVisibility = Visibility.Visible;
                break;

            case PageToShow.ProvisionCard:
                provisionNewKeysViewGridVisibility = Visibility.Visible;
                break;

            case PageToShow.ConfirmFormat:
                confirmFormatVisibility = Visibility.Visible;
                break;

            case PageToShow.Ready:
                readyVisibility = Visibility.Visible;
                break;

            case PageToShow.ShowPassphraseDialog:
                passphraseDialogVisibility = Visibility.Visible;
                break;

            case PageToShow.NoCard:
                noCardVisibility = Visibility.Visible;
                break;

            case PageToShow.Unsupported:
            case PageToShow.Error:
                unsupportedDialogVisibility = Visibility.Visible;
                break;

            case PageToShow.NotInitialized:
                notInitializedWizardVisibility = Visibility.Visible;
                break;

            case PageToShow.CrcError:
                crcErrorViewGridVisibility = Visibility.Visible;
                break;
            }

            DispatcherUpdater(ProvisionMnemonicPhraseViewGrid, provisionMnemonicViewGridVisibility);
            DispatcherUpdater(ShowPrivateKeyViewGrid, showPrivateKeyViewGridVisibility);
            DispatcherUpdater(ProvisionNewKeysViewGrid, provisionNewKeysViewGridVisibility);
            DispatcherUpdater(NonInitializedWizardViewGrid, notInitializedWizardVisibility);
            DispatcherUpdater(CrcErrorViewGrid, crcErrorViewGridVisibility);
            DispatcherUpdater(InitializedUnknownCardViewGrid, unsupportedDialogVisibility);
            DispatcherUpdater(ShowPassphraseViewGrid, passphraseDialogVisibility);
            DispatcherUpdater(InsertCardGrid, noCardVisibility);
            DispatcherUpdater(ConfirmFormatViewGrid, confirmFormatVisibility);
            DispatcherUpdater(ReadyCardViewGrid, readyVisibility);

            if (pageToShow == PageToShow.NoCard)
            {
                // Clear any keys left in UI pages
                UpdateTextLabel(PrivateKeyAddressLabel, "");
                PrivateQrCodeImage.Dispatcher.BeginInvoke(new Action(() =>
                {
                    PrivateQrCodeImage.Source = null;
                }));
            }

            // Populate for card UI
            if (pageToShow == PageToShow.Ready)
            {
                QrCodeImage.Dispatcher.BeginInvoke(new Action(() =>
                {
                    QrCodeImage.Visibility = Visibility.Hidden;
                }));
                PubKeyCopyIcon.Dispatcher.BeginInvoke(new Action(() =>
                {
                    PubKeyCopyIcon.Visibility = Visibility.Hidden;
                }));

                BChipMemoryLayout_BCHIP bchip = (BChipMemoryLayout_BCHIP)bChipSmartCard.SmartCardData;
                UpdateTextLabel(BChipIdLabel, bchip.IdLabel);
                switch (bchip.PkType)
                {
                case PKType.BTC:
                    UpdateTextLabel(PKTypeLabel, "Bitcoin (BTC)");
                    break;

                case PKType.BTC_TestNet:
                    UpdateTextLabel(PKTypeLabel, "Bitcoin (TestNet)");
                    break;

                case PKType.CUSTOM:
                    UpdateTextLabel(PKTypeLabel, "Custom");
                    break;

                case PKType.UNSET:
                    UpdateTextLabel(PKTypeLabel, "(no key data)");
                    break;
                }

                string publicAddress = bchip.PublicAddress;
                if (publicAddress == "")
                {
                    if (bchip.PkType == PKType.UNSET)
                    {
                        UpdateTextLabel(PublicKeyAddressLabel, "Card not setup - remove and re-insert card to reload");
                        DisplayPrivateKeyButton.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            DisplayPrivateKeyButton.IsEnabled = false;
                        }));
                    }
                    else
                    {
                        UpdateTextLabel(PublicKeyAddressLabel, "No public key data on card");
                    }
                }
                else if (publicAddress == null)
                {
                    UpdateTextLabel(PublicKeyAddressLabel, "Failed to parse public key data");
                }
                else
                {
                    QrCodeImage.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        QrCodeImage.Source = Imaging.CreateBitmapSourceFromHBitmap(
                            new QrHandler(publicAddress, 5).GetQrCode().GetHbitmap(),
                            IntPtr.Zero,
                            Int32Rect.Empty,
                            BitmapSizeOptions.FromEmptyOptions());
                        QrCodeImage.Visibility = Visibility.Visible;
                    }));
                    PubKeyCopyIcon.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        PubKeyCopyIcon.Visibility = Visibility.Visible;
                    }));

                    UpdateTextLabel(PublicKeyAddressLabel, publicAddress);
                }

                if (bchip.PkType != PKType.UNSET)
                {
                    DisplayPrivateKeyButton.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        DisplayPrivateKeyButton.IsEnabled = true;
                    }));
                }
            }
        }
예제 #9
0
        private void MnemonicProvisionCardButton_Click(object sender, RoutedEventArgs e)
        {
            MnemonicErrorLabel.Content = "";
            MnemonicKeyLabel.Content   = "";

            if (Mnemonicpassphrase.Password.Length == 0 || MnemonicpassphraseConfirmation.Password.Length == 0)
            {
                MnemonicErrorLabel.Content = "A passphrase was not entered.";
                return;
            }

            if (Mnemonicpassphrase.Password != MnemonicpassphraseConfirmation.Password)
            {
                MnemonicErrorLabel.Content = "Passphrases entered did not match.";
                return;
            }

            if (MnemonicEntryTextBox.Text.Length == 0)
            {
                MnemonicErrorLabel.Content = "No private key data to store.";
                return;
            }

            if (CardPkType != PKType.Mnemonic)
            {
                MnemonicErrorLabel.Content = "Invalid application state. Please restart app.";
                return;
            }

            byte[] privateKeyToEncrypt = null;
            byte[] publicKeyData       = CryptographicBuffer.ConvertStringToBinary("Mnemonic seed backed up.", BinaryStringEncoding.Utf8).ToArray();

            try
            {
                privateKeyToEncrypt = BIP39Helpers.GenerateEntropyFromWords(MnemonicEntryTextBox.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries), NBitcoin.Wordlist.English);
            }
            // TODO: Implement better exception types to ease debugging
            catch (Exception ex)
            {
                Logger.Log(ex);
                MnemonicErrorLabel.Content = "Failed to automatically parse mnemonic phrase.";
                return;
            }

            if (privateKeyToEncrypt.Length > BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA)
            {
                CreateKeyErrorLabel.Content =
                    $"Private key was {PrivateKeyTextBox.Text.Length} bytes, {Math.Abs(PrivateKeyTextBox.Text.Length - BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA)} bytes over the limit.";
                return;
            }

            string friendlyName = MnemonicFriendlyNameTextBox.Text;

            ProvisionMnemonicPhraseViewGrid.Dispatcher.BeginInvoke(new Action(() =>
            {
                ProvisionMnemonicPhraseViewGrid.IsEnabled = false;
            }));

            Task.Run(new Action(() =>
            {
                try
                {
                    UpdateTextLabel(MnemonicKeyLabel, "Setting up bChip! Do not remove card.");

                    // Encrypt data
                    BChipMemoryLayout_BCHIP bchip = LoadedBChips.SmartCardData as BChipMemoryLayout_BCHIP;
                    bchip.EncryptPrivateKeyData(CardPkType, Mnemonicpassphrase.Password, privateKeyToEncrypt, publicKeyData);
                    bchip.SetFriendlyName(friendlyName);

                    using (var context = _contextFactory.Establish(SCardScope.System))
                    {
                        using (var isoReader = new IsoReader(context, LoadedBChips.ReaderName, SCardShareMode.Shared, SCardProtocol.Any))
                        {
                            if (LoadedBChips.AdpuInterface.RequiresInit)
                            {
                                Response initResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.InitCard());
                                if (initResponse.SW1 != 0x90)
                                {
                                    Logger.Log("Error initializing smart card reader");
                                }
                            }

                            var unlockResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.UnblockCard());
                            Logger.Log($"ADPU response from pin request: {unlockResponse.StatusWord:X}");
                            if (unlockResponse.SW1 != 0x90)
                            {
                                UpdateTextLabel(MnemonicKeyLabel, "");
                                UpdateTextLabel(MnemonicErrorLabel, "Could not be unlock bchip for writing.");
                                return;
                            }
                            var writeResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.WriteCard(bchip));
                            Logger.Log($"ADPU response from write card data: {unlockResponse.StatusWord:X}");
                            if (writeResponse.SW1 != 0x90)
                            {
                                UpdateTextLabel(MnemonicKeyLabel, "");
                                UpdateTextLabel(MnemonicErrorLabel, "Failure writing data to the bchip.");
                                return;
                            }
                        }
                    }

                    UpdateTextLabel(MnemonicKeyLabel, string.Empty);
                    ClearTextBox(MnemonicFriendlyNameTextBox);

                    // Done? clear loaded card, reload card
                    LoadedBChips = null;
                    ScanAndLoadConnectedCards();
                }
                catch (Exception ex)
                {
                    Logger.Log(ex);
                }
                finally
                {
                    ProvisionMnemonicPhraseViewGrid.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        ProvisionMnemonicPhraseViewGrid.IsEnabled = true;
                    }));
                }
            }));
        }