Skip to content

Commit 705bee7

Browse files
vkkoskieionut-arm
authored andcommitted
Make UtcTime conversion fallible
In the initial implementation, any parsing error was silently converted to None, which indicates the token doesn't have a clock. Signed-off-by: Keith Koskie <[email protected]>
1 parent 90c9a94 commit 705bee7

File tree

4 files changed

+43
-25
lines changed

4 files changed

+43
-25
lines changed

cryptoki/src/context/slot_token_management.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::label_from_str;
88
use crate::mechanism::{MechanismInfo, MechanismType};
99
use crate::slot::{Slot, SlotInfo, TokenInfo};
1010
use cryptoki_sys::{CK_BBOOL, CK_MECHANISM_INFO, CK_SLOT_INFO, CK_TOKEN_INFO};
11-
use std::convert::TryInto;
11+
use std::convert::{TryFrom, TryInto};
1212

1313
use crate::error::RvError::BufferTooSmall;
1414

@@ -102,7 +102,7 @@ pub(super) fn get_token_info(ctx: &Pkcs11, slot: Slot) -> Result<TokenInfo> {
102102
&mut token_info,
103103
))
104104
.into_result()?;
105-
Ok(TokenInfo::from(token_info))
105+
TokenInfo::try_from(token_info)
106106
}
107107
}
108108

cryptoki/src/error/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ pub enum Error {
2929
/// Error when converting a slice to an array
3030
TryFromSlice(std::array::TryFromSliceError),
3131

32+
/// Error when converting a numerical str to an integral value
33+
ParseInt(core::num::ParseIntError),
34+
35+
/// Error converting into a type assuming valid UTF-8
36+
Utf8(std::str::Utf8Error),
37+
3238
/// Error with nul characters in Strings
3339
NulError(std::ffi::NulError),
3440

@@ -50,6 +56,8 @@ impl fmt::Display for Error {
5056
Error::NotSupported => write!(f, "Feature not supported"),
5157
Error::TryFromInt(e) => write!(f, "Conversion between integers failed ({})", e),
5258
Error::TryFromSlice(e) => write!(f, "Error converting slice to array ({})", e),
59+
Error::ParseInt(e) => write!(f, "Error parsing string as integer ({})", e),
60+
Error::Utf8(e) => write!(f, "Invalid UTF-8 ({})", e),
5361
Error::NulError(e) => write!(f, "An interior nul byte was found ({})", e),
5462
Error::NullFunctionPointer => write!(f, "Calling a NULL function pointer"),
5563
Error::InvalidValue => write!(f, "The value is not one of the expected options"),
@@ -64,6 +72,8 @@ impl std::error::Error for Error {
6472
Error::LibraryLoading(e) => Some(e),
6573
Error::TryFromInt(e) => Some(e),
6674
Error::TryFromSlice(e) => Some(e),
75+
Error::ParseInt(e) => Some(e),
76+
Error::Utf8(e) => Some(e),
6777
Error::NulError(e) => Some(e),
6878
Error::Pkcs11(_)
6979
| Error::NotSupported
@@ -92,6 +102,18 @@ impl From<std::array::TryFromSliceError> for Error {
92102
}
93103
}
94104

105+
impl From<core::num::ParseIntError> for Error {
106+
fn from(err: core::num::ParseIntError) -> Error {
107+
Error::ParseInt(err)
108+
}
109+
}
110+
111+
impl From<std::str::Utf8Error> for Error {
112+
fn from(err: std::str::Utf8Error) -> Error {
113+
Error::Utf8(err)
114+
}
115+
}
116+
95117
impl From<std::ffi::NulError> for Error {
96118
fn from(err: std::ffi::NulError) -> Error {
97119
Error::NulError(err)

cryptoki/src/slot/token_info.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
// SPDX-License-Identifier: Apache-2.0
33
//! PKCS11 Token info and associated flags
44
5+
use crate::error::{Error, Result};
56
use crate::flag::{CkFlags, FlagBit};
67
use crate::string_from_blank_padded;
78
use crate::types::{convert_utc_time, maybe_unlimited};
89
use crate::types::{MaybeUnavailable, UtcTime, Version};
910
use cryptoki_sys::*;
11+
use std::convert::TryFrom;
1012
use std::fmt::{self, Debug, Formatter};
1113

1214
const RNG: FlagBit<TokenInfo> = FlagBit::new(CKF_RNG);
@@ -411,15 +413,16 @@ impl TokenInfo {
411413
}
412414

413415
#[doc(hidden)]
414-
impl From<CK_TOKEN_INFO> for TokenInfo {
415-
fn from(val: CK_TOKEN_INFO) -> Self {
416+
impl TryFrom<CK_TOKEN_INFO> for TokenInfo {
417+
type Error = Error;
418+
fn try_from(val: CK_TOKEN_INFO) -> Result<Self> {
416419
let flags = CkFlags::from(val.flags);
417420
let utc_time = if flags.contains(CLOCK_ON_TOKEN) {
418-
convert_utc_time(val.utcTime)
421+
convert_utc_time(val.utcTime)?
419422
} else {
420423
None
421424
};
422-
Self {
425+
Ok(Self {
423426
label: string_from_blank_padded(&val.label),
424427
manufacturer_id: string_from_blank_padded(&val.manufacturerID),
425428
model: string_from_blank_padded(&val.model),
@@ -438,7 +441,7 @@ impl From<CK_TOKEN_INFO> for TokenInfo {
438441
hardware_version: val.hardwareVersion.into(),
439442
firmware_version: val.firmwareVersion.into(),
440443
utc_time,
441-
}
444+
})
442445
}
443446
}
444447

cryptoki/src/types.rs

+11-18
Original file line numberDiff line numberDiff line change
@@ -289,24 +289,17 @@ impl fmt::Display for UtcTime {
289289
}
290290

291291
// UTC time has the format YYYYMMDDhhmmss00 as ASCII digits
292-
pub(crate) fn convert_utc_time(orig: [u8; 16]) -> Option<UtcTime> {
293-
// skip check of reserved padding chars
294-
for c in orig[0..14].iter() {
295-
if !c.is_ascii_digit() {
296-
return None;
297-
}
298-
}
292+
pub(crate) fn convert_utc_time(orig: [u8; 16]) -> Result<Option<UtcTime>> {
299293
// Note: No validaiton of these values beyond being ASCII digits
300294
// because PKCS#11 doesn't impose any such restrictions.
301-
// Unwraps are safe here because of the digit check above.
302-
Some(UtcTime {
303-
year: std::str::from_utf8(&orig[0..4]).unwrap().parse().unwrap(),
304-
month: std::str::from_utf8(&orig[4..6]).unwrap().parse().unwrap(),
305-
day: std::str::from_utf8(&orig[6..8]).unwrap().parse().unwrap(),
306-
hour: std::str::from_utf8(&orig[8..10]).unwrap().parse().unwrap(),
307-
minute: std::str::from_utf8(&orig[10..12]).unwrap().parse().unwrap(),
308-
second: std::str::from_utf8(&orig[12..14]).unwrap().parse().unwrap(),
309-
})
295+
Ok(Some(UtcTime {
296+
year: std::str::from_utf8(&orig[0..4])?.parse()?,
297+
month: std::str::from_utf8(&orig[4..6])?.parse()?,
298+
day: std::str::from_utf8(&orig[6..8])?.parse()?,
299+
hour: std::str::from_utf8(&orig[8..10])?.parse()?,
300+
minute: std::str::from_utf8(&orig[10..12])?.parse()?,
301+
second: std::str::from_utf8(&orig[12..14])?.parse()?,
302+
}))
310303
}
311304

312305
#[cfg(test)]
@@ -328,7 +321,7 @@ mod test {
328321
0x31, 0x39, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
329322
0x30, 0x30,
330323
];
331-
let valid = convert_utc_time(valid).unwrap();
324+
let valid = convert_utc_time(valid).unwrap().unwrap();
332325
assert_eq!(valid.year, UTC_TIME.year);
333326
assert_eq!(valid.month, UTC_TIME.month);
334327
assert_eq!(valid.day, UTC_TIME.day);
@@ -344,7 +337,7 @@ mod test {
344337
0x30, 0x30,
345338
];
346339
let invalid = convert_utc_time(invalid);
347-
assert!(invalid.is_none());
340+
assert!(invalid.is_err());
348341
}
349342

350343
#[test]

0 commit comments

Comments
 (0)