@@ -25,46 +25,36 @@ namespace Yubico.YubiKey.Piv;
25
25
26
26
public static class KeyParametersPivHelper
27
27
{
28
- // PIV TLV Encoding ---> IPrivateKeyParameters
29
- public static T CreatePrivateParametersFromPivEncoding < T > ( ReadOnlyMemory < byte > pivEncodingBytes )
30
- where T : IPrivateKeyParameters
31
- {
32
- if ( pivEncodingBytes . IsEmpty )
28
+ public static IPublicKeyParameters CreatePublicKeyParameters ( ReadOnlyMemory < byte > pivEncodedKey , KeyType keyType ) =>
29
+ keyType switch
33
30
{
34
- throw new ArgumentException (
31
+ KeyType . Ed25519 or KeyType . X25519 => KeyParametersPivHelper
32
+ . CreatePublicCurve25519FromPivEncoding ( pivEncodedKey , keyType ) ,
33
+ KeyType . P256 or KeyType . P384 or KeyType . P521 => KeyParametersPivHelper
34
+ . CreatePublicEcFromPivEncoding ( pivEncodedKey ) ,
35
+ KeyType . RSA1024 or KeyType . RSA2048 or KeyType . RSA3072 or KeyType . RSA4096 => KeyParametersPivHelper
36
+ . CreatePublicRsaFromPivEncoding ( pivEncodedKey ) ,
37
+ _ => throw new InvalidOperationException (
35
38
string . Format (
36
39
CultureInfo . CurrentCulture ,
37
- ExceptionMessages . InvalidPrivateKeyData ) ) ;
38
- }
39
-
40
- byte tag = pivEncodingBytes . Span [ 0 ] ;
41
- IPrivateKeyParameters pkp = tag switch
42
- {
43
- _ when PivConstants . IsValidPrivateECTag ( tag ) => CreatePrivateEcFromPivEncoding ( pivEncodingBytes ) ,
44
- _ when PivConstants . IsValidPrivateRSATag ( tag ) => CreatePrivateRsaFromPivEncoding ( pivEncodingBytes ) ,
45
- _ => throw new ArgumentException (
46
- string . Format ( CultureInfo . CurrentCulture , ExceptionMessages . InvalidPrivateKeyData ) )
40
+ ExceptionMessages . InvalidApduResponseData ) )
47
41
} ;
48
-
49
- return ( T ) pkp ;
50
- }
51
42
52
- public static IPublicKeyParameters CreatePublicParameters ( ReadOnlyMemory < byte > value , KeyType keyType )
53
- {
54
- return keyType switch
43
+ // TODO Is this needed?
44
+ public static IPrivateKeyParameters CreatePrivateKeyParameters ( ReadOnlyMemory < byte > value , KeyType keyType ) =>
45
+ keyType switch
55
46
{
56
47
KeyType . Ed25519 or KeyType . X25519 => KeyParametersPivHelper
57
- . CreatePublicCurve25519FromPivEncoding ( value , keyType ) ,
48
+ . CreatePrivateCurve25519FromPivEncoding ( value , keyType ) ,
58
49
KeyType . P256 or KeyType . P384 or KeyType . P521 => KeyParametersPivHelper
59
- . CreatePublicEcFromPivEncoding ( value ) ,
50
+ . CreatePrivateEcFromPivEncoding ( value ) ,
60
51
KeyType . RSA1024 or KeyType . RSA2048 or KeyType . RSA3072 or KeyType . RSA4096 => KeyParametersPivHelper
61
- . CreatePublicRsaFromPivEncoding ( value ) ,
52
+ . CreatePrivateRsaFromPivEncoding ( value ) ,
62
53
_ => throw new InvalidOperationException (
63
54
string . Format (
64
55
CultureInfo . CurrentCulture ,
65
56
ExceptionMessages . InvalidApduResponseData ) )
66
57
} ;
67
- }
68
58
69
59
public static RSAPublicKeyParameters CreatePublicRsaFromPivEncoding ( ReadOnlyMemory < byte > pivEncodingBytes )
70
60
{
@@ -108,30 +98,63 @@ public static Curve25519PublicKeyParameters CreatePublicCurve25519FromPivEncodin
108
98
var publicPoint = PivEncodingReader . GetECPublicPointValues ( pivEncodingBytes ) ;
109
99
return Curve25519PublicKeyParameters . CreateFromValue ( publicPoint , keyType ) ;
110
100
}
101
+
102
+ public static Curve25519PrivateKeyParameters CreatePrivateCurve25519FromPivEncoding (
103
+ ReadOnlyMemory < byte > pivEncodingBytes ,
104
+ KeyType keyType )
105
+ {
106
+ if ( ! TlvObject . TryParse ( pivEncodingBytes . Span , out var tlv ) || ! PivConstants . IsValidPrivateECTag ( tlv . Tag ) )
107
+ {
108
+ throw new ArgumentException (
109
+ string . Format (
110
+ CultureInfo . CurrentCulture ,
111
+ ExceptionMessages . InvalidPrivateKeyData ) ) ;
112
+ }
113
+
114
+ using var privateValueHandle = new ZeroingMemoryHandle ( tlv . Value . ToArray ( ) ) ;
115
+
116
+ return tlv . Tag switch
117
+ {
118
+ PivConstants . PrivateECEd25519Tag when keyType == KeyType . Ed25519 => Curve25519PrivateKeyParameters . CreateFromValue (
119
+ privateValueHandle . Data , KeyType . Ed25519 ) ,
120
+
121
+ PivConstants . PrivateECX25519Tag when keyType == KeyType . X25519 => Curve25519PrivateKeyParameters . CreateFromValue (
122
+ privateValueHandle . Data , KeyType . X25519 ) ,
123
+
124
+ _ => throw new ArgumentException (
125
+ string . Format (
126
+ CultureInfo . CurrentCulture ,
127
+ ExceptionMessages . InvalidPrivateKeyData ) )
128
+ } ;
129
+ }
111
130
112
131
public static ECPrivateKeyParameters CreatePrivateEcFromPivEncoding ( ReadOnlyMemory < byte > pivEncodingBytes )
113
132
{
114
- if ( TlvObject . TryParse ( pivEncodingBytes . Span , out var tlv ) && PivConstants . IsValidPrivateECTag ( tlv . Tag ) )
133
+ if ( ! TlvObject . TryParse ( pivEncodingBytes . Span , out var tlv ) || tlv . Tag != PivConstants . PrivateECDsaTag )
115
134
{
116
- switch ( tlv . Tag )
117
- {
118
- case PivConstants . PrivateECDsaTag :
119
- List < KeyDefinition > allowed =
120
- [ KeyDefinitions . P256 , KeyDefinitions . P384 , KeyDefinitions . P521 ] ;
121
-
122
- var keyDefinition = allowed . Single ( kd => kd . LengthInBytes == tlv . Value . Span . Length ) ;
123
- return ECPrivateKeyParameters . CreateFromValue ( tlv . Value . Span . ToArray ( ) , keyDefinition . KeyType ) ;
124
- case PivConstants . PrivateECEd25519Tag :
125
- return ECPrivateKeyParameters . CreateFromValue ( tlv . Value . ToArray ( ) , KeyType . Ed25519 ) ;
126
- case PivConstants . PrivateECX25519Tag :
127
- return ECPrivateKeyParameters . CreateFromValue ( tlv . Value . ToArray ( ) , KeyType . X25519 ) ;
128
- }
135
+ throw new ArgumentException (
136
+ string . Format (
137
+ CultureInfo . CurrentCulture ,
138
+ ExceptionMessages . InvalidPrivateKeyData ) ) ;
139
+ }
140
+
141
+ var allowedKeyDefinitions = KeyDefinitions
142
+ . GetEcKeyDefinitions ( )
143
+ . Where ( kd => kd . AlgorithmOid == KeyDefinitions . CryptoOids . ECDSA ) ;
144
+ try
145
+ {
146
+ var keyDefinition = allowedKeyDefinitions
147
+ . Single ( kd => kd . LengthInBytes == tlv . Value . Span . Length ) ;
148
+ ReadOnlyMemory < byte > value = tlv . Value ;
149
+ return ECPrivateKeyParameters . CreateFromValue ( value , keyDefinition . KeyType ) ;
150
+ }
151
+ catch ( InvalidOperationException )
152
+ {
153
+ throw new ArgumentException (
154
+ string . Format (
155
+ CultureInfo . CurrentCulture ,
156
+ ExceptionMessages . InvalidPrivateKeyData ) ) ;
129
157
}
130
-
131
- throw new ArgumentException (
132
- string . Format (
133
- CultureInfo . CurrentCulture ,
134
- ExceptionMessages . InvalidPrivateKeyData ) ) ;
135
158
}
136
159
137
160
public static RSAPrivateKeyParameters CreatePrivateRsaFromPivEncoding ( ReadOnlyMemory < byte > pivEncodingBytes )
@@ -177,7 +200,7 @@ public static RSAPrivateKeyParameters CreatePrivateRsaFromPivEncoding(ReadOnlyMe
177
200
var exponentQ = valueArray [ PivConstants . PrivateRSAExponentQTag - 1 ] . Span ;
178
201
var coefficient = valueArray [ PivConstants . PrivateRSACoefficientTag - 1 ] . Span ;
179
202
180
- var rsaParameters = new RSAParameters
203
+ var parameters = new RSAParameters
181
204
{
182
205
P = primeP . ToArray ( ) ,
183
206
Q = primeQ . ToArray ( ) ,
@@ -191,6 +214,6 @@ public static RSAPrivateKeyParameters CreatePrivateRsaFromPivEncoding(ReadOnlyMe
191
214
Exponent = Array . Empty < byte > ( ) ,
192
215
} ;
193
216
194
- return RSAPrivateKeyParameters . CreateFromParameters ( rsaParameters ) ;
217
+ return RSAPrivateKeyParameters . CreateFromParameters ( parameters ) ;
195
218
}
196
219
}
0 commit comments