1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
use std::convert::TryFrom;
use anyhow::Result;
use nom::branch::alt;
use nom::combinator::map;
use nom::{branch, bytes::complete as bytes, combinator, multi, sequence};
use std::fmt;
use crate::algorithm::{Algo, AlgoInfo};
use crate::card_do::{algo_attrs, complete};
use crate::KeyType;
impl AlgoInfo {
pub fn get_by_keytype(&self, kt: KeyType) -> Vec<&Algo> {
self.0
.iter()
.filter(|(k, _)| *k == kt)
.map(|(_, a)| a)
.collect()
}
}
impl fmt::Display for AlgoInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (kt, a) in &self.0 {
let kt = match kt {
KeyType::Signing => "SIG",
KeyType::Decryption => "DEC",
KeyType::Authentication => "AUT",
KeyType::Attestation => "ATT",
};
writeln!(f, "{}: {} ", kt, a)?;
}
Ok(())
}
}
fn key_type(input: &[u8]) -> nom::IResult<&[u8], KeyType> {
alt((
map(bytes::tag([0xc1]), |_| KeyType::Signing),
map(bytes::tag([0xc2]), |_| KeyType::Decryption),
map(bytes::tag([0xc3]), |_| KeyType::Authentication),
map(bytes::tag([0xda]), |_| KeyType::Attestation),
))(input)
}
fn unknown(input: &[u8]) -> nom::IResult<&[u8], Algo> {
Ok((&[], Algo::Unknown(input.to_vec())))
}
fn parse_one(input: &[u8]) -> nom::IResult<&[u8], Algo> {
let (input, a) = combinator::map(
combinator::flat_map(crate::tlv::length::length, bytes::take),
|i| alt((combinator::all_consuming(algo_attrs::parse), unknown))(i),
)(input)?;
Ok((input, a?.1))
}
fn parse_list(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, Algo)>> {
multi::many0(sequence::pair(key_type, parse_one))(input)
}
fn parse_tl_list(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, Algo)>> {
let (input, (_, _, list)) = sequence::tuple((
bytes::tag([0xfa]),
crate::tlv::length::length,
parse_list,
))(input)?;
Ok((input, list))
}
pub(self) fn parse(input: &[u8]) -> nom::IResult<&[u8], Vec<(KeyType, Algo)>> {
branch::alt((
combinator::all_consuming(parse_list),
combinator::all_consuming(parse_tl_list),
))(input)
}
impl TryFrom<&[u8]> for AlgoInfo {
type Error = anyhow::Error;
fn try_from(input: &[u8]) -> Result<Self> {
Ok(AlgoInfo(complete(parse(input))?))
}
}
#[cfg(test)]
mod test {
use std::convert::TryFrom;
use crate::algorithm::{Algo::*, AlgoInfo, Curve::*, EccAttrs, RsaAttrs};
use crate::crypto_data::EccType::*;
use crate::KeyType::*;
#[test]
fn test_gnuk() {
let data = [
0xc1, 0x6, 0x1, 0x8, 0x0, 0x0, 0x20, 0x0, 0xc1, 0x6, 0x1, 0x10,
0x0, 0x0, 0x20, 0x0, 0xc1, 0x9, 0x13, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x3, 0x1, 0x7, 0xc1, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0xa,
0xc1, 0xa, 0x16, 0x2b, 0x6, 0x1, 0x4, 0x1, 0xda, 0x47, 0xf, 0x1,
0xc2, 0x6, 0x1, 0x8, 0x0, 0x0, 0x20, 0x0, 0xc2, 0x6, 0x1, 0x10,
0x0, 0x0, 0x20, 0x0, 0xc2, 0x9, 0x13, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x3, 0x1, 0x7, 0xc2, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0xa,
0xc2, 0xb, 0x12, 0x2b, 0x6, 0x1, 0x4, 0x1, 0x97, 0x55, 0x1, 0x5,
0x1, 0xc3, 0x6, 0x1, 0x8, 0x0, 0x0, 0x20, 0x0, 0xc3, 0x6, 0x1,
0x10, 0x0, 0x0, 0x20, 0x0, 0xc3, 0x9, 0x13, 0x2a, 0x86, 0x48,
0xce, 0x3d, 0x3, 0x1, 0x7, 0xc3, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0,
0xa, 0xc3, 0xa, 0x16, 0x2b, 0x6, 0x1, 0x4, 0x1, 0xda, 0x47, 0xf,
0x1,
];
let ai = AlgoInfo::try_from(&data[..]).unwrap();
assert_eq!(
ai,
AlgoInfo(vec![
(Signing, Rsa(RsaAttrs::new(2048, 32, 0))),
(Signing, Rsa(RsaAttrs::new(4096, 32, 0))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, Secp256k1, None))),
(Signing, Ecc(EccAttrs::new(EdDSA, Ed25519, None))),
(Decryption, Rsa(RsaAttrs::new(2048, 32, 0))),
(Decryption, Rsa(RsaAttrs::new(4096, 32, 0))),
(Decryption, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDSA, Secp256k1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, Cv25519, None))),
(Authentication, Rsa(RsaAttrs::new(2048, 32, 0))),
(Authentication, Rsa(RsaAttrs::new(4096, 32, 0))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Authentication, Ecc(EccAttrs::new(ECDSA, Secp256k1, None))),
(Authentication, Ecc(EccAttrs::new(EdDSA, Ed25519, None)))
])
);
}
#[test]
fn test_opgp_card_34() {
let data = [
0xc1, 0x6, 0x1, 0x8, 0x0, 0x0, 0x20, 0x0, 0xc1, 0x6, 0x1, 0xc,
0x0, 0x0, 0x20, 0x0, 0xc1, 0x6, 0x1, 0x10, 0x0, 0x0, 0x20, 0x0,
0xc1, 0x9, 0x13, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x3, 0x1, 0x7,
0xc1, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0x22, 0xc1, 0x6, 0x13,
0x2b, 0x81, 0x4, 0x0, 0x23, 0xc1, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3,
0x2, 0x8, 0x1, 0x1, 0x7, 0xc1, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3,
0x2, 0x8, 0x1, 0x1, 0xb, 0xc1, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3,
0x2, 0x8, 0x1, 0x1, 0xd, 0xc2, 0x6, 0x1, 0x8, 0x0, 0x0, 0x20, 0x0,
0xc2, 0x6, 0x1, 0xc, 0x0, 0x0, 0x20, 0x0, 0xc2, 0x6, 0x1, 0x10,
0x0, 0x0, 0x20, 0x0, 0xc2, 0x9, 0x12, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x3, 0x1, 0x7, 0xc2, 0x6, 0x12, 0x2b, 0x81, 0x4, 0x0, 0x22,
0xc2, 0x6, 0x12, 0x2b, 0x81, 0x4, 0x0, 0x23, 0xc2, 0xa, 0x12,
0x2b, 0x24, 0x3, 0x3, 0x2, 0x8, 0x1, 0x1, 0x7, 0xc2, 0xa, 0x12,
0x2b, 0x24, 0x3, 0x3, 0x2, 0x8, 0x1, 0x1, 0xb, 0xc2, 0xa, 0x12,
0x2b, 0x24, 0x3, 0x3, 0x2, 0x8, 0x1, 0x1, 0xd, 0xc3, 0x6, 0x1,
0x8, 0x0, 0x0, 0x20, 0x0, 0xc3, 0x6, 0x1, 0xc, 0x0, 0x0, 0x20,
0x0, 0xc3, 0x6, 0x1, 0x10, 0x0, 0x0, 0x20, 0x0, 0xc3, 0x9, 0x13,
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x3, 0x1, 0x7, 0xc3, 0x6, 0x13,
0x2b, 0x81, 0x4, 0x0, 0x22, 0xc3, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0,
0x23, 0xc3, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3, 0x2, 0x8, 0x1, 0x1,
0x7, 0xc3, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3, 0x2, 0x8, 0x1, 0x1,
0xb, 0xc3, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3, 0x2, 0x8, 0x1, 0x1,
0xd,
];
let ai = AlgoInfo::try_from(&data[..]).unwrap();
assert_eq!(
ai,
AlgoInfo(vec![
(Signing, Rsa(RsaAttrs::new(2048, 32, 0))),
(Signing, Rsa(RsaAttrs::new(3072, 32, 0))),
(Signing, Rsa(RsaAttrs::new(4096, 32, 0))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP384r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP521r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, BrainpoolP256r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, BrainpoolP384r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, BrainpoolP512r1, None))),
(Decryption, Rsa(RsaAttrs::new(2048, 32, 0))),
(Decryption, Rsa(RsaAttrs::new(3072, 32, 0))),
(Decryption, Rsa(RsaAttrs::new(4096, 32, 0))),
(Decryption, Ecc(EccAttrs::new(ECDH, NistP256r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, NistP384r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, NistP521r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, BrainpoolP256r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, BrainpoolP384r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, BrainpoolP512r1, None))),
(Authentication, Rsa(RsaAttrs::new(2048, 32, 0))),
(Authentication, Rsa(RsaAttrs::new(3072, 32, 0))),
(Authentication, Rsa(RsaAttrs::new(4096, 32, 0))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP384r1, None))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP521r1, None))),
(
Authentication,
Ecc(EccAttrs::new(ECDSA, BrainpoolP256r1, None))
),
(
Authentication,
Ecc(EccAttrs::new(ECDSA, BrainpoolP384r1, None))
),
(
Authentication,
Ecc(EccAttrs::new(ECDSA, BrainpoolP512r1, None))
)
])
);
}
#[test]
fn test_yk5() {
let data = [
0xfa, 0x82, 0x1, 0xe2, 0xc1, 0x6, 0x1, 0x8, 0x0, 0x0, 0x11, 0x0,
0xc1, 0x6, 0x1, 0xc, 0x0, 0x0, 0x11, 0x0, 0xc1, 0x6, 0x1, 0x10,
0x0, 0x0, 0x11, 0x0, 0xc1, 0x9, 0x13, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x3, 0x1, 0x7, 0xc1, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0x22,
0xc1, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0x23, 0xc1, 0x6, 0x13,
0x2b, 0x81, 0x4, 0x0, 0xa, 0xc1, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3,
0x2, 0x8, 0x1, 0x1, 0x7, 0xc1, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3,
0x2, 0x8, 0x1, 0x1, 0xb, 0xc1, 0xa, 0x13, 0x2b, 0x24, 0x3, 0x3,
0x2, 0x8, 0x1, 0x1, 0xd, 0xc1, 0xa, 0x16, 0x2b, 0x6, 0x1, 0x4,
0x1, 0xda, 0x47, 0xf, 0x1, 0xc1, 0xb, 0x16, 0x2b, 0x6, 0x1, 0x4,
0x1, 0x97, 0x55, 0x1, 0x5, 0x1, 0xc2, 0x6, 0x1, 0x8, 0x0, 0x0,
0x11, 0x0, 0xc2, 0x6, 0x1, 0xc, 0x0, 0x0, 0x11, 0x0, 0xc2, 0x6,
0x1, 0x10, 0x0, 0x0, 0x11, 0x0, 0xc2, 0x9, 0x12, 0x2a, 0x86, 0x48,
0xce, 0x3d, 0x3, 0x1, 0x7, 0xc2, 0x6, 0x12, 0x2b, 0x81, 0x4, 0x0,
0x22, 0xc2, 0x6, 0x12, 0x2b, 0x81, 0x4, 0x0, 0x23, 0xc2, 0x6,
0x12, 0x2b, 0x81, 0x4, 0x0, 0xa, 0xc2, 0xa, 0x12, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0x7, 0xc2, 0xa, 0x12, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0xb, 0xc2, 0xa, 0x12, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0xd, 0xc2, 0xa, 0x16, 0x2b, 0x6, 0x1,
0x4, 0x1, 0xda, 0x47, 0xf, 0x1, 0xc2, 0xb, 0x16, 0x2b, 0x6, 0x1,
0x4, 0x1, 0x97, 0x55, 0x1, 0x5, 0x1, 0xc3, 0x6, 0x1, 0x8, 0x0,
0x0, 0x11, 0x0, 0xc3, 0x6, 0x1, 0xc, 0x0, 0x0, 0x11, 0x0, 0xc3,
0x6, 0x1, 0x10, 0x0, 0x0, 0x11, 0x0, 0xc3, 0x9, 0x13, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x3, 0x1, 0x7, 0xc3, 0x6, 0x13, 0x2b, 0x81, 0x4,
0x0, 0x22, 0xc3, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0x23, 0xc3, 0x6,
0x13, 0x2b, 0x81, 0x4, 0x0, 0xa, 0xc3, 0xa, 0x13, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0x7, 0xc3, 0xa, 0x13, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0xb, 0xc3, 0xa, 0x13, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0xd, 0xc3, 0xa, 0x16, 0x2b, 0x6, 0x1,
0x4, 0x1, 0xda, 0x47, 0xf, 0x1, 0xc3, 0xb, 0x16, 0x2b, 0x6, 0x1,
0x4, 0x1, 0x97, 0x55, 0x1, 0x5, 0x1, 0xda, 0x6, 0x1, 0x8, 0x0,
0x0, 0x11, 0x0, 0xda, 0x6, 0x1, 0xc, 0x0, 0x0, 0x11, 0x0, 0xda,
0x6, 0x1, 0x10, 0x0, 0x0, 0x11, 0x0, 0xda, 0x9, 0x13, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x3, 0x1, 0x7, 0xda, 0x6, 0x13, 0x2b, 0x81, 0x4,
0x0, 0x22, 0xda, 0x6, 0x13, 0x2b, 0x81, 0x4, 0x0, 0x23, 0xda, 0x6,
0x13, 0x2b, 0x81, 0x4, 0x0, 0xa, 0xda, 0xa, 0x13, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0x7, 0xda, 0xa, 0x13, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0xb, 0xda, 0xa, 0x13, 0x2b, 0x24, 0x3,
0x3, 0x2, 0x8, 0x1, 0x1, 0xd, 0xda, 0xa, 0x16, 0x2b, 0x6, 0x1,
0x4, 0x1, 0xda, 0x47, 0xf, 0x1, 0xda, 0xb, 0x16, 0x2b, 0x6, 0x1,
0x4, 0x1, 0x97, 0x55, 0x1, 0x5, 0x1,
];
let ai = AlgoInfo::try_from(&data[..]).unwrap();
assert_eq!(
ai,
AlgoInfo(vec![
(Signing, Rsa(RsaAttrs::new(2048, 17, 0))),
(Signing, Rsa(RsaAttrs::new(3072, 17, 0))),
(Signing, Rsa(RsaAttrs::new(4096, 17, 0))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP384r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, NistP521r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, Secp256k1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, BrainpoolP256r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, BrainpoolP384r1, None))),
(Signing, Ecc(EccAttrs::new(ECDSA, BrainpoolP512r1, None))),
(Signing, Ecc(EccAttrs::new(EdDSA, Ed25519, None))),
(Signing, Ecc(EccAttrs::new(EdDSA, Cv25519, None))),
(Decryption, Rsa(RsaAttrs::new(2048, 17, 0))),
(Decryption, Rsa(RsaAttrs::new(3072, 17, 0))),
(Decryption, Rsa(RsaAttrs::new(4096, 17, 0))),
(Decryption, Ecc(EccAttrs::new(ECDH, NistP256r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, NistP384r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, NistP521r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, Secp256k1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, BrainpoolP256r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, BrainpoolP384r1, None))),
(Decryption, Ecc(EccAttrs::new(ECDH, BrainpoolP512r1, None))),
(Decryption, Ecc(EccAttrs::new(EdDSA, Ed25519, None))),
(Decryption, Ecc(EccAttrs::new(EdDSA, Cv25519, None))),
(Authentication, Rsa(RsaAttrs::new(2048, 17, 0))),
(Authentication, Rsa(RsaAttrs::new(3072, 17, 0))),
(Authentication, Rsa(RsaAttrs::new(4096, 17, 0))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP384r1, None))),
(Authentication, Ecc(EccAttrs::new(ECDSA, NistP521r1, None))),
(Authentication, Ecc(EccAttrs::new(ECDSA, Secp256k1, None))),
(
Authentication,
Ecc(EccAttrs::new(ECDSA, BrainpoolP256r1, None))
),
(
Authentication,
Ecc(EccAttrs::new(ECDSA, BrainpoolP384r1, None))
),
(
Authentication,
Ecc(EccAttrs::new(ECDSA, BrainpoolP512r1, None))
),
(Authentication, Ecc(EccAttrs::new(EdDSA, Ed25519, None))),
(Authentication, Ecc(EccAttrs::new(EdDSA, Cv25519, None))),
(Attestation, Rsa(RsaAttrs::new(2048, 17, 0))),
(Attestation, Rsa(RsaAttrs::new(3072, 17, 0))),
(Attestation, Rsa(RsaAttrs::new(4096, 17, 0))),
(Attestation, Ecc(EccAttrs::new(ECDSA, NistP256r1, None))),
(Attestation, Ecc(EccAttrs::new(ECDSA, NistP384r1, None))),
(Attestation, Ecc(EccAttrs::new(ECDSA, NistP521r1, None))),
(Attestation, Ecc(EccAttrs::new(ECDSA, Secp256k1, None))),
(
Attestation,
Ecc(EccAttrs::new(ECDSA, BrainpoolP256r1, None))
),
(
Attestation,
Ecc(EccAttrs::new(ECDSA, BrainpoolP384r1, None))
),
(
Attestation,
Ecc(EccAttrs::new(ECDSA, BrainpoolP512r1, None))
),
(Attestation, Ecc(EccAttrs::new(EdDSA, Ed25519, None))),
(Attestation, Ecc(EccAttrs::new(EdDSA, Cv25519, None)))
])
);
}
}