Skip to content

Commit 2992420

Browse files
committed
Extend Pkcs11Uri to surface object, id, and type attributes
Adds three optional fields to `Pkcs11Uri` so callers can locate specific objects on a token by the standard RFC 7512 query attributes: * `object` - percent-decoded label (cert/key) * `id` - percent-decoded raw CKA_ID bytes * `type` - object-type discriminator (public, private, cert, secret-key, data) The existing `token`-only parse path is preserved; unknown attributes continue to be ignored. Two new tests cover the extended parse and the back-compat empty case.
1 parent 74e8c74 commit 2992420

1 file changed

Lines changed: 49 additions & 5 deletions

File tree

src/pk11_utils.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ use crate::err::{Error, Res};
99
#[derive(Debug, Clone, PartialEq, Eq)]
1010
pub struct Pkcs11Uri {
1111
pub token: Option<String>,
12+
/// `object=` attribute. For RSA / asymmetric uses this is typically a
13+
/// certificate label; for symmetric uses it's a key label.
14+
pub object: Option<String>,
15+
/// `id=` attribute (percent-decoded raw bytes). Identifies an object
16+
/// by PKCS#11 CKA_ID rather than label.
17+
pub id: Option<Vec<u8>>,
18+
/// `type=` attribute: `public`, `private`, `cert`, `secret-key`, or
19+
/// `data`. Callers use this to pick the right NSS lookup (e.g.
20+
/// `find_cert_by_nickname` vs `find_key_by_nickname`).
21+
pub object_type: Option<String>,
1222
}
1323

1424
fn percent_decode(s: &str) -> String {
@@ -53,15 +63,27 @@ pub fn parse(uri: &str) -> Res<Pkcs11Uri> {
5363
let path = uri.strip_prefix("pkcs11:").ok_or(Error::InvalidInput)?;
5464

5565
let mut token = None;
66+
let mut object = None;
67+
let mut id = None;
68+
let mut object_type = None;
5669
for attr in path.split(';') {
57-
if let Some((key, value)) = attr.split_once('=')
58-
&& key == "token"
59-
{
60-
token = Some(percent_decode(value));
70+
if let Some((key, value)) = attr.split_once('=') {
71+
match key {
72+
"token" => token = Some(percent_decode(value)),
73+
"object" => object = Some(percent_decode(value)),
74+
"id" => id = Some(percent_decode(value).into_bytes()),
75+
"type" => object_type = Some(percent_decode(value)),
76+
_ => {}
77+
}
6178
}
6279
}
6380

64-
Ok(Pkcs11Uri { token })
81+
Ok(Pkcs11Uri {
82+
token,
83+
object,
84+
id,
85+
object_type,
86+
})
6587
}
6688

6789
/// Build a PKCS#11 URI from a token name.
@@ -120,4 +142,26 @@ mod tests {
120142
let parsed = parse(&uri_str).unwrap();
121143
assert_eq!(parsed.token.as_deref(), Some(name));
122144
}
145+
146+
#[test]
147+
fn parse_object_id_type() {
148+
fixture_init();
149+
let uri = parse(
150+
"pkcs11:token=YubiKey%20PIV;object=Key%20Management;id=%03;type=public",
151+
)
152+
.unwrap();
153+
assert_eq!(uri.token.as_deref(), Some("YubiKey PIV"));
154+
assert_eq!(uri.object.as_deref(), Some("Key Management"));
155+
assert_eq!(uri.id, Some(b"\x03".to_vec()));
156+
assert_eq!(uri.object_type.as_deref(), Some("public"));
157+
}
158+
159+
#[test]
160+
fn parse_no_extra_attrs() {
161+
fixture_init();
162+
let uri = parse("pkcs11:token=NSS%20Certificate%20DB").unwrap();
163+
assert_eq!(uri.object, None);
164+
assert_eq!(uri.id, None);
165+
assert_eq!(uri.object_type, None);
166+
}
123167
}

0 commit comments

Comments
 (0)