Skip to content

Commit 3270be7

Browse files
authored
yescrypt: warn for clippy::unwrap_used (#698)
Replaces usages of `unwrap` with `Error::Internal`
1 parent a6d3fef commit 3270be7

File tree

4 files changed

+58
-44
lines changed

4 files changed

+58
-44
lines changed

yescrypt/src/error.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Error type.
22
3-
use core::fmt;
3+
use core::{fmt, num::TryFromIntError};
44

55
/// Result type for the `yescrypt` crate with its [`Error`] type.
66
pub type Result<T> = core::result::Result<T, Error>;
@@ -16,6 +16,9 @@ pub enum Error {
1616
/// Encoding error (i.e. Base64)
1717
Encoding,
1818

19+
/// Internal error (bug in library)
20+
Internal,
21+
1922
/// Invalid params
2023
Params,
2124

@@ -28,13 +31,20 @@ impl fmt::Display for Error {
2831
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2932
match self {
3033
#[cfg(feature = "simple")]
31-
Error::Algorithm => f.write_str("password hash must begin with `$y$`"),
32-
Error::Encoding => f.write_str("yescrypt encoding invalid"),
33-
Error::Params => f.write_str("yescrypt params invalid"),
34+
Error::Algorithm => write!(f, "password hash must begin with `$y$`"),
35+
Error::Encoding => write!(f, "yescrypt encoding invalid"),
36+
Error::Internal => write!(f, "internal error"),
37+
Error::Params => write!(f, "yescrypt params invalid"),
3438
#[cfg(feature = "simple")]
35-
Error::Password => f.write_str("invalid password"),
39+
Error::Password => write!(f, "invalid password"),
3640
}
3741
}
3842
}
3943

4044
impl core::error::Error for Error {}
45+
46+
impl From<TryFromIntError> for Error {
47+
fn from(_: TryFromIntError) -> Self {
48+
Error::Internal
49+
}
50+
}

yescrypt/src/lib.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
clippy::implicit_saturating_sub,
1717
clippy::panic,
1818
clippy::panic_in_result_fn,
19+
clippy::unwrap_used,
1920
missing_docs,
2021
rust_2018_idioms,
2122
unused_lifetimes,
@@ -220,28 +221,26 @@ fn yescrypt_kdf_body(
220221

221222
let mut passwd = passwd;
222223
let mut sha256 = [0u8; 32];
224+
let key: &[u8] = if prehash {
225+
b"yescrypt-prehash"
226+
} else {
227+
b"yescrypt"
228+
};
223229
if !mode.is_classic() {
224-
sha256 = util::hmac_sha256(
225-
if prehash {
226-
b"yescrypt-prehash"
227-
} else {
228-
b"yescrypt"
229-
},
230-
passwd,
231-
);
230+
sha256 = util::hmac_sha256(key, passwd)?;
232231
passwd = &sha256;
233232
}
234233

235234
// 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen)
236-
pbkdf2::pbkdf2_hmac::<Sha256>(passwd, salt, 1, util::cast_slice_mut(&mut b));
235+
pbkdf2::pbkdf2_hmac::<Sha256>(passwd, salt, 1, util::cast_slice_mut(&mut b)?);
237236

238237
if !mode.is_classic() {
239-
sha256.copy_from_slice(util::cast_slice(&b[..8]));
238+
sha256.copy_from_slice(util::cast_slice(&b[..8])?);
240239
passwd = &sha256;
241240
}
242241

243242
if mode.is_rw() {
244-
smix::smix(&mut b, r, n, p, t, mode, &mut v, &mut xy, &mut sha256);
243+
smix::smix(&mut b, r, n, p, t, mode, &mut v, &mut xy, &mut sha256)?;
245244
passwd = &sha256;
246245
} else {
247246
// 2: for i = 0 to p - 1 do
@@ -257,17 +256,17 @@ fn yescrypt_kdf_body(
257256
&mut v,
258257
&mut xy,
259258
&mut [],
260-
);
259+
)?;
261260
}
262261
}
263262

264263
let mut dk = [0u8; 32];
265264
if !mode.is_classic() && out.len() < 32 {
266-
pbkdf2::pbkdf2_hmac::<Sha256>(passwd, util::cast_slice(&b), 1, &mut dk);
265+
pbkdf2::pbkdf2_hmac::<Sha256>(passwd, util::cast_slice(&b)?, 1, &mut dk);
267266
}
268267

269268
// 5: DK <-- PBKDF2(P, B, 1, dkLen)
270-
pbkdf2::pbkdf2_hmac::<Sha256>(passwd, util::cast_slice(&b), 1, out);
269+
pbkdf2::pbkdf2_hmac::<Sha256>(passwd, util::cast_slice(&b)?, 1, out);
271270

272271
// Except when computing classic scrypt, allow all computation so far
273272
// to be performed on the client. The final steps below match those of
@@ -282,7 +281,7 @@ fn yescrypt_kdf_body(
282281
};
283282

284283
// Compute ClientKey
285-
sha256 = util::hmac_sha256(&dkp[..32], b"Client Key");
284+
sha256 = util::hmac_sha256(&dkp[..32], b"Client Key")?;
286285

287286
// Compute StoredKey
288287
let clen = out.len().clamp(0, 32);

yescrypt/src/smix.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
33
#![allow(clippy::too_many_arguments)]
44

5-
use alloc::vec::Vec;
6-
75
use crate::{
8-
Mode,
6+
Error, Mode, Result,
97
pwxform::{PwxformCtx, SWORDS},
108
salsa20,
119
util::{cast_slice, hmac_sha256, slice_as_chunks_mut, xor},
1210
};
11+
use alloc::vec::Vec;
1312

1413
const SBYTES: u64 = crate::pwxform::SBYTES as u64;
1514

@@ -28,7 +27,7 @@ pub(crate) fn smix(
2827
v: &mut [u32],
2928
xy: &mut [u32],
3029
passwd: &mut [u8],
31-
) {
30+
) -> Result<()> {
3231
let r = r as usize;
3332
let s = 32 * r;
3433

@@ -100,7 +99,7 @@ pub(crate) fn smix(
10099

101100
// 17: if YESCRYPT_RW flag is set
102101
let mut ctx_i = if mode.is_rw() {
103-
let si = sn.next().unwrap();
102+
let si = sn.next().ok_or(Error::Internal)?;
104103

105104
// 18: SMix1_1(B_i, Sbytes / 128, S_i, no flags)
106105
smix1(
@@ -111,7 +110,7 @@ pub(crate) fn smix(
111110
&mut si[..],
112111
xy,
113112
&mut None,
114-
);
113+
)?;
115114

116115
let (s2, s10) = si.split_at_mut((1 << 8) * 4);
117116
let (s1, s0) = s10.split_at_mut((1 << 8) * 4);
@@ -134,7 +133,7 @@ pub(crate) fn smix(
134133
// 23: if i = 0
135134
if i == 0 {
136135
// 24: passwd <-- HMAC-SHA256(B_{0,2r-1}, passwd)
137-
let digest = hmac_sha256(cast_slice(&bs[(s - 16)..s]), &passwd[..32]);
136+
let digest = hmac_sha256(cast_slice(&bs[(s - 16)..s])?, &passwd[..32])?;
138137
passwd[..32].copy_from_slice(&digest);
139138
}
140139

@@ -145,7 +144,7 @@ pub(crate) fn smix(
145144
};
146145

147146
// 27: SMix1_r(B_i, n, V_{u..v}, flags)
148-
smix1(bs, r, np, mode, vp, xy, &mut ctx_i);
147+
smix1(bs, r, np, mode, vp, xy, &mut ctx_i)?;
149148

150149
// 28: SMix2_r(B_i, p2floor(n), Nloop_rw, V_{u..v}, flags)
151150
smix2(
@@ -157,7 +156,7 @@ pub(crate) fn smix(
157156
vp,
158157
xy,
159158
&mut ctx_i,
160-
);
159+
)?;
161160

162161
vchunk += nchunk;
163162
}
@@ -185,8 +184,10 @@ pub(crate) fn smix(
185184
v,
186185
xy,
187186
&mut ctx_i,
188-
);
187+
)?;
189188
}
189+
190+
Ok(())
190191
}
191192

192193
/// Compute first loop of `B = SMix_r(B, N)`.
@@ -201,7 +202,7 @@ fn smix1(
201202
v: &mut [u32],
202203
xy: &mut [u32],
203204
ctx: &mut Option<&mut PwxformCtx<'_>>,
204-
) {
205+
) -> Result<()> {
205206
let s = 32 * r;
206207
let (x, y) = xy.split_at_mut(s);
207208

@@ -218,7 +219,7 @@ fn smix1(
218219
v[i as usize * s..][..s].copy_from_slice(x);
219220
if mode.is_rw() && i > 1 {
220221
let n = prev_power_of_two(i);
221-
let j = usize::try_from((integerify(x, r) & (n - 1)) + (i - n)).unwrap();
222+
let j = usize::try_from((integerify(x, r) & (n - 1)) + (i - n))?;
222223
xor(x, &v[j * s..][..s]);
223224
}
224225

@@ -235,6 +236,8 @@ fn smix1(
235236
b[(k * 16) + ((i * 5) % 16)] = (x[k * 16 + i]).to_le();
236237
}
237238
}
239+
240+
Ok(())
238241
}
239242

240243
/// Compute second loop of `B = SMix_r(B, N)`.
@@ -251,7 +254,7 @@ fn smix2(
251254
v: &mut [u32],
252255
xy: &mut [u32],
253256
ctx: &mut Option<&mut PwxformCtx<'_>>,
254-
) {
257+
) -> Result<()> {
255258
let s = 32 * r;
256259
let (x, y) = xy.split_at_mut(s);
257260

@@ -265,7 +268,7 @@ fn smix2(
265268
// 6: for i = 0 to N - 1 do
266269
for _ in 0..nloop {
267270
// 7: j <-- Integerify(X) mod N
268-
let j = usize::try_from(integerify(x, r) & (n - 1)).unwrap();
271+
let j = usize::try_from(integerify(x, r) & (n - 1))?;
269272

270273
// 8.1: X <-- X xor V_j
271274
xor(x, &v[j * s..][..s]);
@@ -288,6 +291,8 @@ fn smix2(
288291
b[(k * 16) + ((i * 5) % 16)] = (x[k * 16 + i]).to_le();
289292
}
290293
}
294+
295+
Ok(())
291296
}
292297

293298
/// Return the result of parsing B_{2r-1} as a little-endian integer.

yescrypt/src/util.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// TODO(tarcieri): find safe replacements for unsafe code if possible
44
#![allow(unsafe_code)]
55

6+
use crate::{Error, Result};
67
use core::{ops::BitXorAssign, slice};
78
use sha2::Sha256;
89

@@ -16,33 +17,32 @@ where
1617
}
1718
}
1819

19-
pub(crate) fn cast_slice(input: &[u32]) -> &[u8] {
20+
pub(crate) fn cast_slice(input: &[u32]) -> Result<&[u8]> {
2021
let new_len = input
2122
.len()
2223
.checked_mul(size_of::<u32>() / size_of::<u8>())
23-
.unwrap();
24+
.ok_or(Error::Internal)?;
2425

2526
// SAFETY: `new_len` accounts for the size difference between the two types
26-
unsafe { slice::from_raw_parts(input.as_ptr().cast(), new_len) }
27+
Ok(unsafe { slice::from_raw_parts(input.as_ptr().cast(), new_len) })
2728
}
2829

29-
pub(crate) fn cast_slice_mut(input: &mut [u32]) -> &mut [u8] {
30+
pub(crate) fn cast_slice_mut(input: &mut [u32]) -> Result<&mut [u8]> {
3031
let new_len = input
3132
.len()
3233
.checked_mul(size_of::<u32>() / size_of::<u8>())
33-
.unwrap();
34+
.ok_or(Error::Internal)?;
3435

3536
// SAFETY: `new_len` accounts for the size difference between the two types
36-
unsafe { slice::from_raw_parts_mut(input.as_mut_ptr().cast(), new_len) }
37+
Ok(unsafe { slice::from_raw_parts_mut(input.as_mut_ptr().cast(), new_len) })
3738
}
3839

39-
pub(crate) fn hmac_sha256(key: &[u8], in_0: &[u8]) -> [u8; 32] {
40+
pub(crate) fn hmac_sha256(key: &[u8], in_0: &[u8]) -> Result<[u8; 32]> {
4041
use hmac::{KeyInit, Mac};
4142

42-
let mut hmac = hmac::Hmac::<Sha256>::new_from_slice(key)
43-
.expect("key length should always be valid with hmac");
43+
let mut hmac = hmac::Hmac::<Sha256>::new_from_slice(key).map_err(|_| Error::Internal)?;
4444
hmac.update(in_0);
45-
hmac.finalize().into_bytes().into()
45+
Ok(hmac.finalize().into_bytes().into())
4646
}
4747

4848
// TODO(tarcieri): use upstream `[T]::as_chunks_mut` when MSRV is 1.88

0 commit comments

Comments
 (0)