From c5c1b14570423dad420cb2047e1e0e3debfa3228 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Thu, 11 May 2023 22:36:52 +0200 Subject: [PATCH] PM-1575 Added new models for Fido2Key --- src/Core/Constants.cs | 3 + src/Core/Enums/CipherType.cs | 3 +- src/Core/Models/Api/Fido2KeyApi.cs | 16 +++++ src/Core/Models/Api/LoginApi.cs | 1 + src/Core/Models/Data/CipherData.cs | 4 ++ src/Core/Models/Data/Fido2KeyData.cs | 34 ++++++++++ src/Core/Models/Data/LoginData.cs | 2 + src/Core/Models/Domain/Cipher.cs | 10 +++ src/Core/Models/Domain/Fido2Key.cs | 77 ++++++++++++++++++++++ src/Core/Models/Domain/Login.cs | 9 +++ src/Core/Models/Response/CipherResponse.cs | 1 + src/Core/Models/View/CipherView.cs | 4 +- src/Core/Models/View/Fido2KeyView.cs | 23 +++++++ src/Core/Models/View/LoginView.cs | 2 + 14 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 src/Core/Models/Api/Fido2KeyApi.cs create mode 100644 src/Core/Models/Data/Fido2KeyData.cs create mode 100644 src/Core/Models/Domain/Fido2Key.cs create mode 100644 src/Core/Models/View/Fido2KeyView.cs diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 0f4b0915c..f5c8d9d9a 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -60,6 +60,9 @@ public const int Argon2MemoryInMB = 64; public const int Argon2Parallelism = 4; public const int MasterPasswordMinimumChars = 12; + public const string DefaultFido2KeyType = "public-key"; + public const string DefaultFido2KeyAlgorithm = "ECDSA"; + public const string DefaultFido2KeyCurve = "P-256"; public static readonly string[] AndroidAllClearCipherCacheKeys = { diff --git a/src/Core/Enums/CipherType.cs b/src/Core/Enums/CipherType.cs index 0aca94864..cefa35182 100644 --- a/src/Core/Enums/CipherType.cs +++ b/src/Core/Enums/CipherType.cs @@ -7,6 +7,7 @@ Login = 1, SecureNote = 2, Card = 3, - Identity = 4 + Identity = 4, + Fido2Key = 5 } } diff --git a/src/Core/Models/Api/Fido2KeyApi.cs b/src/Core/Models/Api/Fido2KeyApi.cs new file mode 100644 index 000000000..666f08456 --- /dev/null +++ b/src/Core/Models/Api/Fido2KeyApi.cs @@ -0,0 +1,16 @@ +namespace Bit.Core.Models.Api +{ + public class Fido2KeyApi + { + public string NonDiscoverableId { get; set; } + public string KeyType { get; set; } = Constants.DefaultFido2KeyType; + public string KeyAlgorithm { get; set; } = Constants.DefaultFido2KeyAlgorithm; + public string KeyCurve { get; set; } = Constants.DefaultFido2KeyCurve; + public string KeyValue { get; set; } + public string RpId { get; set; } + public string RpName { get; set; } + public string UserHandle { get; set; } + public string UserName { get; set; } + public string Counter { get; set; } + } +} diff --git a/src/Core/Models/Api/LoginApi.cs b/src/Core/Models/Api/LoginApi.cs index b611c2eb8..42d32f343 100644 --- a/src/Core/Models/Api/LoginApi.cs +++ b/src/Core/Models/Api/LoginApi.cs @@ -10,5 +10,6 @@ namespace Bit.Core.Models.Api public string Password { get; set; } public DateTime? PasswordRevisionDate { get; set; } public string Totp { get; set; } + public Fido2KeyApi Fido2Key { get; set; } } } diff --git a/src/Core/Models/Data/CipherData.cs b/src/Core/Models/Data/CipherData.cs index c571771a7..56181338f 100644 --- a/src/Core/Models/Data/CipherData.cs +++ b/src/Core/Models/Data/CipherData.cs @@ -43,6 +43,9 @@ namespace Bit.Core.Models.Data case Enums.CipherType.Identity: Identity = new IdentityData(response.Identity); break; + case Enums.CipherType.Fido2Key: + Fido2Key = new Fido2KeyData(response.Fido2Key); + break; default: break; } @@ -80,6 +83,7 @@ namespace Bit.Core.Models.Data public SecureNoteData SecureNote { get; set; } public CardData Card { get; set; } public IdentityData Identity { get; set; } + public Fido2KeyData Fido2Key { get; set; } public List Fields { get; set; } public List Attachments { get; set; } public List PasswordHistory { get; set; } diff --git a/src/Core/Models/Data/Fido2KeyData.cs b/src/Core/Models/Data/Fido2KeyData.cs new file mode 100644 index 000000000..234406eee --- /dev/null +++ b/src/Core/Models/Data/Fido2KeyData.cs @@ -0,0 +1,34 @@ +using Bit.Core.Models.Api; + +namespace Bit.Core.Models.Data +{ + public class Fido2KeyData : Data + { + public Fido2KeyData() { } + + public Fido2KeyData(Fido2KeyApi apiData) + { + NonDiscoverableId = apiData.NonDiscoverableId; + KeyType = apiData.KeyType; + KeyAlgorithm = apiData.KeyAlgorithm; + KeyCurve = apiData.KeyCurve; + KeyValue = apiData.KeyValue; + RpId = apiData.RpId; + RpName = apiData.RpName; + UserHandle = apiData.UserHandle; + UserName = apiData.UserName; + Counter = apiData.Counter; + } + + public string NonDiscoverableId { get; set; } + public string KeyType { get; set; } = Constants.DefaultFido2KeyType; + public string KeyAlgorithm { get; set; } = Constants.DefaultFido2KeyAlgorithm; + public string KeyCurve { get; set; } = Constants.DefaultFido2KeyCurve; + public string KeyValue { get; set; } + public string RpId { get; set; } + public string RpName { get; set; } + public string UserHandle { get; set; } + public string UserName { get; set; } + public string Counter { get; set; } + } +} diff --git a/src/Core/Models/Data/LoginData.cs b/src/Core/Models/Data/LoginData.cs index 286c542ed..1460e0b17 100644 --- a/src/Core/Models/Data/LoginData.cs +++ b/src/Core/Models/Data/LoginData.cs @@ -16,6 +16,7 @@ namespace Bit.Core.Models.Data PasswordRevisionDate = data.PasswordRevisionDate; Totp = data.Totp; Uris = data.Uris?.Select(u => new LoginUriData(u)).ToList(); + Fido2Key = data.Fido2Key != null ? new Fido2KeyData(data.Fido2Key) : null; } public List Uris { get; set; } @@ -23,5 +24,6 @@ namespace Bit.Core.Models.Data public string Password { get; set; } public DateTime? PasswordRevisionDate { get; set; } public string Totp { get; set; } + public Fido2KeyData Fido2Key { get; set; } } } diff --git a/src/Core/Models/Domain/Cipher.cs b/src/Core/Models/Domain/Cipher.cs index d744f6a57..cfe1db60c 100644 --- a/src/Core/Models/Domain/Cipher.cs +++ b/src/Core/Models/Domain/Cipher.cs @@ -47,6 +47,9 @@ namespace Bit.Core.Models.Domain case Enums.CipherType.Identity: Identity = new Identity(obj.Identity, alreadyEncrypted); break; + case CipherType.Fido2Key: + Fido2Key = new Fido2Key(obj.Fido2Key, alreadyEncrypted); + break; default: break; } @@ -73,6 +76,7 @@ namespace Bit.Core.Models.Domain public Identity Identity { get; set; } public Card Card { get; set; } public SecureNote SecureNote { get; set; } + public Fido2Key Fido2Key { get; set; } public List Attachments { get; set; } public List Fields { get; set; } public List PasswordHistory { get; set; } @@ -103,6 +107,9 @@ namespace Bit.Core.Models.Domain case Enums.CipherType.Identity: model.Identity = await Identity.DecryptAsync(OrganizationId); break; + case Enums.CipherType.Fido2Key: + model.Fido2Key = await Fido2Key.DecryptAsync(OrganizationId); + break; default: break; } @@ -191,6 +198,9 @@ namespace Bit.Core.Models.Domain case Enums.CipherType.Identity: c.Identity = Identity.ToIdentityData(); break; + case Enums.CipherType.Fido2Key: + c.Fido2Key= Fido2Key.ToFido2KeyData(); + break; default: break; } diff --git a/src/Core/Models/Domain/Fido2Key.cs b/src/Core/Models/Domain/Fido2Key.cs new file mode 100644 index 000000000..c2a9191d3 --- /dev/null +++ b/src/Core/Models/Domain/Fido2Key.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Bit.Core.Models.Data; +using Bit.Core.Models.View; + +namespace Bit.Core.Models.Domain +{ + public class Fido2Key : Domain + { + public Fido2Key() { } + + public Fido2Key(Fido2KeyData data, bool alreadyEncrypted = false) + { + BuildDomainModel(this, data, new HashSet + { + nameof(NonDiscoverableId), + nameof(KeyType), + nameof(KeyAlgorithm), + nameof(KeyCurve), + nameof(KeyValue), + nameof(RpId), + nameof(RpName), + nameof(UserHandle), + nameof(UserName), + nameof(Counter) + }, alreadyEncrypted); + } + + public EncString NonDiscoverableId { get; set; } + public EncString KeyType { get; set; } + public EncString KeyAlgorithm { get; set; } + public EncString KeyCurve { get; set; } + public EncString KeyValue { get; set; } + public EncString RpId { get; set; } + public EncString RpName { get; set; } + public EncString UserHandle { get; set; } + public EncString UserName { get; set; } + public EncString Counter { get; set; } + + public async Task DecryptAsync(string orgId) + { + return await DecryptObjAsync(new Fido2KeyView(), this, new HashSet + { + nameof(NonDiscoverableId), + nameof(KeyType), + nameof(KeyAlgorithm), + nameof(KeyCurve), + nameof(KeyValue), + nameof(RpId), + nameof(RpName), + nameof(UserHandle), + nameof(UserName), + nameof(Counter) + }, orgId); + } + + public Fido2KeyData ToFido2KeyData() + { + var data = new Fido2KeyData(); + BuildDataModel(this, data, new HashSet + { + nameof(NonDiscoverableId), + nameof(KeyType), + nameof(KeyAlgorithm), + nameof(KeyCurve), + nameof(KeyValue), + nameof(RpId), + nameof(RpName), + nameof(UserHandle), + nameof(UserName), + nameof(Counter) + }); + return data; + } + } +} diff --git a/src/Core/Models/Domain/Login.cs b/src/Core/Models/Domain/Login.cs index 00c0ab07b..5501b043f 100644 --- a/src/Core/Models/Domain/Login.cs +++ b/src/Core/Models/Domain/Login.cs @@ -28,6 +28,7 @@ namespace Bit.Core.Models.Domain public EncString Password { get; set; } public DateTime? PasswordRevisionDate { get; set; } public EncString Totp { get; set; } + public Fido2Key Fido2Key { get; set; } public async Task DecryptAsync(string orgId) { @@ -45,6 +46,10 @@ namespace Bit.Core.Models.Domain view.Uris.Add(await uri.DecryptAsync(orgId)); } } + if (Fido2Key != null) + { + view.Fido2Key = await Fido2Key.DecryptAsync(orgId); + } return view; } @@ -62,6 +67,10 @@ namespace Bit.Core.Models.Domain { l.Uris = Uris.Select(u => u.ToLoginUriData()).ToList(); } + if (Fido2Key != null) + { + l.Fido2Key = Fido2Key.ToFido2KeyData(); + } return l; } } diff --git a/src/Core/Models/Response/CipherResponse.cs b/src/Core/Models/Response/CipherResponse.cs index 070d41eee..4abfcf4c0 100644 --- a/src/Core/Models/Response/CipherResponse.cs +++ b/src/Core/Models/Response/CipherResponse.cs @@ -18,6 +18,7 @@ namespace Bit.Core.Models.Response public CardApi Card { get; set; } public IdentityApi Identity { get; set; } public SecureNoteApi SecureNote { get; set; } + public Fido2KeyApi Fido2Key { get; set; } public bool Favorite { get; set; } public bool Edit { get; set; } public bool ViewPassword { get; set; } = true; // Fallback for old server versions diff --git a/src/Core/Models/View/CipherView.cs b/src/Core/Models/View/CipherView.cs index 6bec74ee4..c4f6455cf 100644 --- a/src/Core/Models/View/CipherView.cs +++ b/src/Core/Models/View/CipherView.cs @@ -42,6 +42,7 @@ namespace Bit.Core.Models.View public IdentityView Identity { get; set; } public CardView Card { get; set; } public SecureNoteView SecureNote { get; set; } + public Fido2KeyView Fido2Key { get; set; } public List Attachments { get; set; } public List Fields { get; set; } public List PasswordHistory { get; set; } @@ -64,6 +65,8 @@ namespace Bit.Core.Models.View return Card; case CipherType.Identity: return Identity; + case CipherType.Fido2Key: + return Fido2Key; default: break; } @@ -109,6 +112,5 @@ namespace Bit.Core.Models.View { return LinkedFieldOptions.Find(lfo => lfo.Value == id).Key; } - } } diff --git a/src/Core/Models/View/Fido2KeyView.cs b/src/Core/Models/View/Fido2KeyView.cs new file mode 100644 index 000000000..06d8e4cef --- /dev/null +++ b/src/Core/Models/View/Fido2KeyView.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Bit.Core.Enums; + +namespace Bit.Core.Models.View +{ + public class Fido2KeyView : ItemView + { + public string NonDiscoverableId { get; set; } + public string KeyType { get; set; } = Constants.DefaultFido2KeyType; + public string KeyAlgorithm { get; set; } = Constants.DefaultFido2KeyAlgorithm; + public string KeyCurve { get; set; } = Constants.DefaultFido2KeyCurve; + public string KeyValue { get; set; } + public string RpId { get; set; } + public string RpName { get; set; } + public string UserHandle { get; set; } + public string UserName { get; set; } + public string Counter { get; set; } + + public override string SubTitle => UserName; + + public override List> LinkedFieldOptions => new List>(); + } +} diff --git a/src/Core/Models/View/LoginView.cs b/src/Core/Models/View/LoginView.cs index 850082115..94a735dc6 100644 --- a/src/Core/Models/View/LoginView.cs +++ b/src/Core/Models/View/LoginView.cs @@ -20,6 +20,8 @@ namespace Bit.Core.Models.View public DateTime? PasswordRevisionDate { get; set; } public string Totp { get; set; } public List Uris { get; set; } + public Fido2KeyView Fido2Key { get; set; } + public string Uri => HasUris ? Uris[0].Uri : null; public string MaskedPassword => Password != null ? "••••••••" : null; public override string SubTitle => Username;