Skip to content

Commit

Permalink
Add some visual feedbacks when loading key entries list
Browse files Browse the repository at this point in the history
Remove LockWithSpecificKey action on SAM Tools, for now
  • Loading branch information
Maxhy committed Sep 29, 2023
1 parent 29aaa0d commit 5aa39bf
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Leosac.KeyManager.Library.UI.Domain;
using Leosac.WpfApp.Domain;
using Leosac.WpfApp;
using LibLogicalAccess.Card;
using LibLogicalAccess.Reader;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.Input;
Expand All @@ -16,14 +14,19 @@ public SAMKeyStoreToolsControlViewModel()
{
_samAuthKey = new KeyVersion() { Name = "Key" };
_samAuthKeyId = 0;
_samAuthKeyType = SAMKeyType.SAM_KEY_AES;
_samAuthKeyType = LibLogicalAccess.Card.SAMKeyType.SAM_KEY_AES;

_samUnlockKey = new KeyVersion() { Name = "Key" };
_samUnlockKey = new KeyVersion() { Name = "Key", Key = new Key(null, 16, "") };
_samUnlockKeyId = 1;
_samUnlockAction = LibLogicalAccess.Card.SAMLockUnlock.Unlock;

KeyTypes = new ObservableCollection<SAMKeyType>(Enum.GetValues<SAMKeyType>());
UnlockActions = new ObservableCollection<SAMLockUnlock>(Enum.GetValues<SAMLockUnlock>());
KeyTypes = new ObservableCollection<LibLogicalAccess.Card.SAMKeyType>(Enum.GetValues<LibLogicalAccess.Card.SAMKeyType>());
UnlockActions = new ObservableCollection<LibLogicalAccess.Card.SAMLockUnlock>(new[]
{
LibLogicalAccess.Card.SAMLockUnlock.Unlock,
LibLogicalAccess.Card.SAMLockUnlock.LockWithoutSpecifyingKey,
LibLogicalAccess.Card.SAMLockUnlock.SwitchAV2Mode
});

SAMAuthCommand = new RelayCommand(
() =>
Expand Down Expand Up @@ -70,8 +73,8 @@ public byte SAMAuthKeyId
set => SetProperty(ref _samAuthKeyId, value);
}

private SAMKeyType _samAuthKeyType;
public SAMKeyType SAMAuthKeyType
private LibLogicalAccess.Card.SAMKeyType _samAuthKeyType;
public LibLogicalAccess.Card.SAMKeyType SAMAuthKeyType
{
get => _samAuthKeyType;
set => SetProperty(ref _samAuthKeyType, value);
Expand All @@ -91,16 +94,16 @@ public byte SAMUnlockKeyId
set => SetProperty(ref _samUnlockKeyId, value);
}

private SAMLockUnlock _samUnlockAction;
public SAMLockUnlock SAMUnlockAction
private LibLogicalAccess.Card.SAMLockUnlock _samUnlockAction;
public LibLogicalAccess.Card.SAMLockUnlock SAMUnlockAction
{
get => _samUnlockAction;
set => SetProperty(ref _samUnlockAction, value);
}

public ObservableCollection<SAMKeyType> KeyTypes { get; set; }
public ObservableCollection<LibLogicalAccess.Card.SAMKeyType> KeyTypes { get; set; }

public ObservableCollection<SAMLockUnlock> UnlockActions { get; set; }
public ObservableCollection<LibLogicalAccess.Card.SAMLockUnlock> UnlockActions { get; set; }

public RelayCommand SAMAuthCommand { get; }

Expand All @@ -120,7 +123,7 @@ private void SAMGetVersion()
var cmd = chip?.getCommands();
var ctype = chip?.getCardType();

SAMVersion? version = null;
LibLogicalAccess.Card.SAMVersion? version = null;
if (cmd is SAMAV1ISO7816Commands samav1cmd)
version = samav1cmd.getVersion();
else if (cmd is SAMAV2ISO7816Commands samav2cmd)
Expand Down Expand Up @@ -148,14 +151,14 @@ private void SAMAuthenticate()
{
try
{
var key = new DESFireKey();
var key = new LibLogicalAccess.Card.DESFireKey();

if (SAMAuthKeyType == SAMKeyType.SAM_KEY_DES)
key.setKeyType(DESFireKeyType.DF_KEY_DES);
else if (SAMAuthKeyType == SAMKeyType.SAM_KEY_AES)
key.setKeyType(DESFireKeyType.DF_KEY_AES);
if (SAMAuthKeyType == LibLogicalAccess.Card.SAMKeyType.SAM_KEY_DES)
key.setKeyType(LibLogicalAccess.Card.DESFireKeyType.DF_KEY_DES);
else if (SAMAuthKeyType == LibLogicalAccess.Card.SAMKeyType.SAM_KEY_AES)
key.setKeyType(LibLogicalAccess.Card.DESFireKeyType.DF_KEY_AES);
else
key.setKeyType(DESFireKeyType.DF_KEY_3K3DES);
key.setKeyType(LibLogicalAccess.Card.DESFireKeyType.DF_KEY_3K3DES);

key.fromString(SAMAuthKey.Key.GetAggregatedValue<string>(KeyValueFormat.HexStringWithSpace));
key.setKeyVersion(SAMAuthKey.Version);
Expand Down Expand Up @@ -235,19 +238,22 @@ private void SAMLockUnlock()
var ks = (KeyStore as SAMKeyStore);
var cmd = ks?.Chip?.getCommands();

var key = new DESFireKey();
key.setKeyType(DESFireKeyType.DF_KEY_AES);
var key = new LibLogicalAccess.Card.DESFireKey();
key.setKeyType(LibLogicalAccess.Card.DESFireKeyType.DF_KEY_AES);
key.fromString(SAMUnlockKey.Key.GetAggregatedValue<string>(KeyValueFormat.HexStringWithSpace));
key.setKeyVersion(SAMUnlockKey.Version);

if (cmd is SAMAV1ISO7816Commands samav1cmd)
{
samav1cmd.lockUnlock(key, SAMUnlockAction, SAMUnlockKeyId, SAMUnlockKeyId, SAMUnlockKey.Version);
samav1cmd.lockUnlock(key, SAMUnlockAction, SAMUnlockKeyId, 0, 0);
}
else if (cmd is SAMAV2ISO7816Commands samav2cmd)
{
samav2cmd.lockUnlock(key, SAMUnlockAction, SAMUnlockKeyId, SAMUnlockKeyId, SAMUnlockKey.Version);
samav2cmd.lockUnlock(key, SAMUnlockAction, SAMUnlockKeyId, 0, 0);
}

if (SnackbarMessageQueue != null)
SnackbarHelper.EnqueueMessage(SnackbarMessageQueue, "SAM Lock/Unlock completed.");
}
catch (Exception ex)
{
Expand Down
4 changes: 2 additions & 2 deletions KeyManager.Library.KeyStore.NXP_SAM/SAMKeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ public void ActivateMifareSAM(SAMAV2ISO7816Commands av2cmd)
public void ActivateMifareSAM(SAMAV2ISO7816Commands av2cmd, byte keyno, DESFireKeyType keyType, byte keyVersion, string? keyValue)
{
var key = CreateDESFireKey(keyType, keyVersion, keyValue);
av2cmd.lockUnlock(key, SAMLockUnlock.SwitchAV2Mode /* AV3 = Active Mifare SAM */, keyno, keyno, keyVersion);
av2cmd.lockUnlock(key, SAMLockUnlock.SwitchAV2Mode /* AV3 = Active Mifare SAM */, keyno, 0, 0);
log.Info("Mifare SAM features activation completed.");
}

Expand All @@ -570,7 +570,7 @@ public static void UnlockSAM(SAMAV2ISO7816Commands av2cmd, byte keyEntry, byte k
key.setKeyType(DESFireKeyType.DF_KEY_AES);
key.setKeyVersion(keyVersion);
key.fromString(keyValue ?? "");
av2cmd.lockUnlock(key, SAMLockUnlock.Unlock, keyEntry, 0x00, 0x00);
av2cmd.lockUnlock(key, SAMLockUnlock.Unlock, keyEntry, 0, 0);
log.Info("SAM unlocked.");
}

Expand Down
31 changes: 25 additions & 6 deletions KeyManager.Library.UI/Domain/KeyEntriesControlViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System.Windows.Data;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows.Threading;
using System.Windows.Input;

namespace Leosac.KeyManager.Library.UI.Domain
{
Expand All @@ -18,7 +20,9 @@ public class KeyEntriesControlViewModel : ObservableValidator
public KeyEntriesControlViewModel(ISnackbarMessageQueue snackbarMessageQueue)
{
_snackbarMessageQueue = snackbarMessageQueue;
_identifierLock = new object();
Identifiers = new ObservableCollection<SelectableKeyEntryId>();
BindingOperations.EnableCollectionSynchronization(Identifiers, _identifierLock);
WizardFactories = new ObservableCollection<WizardFactory>(WizardFactory.RegisteredFactories);

CreateKeyEntryCommand = new RelayCommand(
Expand Down Expand Up @@ -160,6 +164,7 @@ public KeyEntriesControlViewModel(ISnackbarMessageQueue snackbarMessageQueue)
}

protected ISnackbarMessageQueue _snackbarMessageQueue;
private object _identifierLock;
private KeyStore.KeyStore? _keyStore;
private KeyEntryClass _keClass;
private bool _showSelection;
Expand Down Expand Up @@ -407,17 +412,31 @@ private void ToggleAllSelection(bool selected)

public async Task RefreshKeyEntries()
{
Identifiers.Clear();
lock (_identifierLock)
{
Mouse.OverrideCursor = Cursors.Wait;
Identifiers.Clear();
}
if (KeyStore != null)
{
foreach (var id in await KeyStore.GetAll(_keClass))
var ids = await KeyStore.GetAll(_keClass);
foreach (var id in ids)
{
Identifiers.Add(new SelectableKeyEntryId() {
Selected = false,
KeyEntryId = id
});
lock (_identifierLock)
{
Identifiers.Add(new SelectableKeyEntryId()
{
Selected = false,
KeyEntryId = id
});
}
}
}

lock (_identifierLock)
{
Mouse.OverrideCursor = null;
}
}

public void RefreshKeyEntriesView()
Expand Down
2 changes: 1 addition & 1 deletion KeyManager.Library.UI/Domain/KeyEntryDialogViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public KeyEntryDialogViewModel()
BeforeSubmitCommand = new RelayCommand(
() =>
{
DialogHost.CloseDialogCommand.Execute(null, null);
DialogHost.CloseDialogCommand.Execute(KeyEntry, null);
}, CanSubmit);
}

Expand Down
46 changes: 20 additions & 26 deletions KeyManager.Library.UI/KeyEntriesControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,17 @@
Command="{Binding DataContext.ShowSelectionChangedCommand, ElementName=keyStoreControl}"/>
<WrapPanel Orientation="Horizontal" Visibility="{Binding DataContext.ShowSelection, ElementName=keyStoreControl, Converter={StaticResource BoolToVisibleConverter}}">
<Rectangle VerticalAlignment="Stretch" Width="1" Margin="2" Stroke="Gray" />
<materialDesign:PopupBox
<materialDesign:DialogHost DialogClosed="KeyEntryDeletion_OnDialogClosed" DialogTheme="Inherit">
<materialDesign:DialogHost.DialogContent>
<StackPanel Margin="16">
<TextBlock Text="{x:Static properties:Resources.DeleteKeyEntryConfirmation}" />
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{Binding Identifiers}" Content="{x:Static properties:Resources.Confirm}" IsDefault="True" Style="{StaticResource MaterialDesignFlatButton}" />
<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" Content="{x:Static properties:Resources.Cancel}" IsCancel="True" Style="{StaticResource MaterialDesignFlatButton}" />
</StackPanel>
</StackPanel>
</materialDesign:DialogHost.DialogContent>
<materialDesign:PopupBox
PlacementMode="BottomAndAlignCentres"
ToolTip="{x:Static properties:Resources.Selection}" Margin="5"
Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}">
Expand All @@ -77,29 +87,16 @@
ToolTip="{x:Static properties:Resources.ToggleSelectAll}" Margin="5">
<materialDesign:PackIcon Kind="CheckAll" Height="24" Width="24" Cursor="Hand" />
</Button>
<materialDesign:DialogHost DialogClosed="KeyEntryDeletion_OnDialogClosed" DialogTheme="Inherit">
<materialDesign:DialogHost.DialogContent>
<StackPanel Margin="16">
<TextBlock Text="{x:Static properties:Resources.DeleteKeyEntryConfirmation}" />

<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{Binding Identifiers}" Content="{x:Static properties:Resources.Confirm}" IsDefault="True" Style="{StaticResource MaterialDesignFlatButton}">
</Button>

<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" Content="{x:Static properties:Resources.Cancel}" IsCancel="True" Style="{StaticResource MaterialDesignFlatButton}" />
</StackPanel>
</StackPanel>
</materialDesign:DialogHost.DialogContent>
<Button x:Name="btnDeleteKeyEntry" Style="{StaticResource MaterialDesignFloatingActionButton}"
Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}"
ToolTip="{x:Static properties:Resources.DeleteKeyEntry}"
Visibility="{Binding DataContext.KeyStore.CanDeleteKeyEntries, ElementName=keyStoreControl, Converter={StaticResource BoolToVisibleConverter}}"
Margin="5">
<materialDesign:PackIcon Kind="Delete" Height="24" Width="24" Cursor="Hand" />
</Button>
</materialDesign:DialogHost>
<Button x:Name="btnDeleteKeyEntry" Style="{StaticResource MaterialDesignFloatingActionButton}"
Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}"
ToolTip="{x:Static properties:Resources.DeleteKeyEntry}"
Visibility="{Binding KeyStore.CanDeleteKeyEntries, Converter={StaticResource BoolToVisibleConverter}}"
Margin="5">
<materialDesign:PackIcon Kind="Delete" Height="24" Width="24" Cursor="Hand" />
</Button>
</StackPanel>
</materialDesign:PopupBox>
</materialDesign:DialogHost>
</WrapPanel>
</WrapPanel>
<DockPanel LastChildFill="True" Grid.Column="1">
Expand Down Expand Up @@ -133,11 +130,8 @@
<materialDesign:DialogHost.DialogContent>
<StackPanel Margin="16">
<TextBlock Text="{x:Static properties:Resources.DeleteKeyEntryConfirmation}" />

<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{Binding}" Content="{x:Static properties:Resources.Confirm}" IsDefault="True" Style="{StaticResource MaterialDesignFlatButton}">
</Button>

<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" CommandParameter="{Binding}" Content="{x:Static properties:Resources.Confirm}" IsDefault="True" Style="{StaticResource MaterialDesignFlatButton}" />
<Button Margin="0,8,8,0" Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}" Content="{x:Static properties:Resources.Cancel}" IsCancel="True" Style="{StaticResource MaterialDesignFlatButton}" />
</StackPanel>
</StackPanel>
Expand Down
32 changes: 29 additions & 3 deletions KeyManager/Domain/EditKeyStoreControlViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using Leosac.KeyManager.Library.Plugin;
using Leosac.KeyManager.Library.UI;
using Leosac.KeyManager.Library.UI.Domain;
using Leosac.WpfApp.Domain;
using Leosac.WpfApp;
using MaterialDesignThemes.Wpf;
using System;
Expand All @@ -14,6 +13,7 @@
using System.Collections.Generic;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows.Input;

namespace Leosac.KeyManager.Domain
{
Expand All @@ -26,6 +26,7 @@ public EditKeyStoreControlViewModel(ISnackbarMessageQueue snackbarMessageQueue)
_snackbarMessageQueue = snackbarMessageQueue;
Tabs = new ObservableCollection<TabItem>();
_keModels = new List<KeyEntriesControlViewModel>();
RefreshKeyEntriesCommand = new AsyncRelayCommand(() => RefreshKeyEntries(500));
SaveFavoriteCommand = new RelayCommand(
() =>
{
Expand Down Expand Up @@ -79,10 +80,19 @@ public int ProgressMaximum
set => SetProperty(ref _progressMaximum, value);
}

private bool _isLoadingKeyEntries;
public bool IsLoadingKeyEntries
{
get => _isLoadingKeyEntries;
set => SetProperty(ref _isLoadingKeyEntries, value);
}

public ObservableCollection<TabItem> Tabs { get; set; }

public RelayCommand? HomeCommand { get; set; }

public AsyncRelayCommand RefreshKeyEntriesCommand { get; }

public RelayCommand SaveFavoriteCommand { get; }

public void CloseKeyStore(bool navigate = true)
Expand All @@ -101,6 +111,7 @@ public async Task OpenKeyStore()
{
if (KeyStore != null)
{
Mouse.OverrideCursor = Cursors.Wait;
await KeyStore.Open();
var classes = KeyStore.SupportedClasses;
foreach (var kclass in classes)
Expand All @@ -109,15 +120,30 @@ public async Task OpenKeyStore()
_keModels.Add(model);
Tabs.Add(new TabItem()
{
Header = String.Format("{0} Key Entries", kclass.ToString()),
Header = string.Format("{0} Key Entries", kclass.ToString()),
Content = new KeyEntriesControl()
{
DataContext = model
}
});
await model.RefreshKeyEntries();
}
Mouse.OverrideCursor = null;
await RefreshKeyEntries();
}
}

public async Task RefreshKeyEntries(int delay = 0)
{
IsLoadingKeyEntries = true;
if (delay > 0)
{
await Task.Delay(delay);
}
foreach (var model in _keModels)
{
await model.RefreshKeyEntries();
}
IsLoadingKeyEntries = false;
}

public async Task EditFavorite()
Expand Down
Loading

0 comments on commit 5aa39bf

Please sign in to comment.