Skip to content

Commit

Permalink
Add Default Key Entry definition on Key Store and add first Key Gener…
Browse files Browse the repository at this point in the history
…ation logic
  • Loading branch information
Maxhy committed Oct 22, 2023
1 parent c5cbab7 commit a620780
Show file tree
Hide file tree
Showing 24 changed files with 487 additions and 71 deletions.
4 changes: 4 additions & 0 deletions KeyManager.Library.KeyStore.File/FileKeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ protected string GetKeyEntryFile(KeyEntryId identifier, KeyEntryClass keClass)

public override Task<bool> CheckKeyEntryExists(KeyEntryId identifier, KeyEntryClass keClass)
{
if (!string.IsNullOrEmpty(identifier.Label))
{
log.Warn("KeyEntry label specified but such key resolution is not supported by the key store type.");
}
return Task.FromResult(System.IO.File.Exists(GetKeyEntryFile(identifier, keClass)));
}

Expand Down
115 changes: 101 additions & 14 deletions KeyManager.Library.KeyStore.HSM_PKCS11/PKCS11KeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,21 +118,8 @@ public override async Task Create(IChangeKeyEntry change)
var rawkey = material.GetValueBinary();
if (rawkey != null)
{
var attributes = GetKeyEntryAttributes(entry, true);
var attributes = GetKeyEntryAttributes(entry, true, material.Name);
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_VALUE, rawkey));
if (entry.KClass == KeyEntryClass.PrivateKey || (entry.KClass == KeyEntryClass.Asymmetric && material.Name == KeyMaterial.PRIVATE_KEY))
{
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
}
else if (entry.KClass == KeyEntryClass.PublicKey || (entry.KClass == KeyEntryClass.Asymmetric && material.Name == KeyMaterial.PUBLIC_KEY))
{
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
}
else
{
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
}

_session!.CreateObject(attributes);
}
}
Expand Down Expand Up @@ -161,12 +148,79 @@ public override async Task Create(IChangeKeyEntry change)
log.Info(string.Format("Key entry `{0}` created.", change.Identifier));
}

public override Task<KeyEntryId> Generate(KeyEntryId? identifier, KeyEntryClass keClass)
{
if (identifier == null)
{
identifier = new KeyEntryId();
}

if (keClass != KeyEntryClass.Symmetric)
{
log.Error(string.Format("The key store doesn't support key entry generation without specifing the target type for class `{0}`.", keClass));
throw new NotImplementedException();
}

var keyEntry = new SymmetricPKCS11KeyEntry
{
Identifier = identifier
};
keyEntry.Variant = keyEntry.GetAllVariants(keClass).FirstOrDefault(v => v.Name == "GENERIC_SECRET");
keyEntry.PKCS11Properties!.Extractable = true;
return Generate(keyEntry);
}

public override Task<KeyEntryId> Generate(KeyEntry keyEntry)
{
log.Info(string.Format("Generating key entry `{0}`...", keyEntry.Identifier));

if(keyEntry.KClass != KeyEntryClass.Symmetric)
{
log.Error(string.Format("The key store doesn't support key entry generation for class `{0}`.", keyEntry.KClass));
throw new NotImplementedException();
}

var attributes = GetKeyEntryAttributes(keyEntry, true);
IMechanism? mechanism = null;
var key = keyEntry.Variant?.KeyContainers.FirstOrDefault()?.Key;
if (key != null)
{
if (key.Tags.Contains("AES"))
{
mechanism = _session!.Factories.MechanismFactory.Create(CKM.CKM_AES_KEY_GEN);
}
else if (key.Tags.Contains("DES") && key.KeySize == 8)
{
mechanism = _session!.Factories.MechanismFactory.Create(CKM.CKM_DES_KEY_GEN);
}
else if (key.Tags.Contains("DES") && key.KeySize == 16)
{
mechanism = _session!.Factories.MechanismFactory.Create(CKM.CKM_DES2_KEY_GEN);
}
else if (key.Tags.Contains("DES") && key.KeySize == 24)
{
mechanism = _session!.Factories.MechanismFactory.Create(CKM.CKM_DES3_KEY_GEN);
}
}

mechanism ??= _session!.Factories.MechanismFactory.Create(CKM.CKM_GENERIC_SECRET_KEY_GEN);

_session!.GenerateKey(mechanism, attributes);
log.Info(string.Format("Key entry `{0}` generated.", keyEntry.Identifier));
return Task.FromResult(keyEntry.Identifier);
}

private List<IObjectAttribute> GetKeyEntryAttributes(KeyEntry? entry)
{
return GetKeyEntryAttributes(entry, false);
}

private List<IObjectAttribute> GetKeyEntryAttributes(KeyEntry? entry, bool create)
{
return GetKeyEntryAttributes(entry, create, null);
}

private List<IObjectAttribute> GetKeyEntryAttributes(KeyEntry? entry, bool create, string? materialName)
{
if (entry != null && entry.Variant?.KeyContainers.Count > 1)
{
Expand Down Expand Up @@ -226,6 +280,22 @@ private List<IObjectAttribute> GetKeyEntryAttributes(KeyEntry? entry, bool creat
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
}

if (entry != null && !string.IsNullOrEmpty(materialName))
{
if (entry.KClass == KeyEntryClass.PrivateKey || (entry.KClass == KeyEntryClass.Asymmetric && materialName == KeyMaterial.PRIVATE_KEY))
{
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
}
else if (entry.KClass == KeyEntryClass.PublicKey || (entry.KClass == KeyEntryClass.Asymmetric && materialName == KeyMaterial.PUBLIC_KEY))
{
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
}
else
{
attributes.Add(_session!.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
}
}

return attributes;
}

Expand Down Expand Up @@ -590,5 +660,22 @@ public override async Task Update(IChangeKeyEntry change, bool ignoreIfMissing)

log.Info(string.Format("Key entry `{0}` updated.", change.Identifier));
}

public override KeyEntry? GetDefaultKeyEntry(KeyEntryClass keClass)
{
var keyEntry = base.GetDefaultKeyEntry(keClass);
if (keyEntry == null)
{
if (keClass == KeyEntryClass.Symmetric)
{
keyEntry = new SymmetricPKCS11KeyEntry();
}
else if (keClass == KeyEntryClass.Asymmetric)
{
keyEntry = new AsymmetricPKCS11KeyEntry();
}
}
return keyEntry;
}
}
}
39 changes: 39 additions & 0 deletions KeyManager.Library.KeyStore.LCP/LCPKeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public override async Task<bool> CheckKeyEntryExists(KeyEntryId identifier, KeyE
{
CheckAuthentication();

if (!string.IsNullOrEmpty(identifier.Label))
{
log.Warn("KeyEntry label specified but such key resolution is not supported by the key store type.");
}

if (!string.IsNullOrEmpty(identifier.Id))
{
var key = await _keyAPI!.Get(Guid.Parse(identifier.Id));
Expand Down Expand Up @@ -81,6 +86,30 @@ public override async Task Create(IChangeKeyEntry change)
log.Info(string.Format("Key entry `{0}` created.", change.Identifier));
}

public override Task<KeyEntryId> Generate(KeyEntryId? identifier, KeyEntryClass keClass)
{
if (identifier == null)
{
identifier = new KeyEntryId();
}

var keyEntry = new LCPKeyEntry
{
Identifier = identifier
};

if (keClass == KeyEntryClass.Symmetric)
{
keyEntry.Variant = keyEntry.GetAllVariants(keClass).FirstOrDefault(v => v.Name == "AES128");
}
else
{
log.Error(string.Format("The key store doesn't support key entry generation without specifing the target type for class `{0}`.", keClass));
throw new NotImplementedException();
}
return Generate(keyEntry);
}

public override async Task Delete(KeyEntryId identifier, KeyEntryClass keClass, bool ignoreIfMissing)
{
log.Info(string.Format("Deleting key entry `{0}`...", identifier));
Expand Down Expand Up @@ -258,6 +287,16 @@ public override async Task Update(IChangeKeyEntry change, bool ignoreIfMissing)
log.Info(string.Format("Key entry `{0}` updated.", change.Identifier));
}

public override KeyEntry? GetDefaultKeyEntry(KeyEntryClass keClass)
{
var keyEntry = base.GetDefaultKeyEntry(keClass);
if (keyEntry == null)
{
keyEntry = new LCPKeyEntry(keClass);
}
return keyEntry;
}

private static CredentialKey CreateCredentialKey(KeyEntryId identifier, KeyContainer? kc, LCPKeyEntryProperties? properties)
{
var key = new CredentialKey();
Expand Down
32 changes: 30 additions & 2 deletions KeyManager.Library.KeyStore.Memory/MemoryKeyStore.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Leosac.KeyManager.Library.KeyStore.Memory
using Org.BouncyCastle.Tls;

namespace Leosac.KeyManager.Library.KeyStore.Memory
{
public class MemoryKeyStore : KeyStore
{
Expand Down Expand Up @@ -39,7 +41,11 @@ public override Task<bool> CheckKeyEntryExists(KeyEntryId identifier, KeyEntryCl

protected Task<bool> CheckKeyEntryExists(KeyEntryId identifier, KeyEntryClass keClass, out KeyEntry? keyEntry)
{
keyEntry = _keyEntries.Where(k => k.Identifier == identifier && k.KClass == keClass).SingleOrDefault();
keyEntry = _keyEntries.SingleOrDefault(k => k.Identifier.Id == identifier.Id && k.KClass == keClass);
if (keyEntry == null && !string.IsNullOrEmpty(identifier.Label))
{
keyEntry = _keyEntries.SingleOrDefault(k => k.Identifier.Label?.ToLowerInvariant() == identifier.Label?.ToLowerInvariant() && k.KClass == keClass);
}
return Task.FromResult(keyEntry != null);
}

Expand All @@ -60,6 +66,28 @@ public override async Task Create(IChangeKeyEntry change)
}
}

public override Task<KeyEntryId> Generate(KeyEntryId? identifier, KeyEntryClass keClass)
{
if (identifier == null)
{
identifier = new KeyEntryId();
}

var keyEntry = new MemoryKeyEntry
{
Identifier = identifier
};
if (keClass == KeyEntryClass.Symmetric)
{
keyEntry.Variant = keyEntry.GetAllVariants(keClass).FirstOrDefault(v => v.Name == "AES128");
}
else
{
keyEntry.Variant = keyEntry.GetAllVariants(keClass).FirstOrDefault(v => v.Name == "RSA");
}
return Generate(keyEntry);
}

public override async Task Delete(KeyEntryId identifier, KeyEntryClass keClass, bool ignoreIfMissing)
{
if (!await CheckKeyEntryExists(identifier, keClass, out KeyEntry? keyEntry) && !ignoreIfMissing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override IList<Leosac.KeyManager.Library.KeyStore.KeyEntry> GetKeyEntries
return entries;
}

private SAMSymmetricKeyEntry CreateKeyEntry(string id, string label, bool generateKeys = true)
private static SAMSymmetricKeyEntry CreateKeyEntry(string id, string label, bool generateKeys = true)
{
var ke = new SAMSymmetricKeyEntry();
ke.Identifier.Id = id;
Expand All @@ -62,11 +62,10 @@ private SAMSymmetricKeyEntry CreateKeyEntry(string id, string label, bool genera
{
for (byte i = 0; i < ke.Variant!.KeyContainers.Count; ++i)
{
var keyVersion = ke.Variant.KeyContainers[i] as KeyVersion;
if (keyVersion != null)
if (ke.Variant.KeyContainers[i] is KeyVersion keyVersion)
{
keyVersion.Version = i;
keyVersion.Key.Materials[0].Value = KeyGeneration.Random((int)keyVersion.Key.KeySize);
keyVersion.Key.Materials[0].Value = KeyGeneration.Random(keyVersion.Key.KeySize);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions KeyManager.Library.KeyStore.NXP_SAM/ISLOG/ISLOGKeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public override IEnumerable<KeyEntryClass> SupportedClasses

public override Task<bool> CheckKeyEntryExists(KeyEntryId identifier, KeyEntryClass keClass)
{
if (!string.IsNullOrEmpty(identifier.Label))
{
log.Warn("KeyEntry label specified but such key resolution is not supported by the key store type.");
}
var id = GetId(identifier, keClass);
return Task.FromResult(_keyEntries.ContainsKey(id));
}
Expand Down
16 changes: 16 additions & 0 deletions KeyManager.Library.KeyStore.NXP_SAM/SAMKeyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ public override Task Close()

public override Task<bool> CheckKeyEntryExists(KeyEntryId identifier, KeyEntryClass keClass)
{
if (!string.IsNullOrEmpty(identifier.Label))
{
log.Warn("KeyEntry label specified but such key resolution is not supported by the key store type.");
}
if (identifier.Id == null)
{
return Task.FromResult(false);
Expand Down Expand Up @@ -716,5 +720,17 @@ public void UpdateCounter(SAMKeyUsageCounter counter)
throw new KeyStoreException("Inserted SAM is not in AV2 mode.");
}
}
public override KeyEntry? GetDefaultKeyEntry(KeyEntryClass keClass)
{
var keyEntry = base.GetDefaultKeyEntry(keClass);
if (keyEntry == null)
{
if (keClass == KeyEntryClass.Symmetric)
{
keyEntry = new SAMSymmetricKeyEntry();
}
}
return keyEntry;
}
}
}
4 changes: 2 additions & 2 deletions KeyManager.Library.Tests/KeyGenerationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ public class KeyGenerationTests
[DataRow(8)]
[DataRow(16)]
[DataRow(32)]
public void Test_Random(int keySize)
public void Test_Random(uint keySize)
{
var key1 = KeyGeneration.Random(keySize);
Assert.AreEqual(keySize * 2, key1.Length);
Assert.AreEqual(keySize * 2, (uint)key1.Length);

var key2 = KeyGeneration.Random(keySize);
Assert.AreNotEqual(key1, key2);
Expand Down
Loading

0 comments on commit a620780

Please sign in to comment.