17
17
using System . Globalization ;
18
18
using System . Numerics ;
19
19
using System . Security ;
20
+ using System . Security . Cryptography ;
20
21
using System . Security . Cryptography . X509Certificates ;
21
22
using Yubico . Core . Tlv ;
22
23
using Yubico . YubiKey . Cryptography ;
@@ -118,7 +119,6 @@ public X509Certificate2 CreateAttestationStatement(byte slotNumber)
118
119
// This call will throw an exception if there was a problem with
119
120
// attestation (imported, invalid cert, etc.).
120
121
return response . GetData ( ) ;
121
-
122
122
}
123
123
124
124
/// <summary>
@@ -404,8 +404,7 @@ private void CheckVersionKeyAndCertRequirements(KeyType keyType, X509Certificate
404
404
ExceptionMessages . NotSupportedByYubiKeyVersion ) ) ;
405
405
}
406
406
407
- bool isValidCert = IsSupportedCert ( certificate , keyType ) ;
408
- if ( ! isValidCert )
407
+ if ( ! IsSupportedCert ( certificate , keyType ) )
409
408
{
410
409
throw new ArgumentException (
411
410
string . Format (
@@ -414,19 +413,48 @@ private void CheckVersionKeyAndCertRequirements(KeyType keyType, X509Certificate
414
413
}
415
414
}
416
415
417
- // Is there really a cert in this variable? Is it > version 1?
418
- // If so, set certDer to the DER encoding of the cert.
419
416
private static bool IsSupportedCert ( X509Certificate2 certificate , KeyType keyType )
420
417
{
421
- byte [ ] certDer = certificate . GetRawCertData ( ) ;
418
+ string oidValue = certificate . PublicKey . Oid . Value ;
419
+ bool isRsa = oidValue == Oids . RSA ;
420
+ if ( isRsa && certificate . PublicKey . Key . KeySize == KeyDefinitions . RSA1024 . LengthInBits )
421
+ {
422
+ // RSA 1024 is not supported for attestation.
423
+ return false ;
424
+ }
422
425
426
+ var certKeyType = oidValue switch
427
+ {
428
+ Oids . ECDSA => GetKeyTypeForECDsa ( certificate . GetECDsaPublicKey ( ) ) ,
429
+ Oids . RSA => GetKeyTypeForRSA ( certificate . GetRSAPublicKey ( ) ) ,
430
+ Oids . Ed25519 => KeyType . Ed25519 ,
431
+ _ => throw new ArgumentException ( $ "Unsupported key type: { keyType } ")
432
+ } ;
433
+
434
+ // var certKeyType = isRsa
435
+ // ? KeyDefinitions.GetByRSALength(certificate.PublicKey.Key.KeySize).KeyType
436
+ // : GetKeyTypeForECDsa(certificate);
437
+ bool isSameAlgorithm = certKeyType == keyType ;
438
+ byte [ ] certDer = certificate . GetRawCertData ( ) ;
423
439
return certificate . Handle != IntPtr . Zero &&
424
440
certificate . Version > 1 &&
425
441
certDer . Length is > 0 and < MaximumCertDerLength &&
426
- certificate . PublicKey . Oid . Value == keyType . GetAlgorithmOid ( ) &&
442
+ isSameAlgorithm &&
427
443
IsValidCertNameAndValidity ( certDer ) ;
428
444
}
429
445
446
+ private static KeyType GetKeyTypeForECDsa ( ECDsa ecdsa )
447
+ {
448
+ var parameters = ecdsa . ExportParameters ( false ) ;
449
+ return KeyDefinitions . GetByOid ( parameters . Curve . Oid ) . KeyType ;
450
+ }
451
+
452
+ private static KeyType GetKeyTypeForRSA ( RSA rsa )
453
+ {
454
+ var parameters = rsa . ExportParameters ( false ) ;
455
+ return KeyDefinitions . GetByRSAModulusLength ( parameters . Modulus ) . KeyType ;
456
+ }
457
+
430
458
private static bool IsValidCertNameAndValidity ( byte [ ] certDer )
431
459
{
432
460
var reader = new AsnReader ( certDer , AsnEncodingRules . BER ) ;
@@ -445,7 +473,8 @@ private static bool IsValidCertNameAndValidity(byte[] certDer)
445
473
var subject = seqTbsCert . ReadSequence ( ) ;
446
474
int subjectValue = GetSequenceLength ( subject ) ;
447
475
448
- return validityValue < MaximumValidityValueLength && subjectValue < MaximumNameValueLength ;
476
+ return validityValue < MaximumValidityValueLength &&
477
+ subjectValue < MaximumNameValueLength ;
449
478
}
450
479
451
480
private static BigInteger ? ReadVersion ( AsnReader seqTbsCert )
0 commit comments