Skip to content

Commit ace1a0a

Browse files
committed
refactor: reuse logic for GetMetadata (PivSession)
1 parent d307713 commit ace1a0a

File tree

3 files changed

+33
-52
lines changed

3 files changed

+33
-52
lines changed

Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.Crypto.cs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ public byte[] Decrypt(byte slotNumber, ReadOnlyMemory<byte> dataToDecrypt)
266266
CultureInfo.CurrentCulture,
267267
ExceptionMessages.IncorrectCiphertextLength));
268268
}
269-
269+
270270
[Obsolete("Usage of PivEccPublic/PivEccPrivateKey is deprecated. Use IPublicKey, IPrivateKey instead", false)]
271271
public byte[] KeyAgree(byte slotNumber, PivPublicKey correspondentPublicKey)
272272
{
@@ -287,7 +287,8 @@ public byte[] KeyAgree(byte slotNumber, PivPublicKey correspondentPublicKey)
287287

288288
// This will verify the slot number and dataToSign length. If one or
289289
// both are incorrect, the call will throw an exception.
290-
var keyAgreeCommand = new AuthenticateKeyAgreeCommand(publicPoint, slotNumber, correspondentPublicKey.Algorithm);
290+
var keyAgreeCommand = new AuthenticateKeyAgreeCommand(
291+
publicPoint, slotNumber, correspondentPublicKey.Algorithm);
291292

292293
return PerformPrivateKeyOperation(
293294
slotNumber,
@@ -297,7 +298,7 @@ public byte[] KeyAgree(byte slotNumber, PivPublicKey correspondentPublicKey)
297298
CultureInfo.CurrentCulture,
298299
ExceptionMessages.IncorrectEccKeyLength));
299300
}
300-
301+
301302
/// <summary>
302303
/// Perform Phase 2 of EC Diffie-Hellman Key Agreement using the private
303304
/// key in the given slot, and the corresponding party's public key.
@@ -398,9 +399,9 @@ public byte[] KeyAgree(byte slotNumber, IPublicKey correspondentPublicKey)
398399
CultureInfo.CurrentCulture,
399400
ExceptionMessages.InvalidPublicKeyData))
400401
};
401-
402+
402403
var keyAgreeCommand = new AuthenticateKeyAgreeCommand(
403-
publicPoint, slotNumber,
404+
publicPoint, slotNumber,
404405
correspondentPublicKey.KeyType.GetPivAlgorithm());
405406

406407
return PerformPrivateKeyOperation(
@@ -430,16 +431,9 @@ private byte[] PerformPrivateKeyOperation(
430431
// to verify the PIN again.
431432
// If the PIN policy is Always, we need to verify the PIN.
432433

433-
// Metadata will give us our answer, but that feature is
434-
// available only on YubiKeys beginning with version 5.3.
435-
if (YubiKey.HasFeature(YubiKeyFeature.PivMetadata))
434+
var metadata = GetMetadataInternal(slotNumber);
435+
if (metadata is not null)
436436
{
437-
var metadataCommand = new GetMetadataCommand(slotNumber);
438-
var metadataResponse = Connection.SendCommand(metadataCommand);
439-
440-
// If there is no key in the slot, this will throw an exception.
441-
var metadata = metadataResponse.GetData();
442-
443437
// We know the algorithm based on the input data. Is it the
444438
// algorithm of the key in the slot?
445439
// We can make this check with metadata. Without metadata there's
@@ -514,14 +508,10 @@ private byte[] PerformPrivateKeyOperation(
514508

515509
private AuthenticateSignCommand BuildSignCommand(byte slotNumber, ReadOnlyMemory<byte> dataToSign)
516510
{
517-
if (!YubiKey.HasFeature(YubiKeyFeature.PivMetadata))
518-
{
519-
return new AuthenticateSignCommand(dataToSign, slotNumber);
520-
}
521-
522-
var slotMetadata = GetMetadata(slotNumber);
523-
var algorithm = slotMetadata.Algorithm;
524-
return new AuthenticateSignCommand(dataToSign, slotNumber, algorithm);
511+
var slotMetadata = GetMetadataInternal(slotNumber);
512+
return slotMetadata is null
513+
? new AuthenticateSignCommand(dataToSign, slotNumber)
514+
: new AuthenticateSignCommand(dataToSign, slotNumber, slotMetadata.Algorithm);
525515
}
526516
}
527517
}

Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.ManagementKey.cs

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ private bool TryAuthenticateManagementKey(
10131013
}
10141014

10151015
ManagementKeyAuthenticated = true;
1016-
return true;
1016+
return true;
10171017
}
10181018

10191019
Logger.LogInformation($"Failed to authenticate management key. Message: {completeResponse.StatusMessage}");
@@ -1023,24 +1023,8 @@ private bool TryAuthenticateManagementKey(
10231023

10241024
private void RefreshManagementKeyAlgorithm() => ManagementKeyAlgorithm = GetManagementKeyAlgorithm();
10251025

1026-
private PivAlgorithm GetManagementKeyAlgorithm()
1027-
{
1028-
if (!YubiKey.HasFeature(YubiKeyFeature.PivMetadata))
1029-
{
1030-
// Assume default for version
1031-
return DefaultManagementKeyAlgorithm;
1032-
}
1033-
1034-
// Get current ManagementKeyAlgorithm from Yubikey metadata
1035-
var response = Connection.SendCommand(new GetMetadataCommand(PivSlot.Management));
1036-
if (response.Status != ResponseStatus.Success)
1037-
{
1038-
throw new InvalidOperationException(response.StatusMessage);
1039-
}
1040-
1041-
var metadata = response.GetData();
1042-
return metadata.Algorithm;
1043-
}
1026+
private PivAlgorithm GetManagementKeyAlgorithm() =>
1027+
GetMetadataInternal(PivSlot.Management)?.Algorithm ?? DefaultManagementKeyAlgorithm;
10441028

10451029
// Verify that and that the given algorithm is allowed.
10461030
// If checkMode is true, also check that the PIN-only mode is None.
@@ -1077,15 +1061,16 @@ private void CheckManagementKeyAlgorithm(PivAlgorithm algorithm, bool checkMode)
10771061
ExceptionMessages.UnsupportedAlgorithm));
10781062
}
10791063
}
1080-
1064+
10811065
private bool IsValidManagementKeyAlgorithm(PivAlgorithm pivAlgorithm) =>
10821066
pivAlgorithm switch
10831067
{
10841068
PivAlgorithm.TripleDes => true, // Default for keys below fw version 5.7
1085-
PivAlgorithm.Aes128 or PivAlgorithm.Aes192 or PivAlgorithm.Aes256 => YubiKey.HasFeature(YubiKeyFeature.PivAesManagementKey),
1069+
PivAlgorithm.Aes128 or PivAlgorithm.Aes192 or PivAlgorithm.Aes256 => YubiKey.HasFeature(
1070+
YubiKeyFeature.PivAesManagementKey),
10861071
_ => false
10871072
};
1088-
1073+
10891074
private PivAlgorithm DefaultManagementKeyAlgorithm =>
10901075
YubiKey.HasFeature(YubiKeyFeature.PivAesManagementKey) &&
10911076
YubiKey.FirmwareVersion >= FirmwareVersion.V5_7_0

Yubico.YubiKey/src/Yubico/YubiKey/Piv/PivSession.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ protected override void Dispose(bool disposing)
231231
KeyCollector = null;
232232
ResetAuthenticationStatus();
233233
}
234+
234235
base.Dispose(disposing);
235236
}
236237

@@ -280,18 +281,11 @@ public PivMetadata GetMetadata(byte slotNumber)
280281
{
281282
Logger.LogInformation("GetMetadata for slot number {SlotNumber:X2}.", slotNumber);
282283

283-
if (!YubiKey.HasFeature(YubiKeyFeature.PivMetadata))
284-
{
284+
return GetMetadataInternal(slotNumber) ??
285285
throw new NotSupportedException(
286286
string.Format(
287287
CultureInfo.CurrentCulture,
288288
ExceptionMessages.NotSupportedByYubiKeyVersion));
289-
}
290-
291-
var command = new GetMetadataCommand(slotNumber);
292-
var response = Connection.SendCommand(command);
293-
294-
return response.GetData();
295289
}
296290

297291
/// <summary>
@@ -571,5 +565,17 @@ private void TryBlock(byte slot)
571565
CultureInfo.CurrentCulture,
572566
ExceptionMessages.ApplicationResetFailure));
573567
}
568+
569+
private PivMetadata? GetMetadataInternal(byte slotNumber)
570+
{
571+
if (!YubiKey.HasFeature(YubiKeyFeature.PivMetadata))
572+
{
573+
return null;
574+
}
575+
576+
var command = new GetMetadataCommand(slotNumber);
577+
var response = Connection.SendCommand(command);
578+
return response.GetData();
579+
}
574580
}
575581
}

0 commit comments

Comments
 (0)