Skip to content

Commit e73f490

Browse files
authored
Merge pull request #23 from josephlr/format
Cleanup payload formatting to avoid allocation
2 parents fcceeb8 + 1753cf3 commit e73f490

File tree

8 files changed

+79
-116
lines changed

8 files changed

+79
-116
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ members = ["libkeyutils-sys"]
1616
[dependencies]
1717
bitflags = "1.0.4"
1818
errno = "0.2"
19-
itertools = "0.8"
2019
libkeyutils-sys = { path = "libkeyutils-sys" }
2120
log = "0.4.4"
2221

src/keytypes/blacklist.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
2929
use std::borrow::Cow;
3030

31-
use super::AsciiHex;
31+
use super::ByteBuf;
3232
use crate::keytype::*;
3333

3434
/// Blacklist hashes.
@@ -81,10 +81,6 @@ pub struct Description {
8181

8282
impl KeyDescription for Description {
8383
fn description(&self) -> Cow<str> {
84-
Cow::Owned(format!(
85-
"{}:{}",
86-
self.hash_type.name(),
87-
AsciiHex::convert(&self.hash),
88-
))
84+
format!("{}:{:x}", self.hash_type.name(), ByteBuf(&self.hash)).into()
8985
}
9086
}

src/keytypes/dns_resolver.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ pub enum QueryType {
5959
impl QueryType {
6060
/// The name of the DNS record.
6161
fn name(&self) -> &str {
62-
match *self {
62+
match self {
6363
QueryType::A => "a",
6464
QueryType::AAAA => "aaaa",
6565
QueryType::AFSDB => "afsdb",
66-
QueryType::Other(ref s) => s,
66+
QueryType::Other(s) => s,
6767
}
6868
}
6969
}
@@ -87,10 +87,9 @@ pub struct Description {
8787

8888
impl KeyDescription for Description {
8989
fn description(&self) -> Cow<str> {
90-
if let Some(ref query_type) = self.query_type {
91-
Cow::Owned(format!("{}:{}", query_type.name(), self.name))
92-
} else {
93-
self.name.clone()
90+
match &self.query_type {
91+
Some(ref query_type) => format!("{}:{}", query_type.name(), self.name).into(),
92+
_ => self.name.clone(),
9493
}
9594
}
9695
}

src/keytypes/encrypted.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
2929
use std::borrow::Cow;
3030

31-
use super::AsciiHex;
31+
use super::ByteBuf;
3232
use crate::keytype::*;
3333

3434
/// Encrypted keys.
@@ -96,7 +96,7 @@ pub enum MasterKeyType {
9696
impl MasterKeyType {
9797
/// The name of the master key type.
9898
fn name(&self) -> &str {
99-
match *self {
99+
match self {
100100
MasterKeyType::Trusted => "trusted",
101101
MasterKeyType::User => "user",
102102
}
@@ -142,12 +142,12 @@ pub enum Payload {
142142

143143
impl KeyPayload for Payload {
144144
fn payload(&self) -> Cow<[u8]> {
145-
let payload = match *self {
145+
match self {
146146
Payload::New {
147-
ref format,
148-
ref keytype,
149-
ref description,
150-
ref keylen,
147+
format,
148+
keytype,
149+
description,
150+
keylen,
151151
} => {
152152
format!(
153153
"new {} {}:{} {}",
@@ -158,14 +158,14 @@ impl KeyPayload for Payload {
158158
)
159159
},
160160
Payload::Load {
161-
ref blob,
162-
} => format!("load {}", AsciiHex::convert(&blob)),
161+
blob,
162+
} => format!("load {:x}", ByteBuf(&blob)),
163163
Payload::Update {
164-
ref keytype,
165-
ref description,
164+
keytype,
165+
description,
166166
} => format!("update {}:{}", keytype.name(), description),
167-
};
168-
169-
payload.bytes().collect()
167+
}
168+
.into_bytes()
169+
.into()
170170
}
171171
}

src/keytypes/mod.rs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
//! The Linux kernel supports many types of keys. They may be compiled out or available as
3030
//! modules. The types provided here try to make it easier to use these keys.
3131
32-
use std::char;
32+
use std::fmt;
3333

3434
pub mod asymmetric;
3535
pub use self::asymmetric::Asymmetric;
@@ -64,36 +64,24 @@ pub use self::trusted::Trusted;
6464
pub mod user;
6565
pub use self::user::User;
6666

67-
/// A structure for assisting in coverting binary data into hexadecimal.
68-
///
69-
/// Many key types take in ASCII hexadecimal input instead of raw binary.
70-
pub struct AsciiHex;
67+
/// A structure for assisting in display binary data.
68+
struct ByteBuf<'a>(&'a [u8]);
7169

72-
/// The mask for a nibble.
73-
const NIBBLE_MASK: u8 = 0x0f;
74-
75-
impl AsciiHex {
76-
/// Convert binary data into an ASCII hexadecimal string.
77-
pub fn convert(data: &[u8]) -> String {
78-
data.iter()
79-
.fold(String::with_capacity(data.len() * 2), |mut string, byte| {
80-
let hi = (byte >> 4) & NIBBLE_MASK;
81-
let lo = byte & NIBBLE_MASK;
82-
83-
string.push(char::from_digit(u32::from(hi), 16).unwrap());
84-
string.push(char::from_digit(u32::from(lo), 16).unwrap());
85-
86-
string
87-
})
70+
impl fmt::LowerHex for ByteBuf<'_> {
71+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72+
for byte in self.0 {
73+
write!(f, "{:02x}", byte)?;
74+
}
75+
Ok(())
8876
}
8977
}
9078

9179
#[cfg(test)]
9280
mod tests {
93-
use super::*;
81+
use super::ByteBuf;
9482

9583
fn check(input: &[u8], expected: &str) {
96-
assert_eq!(AsciiHex::convert(input), expected);
84+
assert_eq!(format!("{:x}", ByteBuf(input)), expected);
9785
}
9886

9987
#[test]

src/keytypes/rxrpc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,6 @@ impl KeyPayload for Payload {
7575
payload.extend(self.session_key.iter());
7676
payload.extend(self.ticket.iter());
7777

78-
Cow::Owned(payload)
78+
payload.into()
7979
}
8080
}

src/keytypes/rxrpc_s.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub struct Description {
5454

5555
impl KeyDescription for Description {
5656
fn description(&self) -> Cow<str> {
57-
Cow::Owned(format!("{}:{}", self.service_id, self.security_index))
57+
format!("{}:{}", self.service_id, self.security_index).into()
5858
}
5959
}
6060

src/keytypes/trusted.rs

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@
2727
//! Trusted keys
2828
2929
use std::borrow::Cow;
30+
use std::fmt;
3031

31-
use itertools::Itertools;
32-
33-
use super::AsciiHex;
32+
use super::ByteBuf;
3433
use crate::keytype::*;
3534

3635
/// Trusted keys are rooted in the TPM.
@@ -111,71 +110,55 @@ pub struct TrustedOptions {
111110
pub policyhandle: Option<u32>,
112111
}
113112

114-
impl TrustedOptions {
115-
fn payload_string(&self) -> String {
116-
let parts = [
113+
impl fmt::Display for TrustedOptions {
114+
/// Formats the options that are present. Starts with a leading space.
115+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116+
if let Some(keyhandle) = self.keyhandle {
117117
// keyhandle= ascii hex value of sealing key; default 40000000 (SRK)
118-
(
119-
"keyhandle",
120-
self.keyhandle
121-
.as_ref()
122-
.map(|v| AsciiHex::convert(&v.to_be().to_be_bytes())),
123-
),
118+
write!(f, " keyhandle={:x}", keyhandle)?;
119+
}
120+
if let Some(keyauth) = self.keyauth.as_ref() {
124121
// keyauth= ascii hex auth for sealing key; default 00...
125122
// (40 ascii zeros)
126-
(
127-
"keyauth",
128-
self.keyauth.as_ref().map(|v| AsciiHex::convert(v)),
129-
),
123+
write!(f, " keyauth={:x}", ByteBuf(keyauth))?;
124+
}
125+
if let Some(blobauth) = self.blobauth.as_ref() {
130126
// blobauth= ascii hex auth for sealed data; default 00...
131127
// (40 ascii zeros)
132-
(
133-
"blobauth",
134-
self.blobauth.as_ref().map(|v| AsciiHex::convert(v)),
135-
),
128+
write!(f, " blobauth={:x}", ByteBuf(blobauth))?;
129+
}
130+
if let Some(pcrinfo) = self.pcrinfo.as_ref() {
136131
// pcrinfo= ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
137-
(
138-
"pcrinfo",
139-
self.pcrinfo.as_ref().map(|v| AsciiHex::convert(&v)),
140-
),
132+
write!(f, " pcrinfo={:x}", ByteBuf(pcrinfo))?;
133+
}
134+
if let Some(pcrlock) = self.pcrlock {
141135
// pcrlock= pcr number to be extended to "lock" blob
142-
("pcrlock", self.pcrlock.as_ref().map(|v| format!("{}", v))),
136+
write!(f, " pcrlock={}", pcrlock)?;
137+
}
138+
if let Some(migratable) = self.migratable {
143139
// migratable= 0|1 indicating permission to reseal to new PCR values,
144140
// default 1 (resealing allowed)
145-
(
146-
"migratable",
147-
self.migratable
148-
.as_ref()
149-
.map(|&v| if v { "1" } else { "0" }.to_string()),
150-
),
141+
write!(f, " migratable={}", migratable as u8)?;
142+
}
143+
if let Some(hash) = self.hash {
151144
// hash= hash algorithm name as a string. For TPM 1.x the only
152145
// allowed value is sha1. For TPM 2.x the allowed values
153146
// are sha1, sha256, sha384, sha512 and sm3-256.
154-
("hash", self.hash.as_ref().map(|v| v.name().to_string())),
147+
write!(f, " hash={}", hash.name())?;
148+
}
149+
if let Some(policydigest) = self.policydigest.as_ref() {
155150
// policydigest= digest for the authorization policy. must be calculated
156151
// with the same hash algorithm as specified by the 'hash='
157152
// option.
158-
(
159-
"policydigest",
160-
self.policydigest.as_ref().map(|v| AsciiHex::convert(&v)),
161-
),
153+
write!(f, " policydigest={:x}", ByteBuf(policydigest))?;
154+
}
155+
if let Some(policyhandle) = self.policyhandle {
162156
// policyhandle= handle to an authorization policy session that defines the
163157
// same policy and with the same hash algorithm as was used to
164158
// seal the key.
165-
(
166-
"policyhandle",
167-
self.policyhandle
168-
.as_ref()
169-
.map(|v| AsciiHex::convert(&v.to_be().to_be_bytes())),
170-
),
171-
];
172-
173-
let options = parts
174-
.iter()
175-
.filter_map(|(key, value)| value.as_ref().map(|value| format!("{}={}", key, value)))
176-
.format(" ");
177-
178-
format!("{}", options)
159+
write!(f, " policyhandle={:x}", policyhandle)?;
160+
}
161+
Ok(())
179162
}
180163
}
181164

@@ -211,22 +194,20 @@ pub enum Payload {
211194

212195
impl KeyPayload for Payload {
213196
fn payload(&self) -> Cow<[u8]> {
214-
let (command, blob, options) = match *self {
197+
match self {
215198
Payload::New {
216-
ref keylen,
217-
ref options,
218-
} => ("new", format!("{}", keylen), options),
199+
keylen,
200+
options,
201+
} => format!("new {}{}", keylen, options),
219202
Payload::Load {
220-
ref blob,
221-
ref options,
222-
} => ("load", AsciiHex::convert(&blob), options),
203+
blob,
204+
options,
205+
} => format!("load {:x}{}", ByteBuf(blob), options),
223206
Payload::Update {
224-
ref options,
225-
} => ("update", String::new(), options),
226-
};
227-
228-
format!("{} {} {}", command, blob, options.payload_string())
229-
.bytes()
230-
.collect()
207+
options,
208+
} => format!("update{}", options),
209+
}
210+
.into_bytes()
211+
.into()
231212
}
232213
}

0 commit comments

Comments
 (0)