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
use yubikey_piv::key::{AlgorithmId, SlotId};
use yubikey_piv::certificate::PublicKeyInfo;
use crate::yubikey::management::{fetch_pubkey, sign_data};
use crate::ssh::{
Curve,
CurveKind,
EcdsaPublicKey,
KeyType,
PublicKey,
PublicKeyKind,
};
use crate::utils::signature_convert_asn1_ecdsa_to_ssh;
pub fn convert_to_ssh_pubkey(pki: &PublicKeyInfo) -> Option<PublicKey> {
match pki {
PublicKeyInfo::EcP256(pubkey) => {
let key_type = KeyType::from_name("ecdsa-sha2-nistp256").unwrap();
let curve = Curve::from_identifier("nistp256").unwrap();
let kind = EcdsaPublicKey {
curve,
key: pubkey.as_bytes().to_vec(),
};
Some(PublicKey {
key_type,
kind: PublicKeyKind::Ecdsa(kind),
comment: None,
})
},
PublicKeyInfo::EcP384(pubkey) => {
let key_type = KeyType::from_name("ecdsa-sha2-nistp384").unwrap();
let curve = Curve::from_identifier("nistp384").unwrap();
let kind = EcdsaPublicKey {
curve,
key: pubkey.as_bytes().to_vec(),
};
Some(PublicKey {
key_type,
kind: PublicKeyKind::Ecdsa(kind),
comment: None,
})
}
_ => None,
}
}
pub fn ssh_cert_fetch_pubkey(slot: SlotId) -> Option<PublicKey> {
match fetch_pubkey(slot) {
Ok(pki) => convert_to_ssh_pubkey(&pki),
_ => None,
}
}
pub fn ssh_cert_signer(buf: &[u8], slot: SlotId) -> Option<Vec<u8>> {
let pubkey = match ssh_cert_fetch_pubkey(slot) {
None => return None,
Some(pk) => pk,
};
let (alg, sig_type) = match pubkey.kind {
PublicKeyKind::Ecdsa(x) => {
match x.curve.kind {
CurveKind::Nistp256 => (AlgorithmId::EccP256, "ecdsa-sha2-nistp256"),
CurveKind::Nistp384 => (AlgorithmId::EccP384, "ecdsa-sha2-nistp384"),
CurveKind::Nistp521 => return None,
}
},
PublicKeyKind::Rsa(_) => return None,
PublicKeyKind::Ed25519(_) => return None,
};
match sign_data(&buf, alg, slot) {
Ok(signature) => {
let mut encoded: Vec<u8> = (sig_type.len() as u32).to_be_bytes().to_vec();
encoded.extend_from_slice(sig_type.as_bytes());
let sig_encoding = match signature_convert_asn1_ecdsa_to_ssh(&signature) {
Some(se) => se,
None => return None,
};
encoded.extend(sig_encoding);
Some(encoded)
},
Err(e) => {
error!("SSH Cert Signer Error: {:?}", e);
None
},
}
}