Skip to content

Commit c631005

Browse files
committed
wip: no-std
1 parent 2feb46f commit c631005

File tree

6 files changed

+43
-71
lines changed

6 files changed

+43
-71
lines changed

md5-crypt/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ md-5 = { version = "0.10.5", default-features = false }
2525

2626
[features]
2727
default = ["simple"]
28-
simple = ["rand", "std", "subtle"]
29-
std = []
28+
alloc = []
29+
simple = ["alloc", "rand", "subtle"]
3030

3131
[package.metadata.docs.rs]
3232
all-features = true

md5-crypt/src/b64.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,32 @@
11
//! Base64 encoding support
22
33
use crate::defs::{BLOCK_SIZE, MAP_MD5, PW_SIZE_MD5};
4-
use alloc::vec::Vec;
5-
use base64ct::{Base64ShaCrypt, Encoding};
6-
7-
#[cfg(feature = "simple")]
4+
#[cfg(any(feature = "subtle", test))]
85
use crate::errors::DecodeError;
6+
use base64ct::{Base64ShaCrypt, Encoding};
97

10-
pub fn encode_md5(source: &[u8]) -> Vec<u8> {
8+
pub fn encode_md5(source: &[u8]) -> [u8; PW_SIZE_MD5] {
119
let mut transposed = [0u8; BLOCK_SIZE];
1210
for (i, &ti) in MAP_MD5.iter().enumerate() {
1311
transposed[i] = source[ti as usize];
1412
}
1513
let mut buf = [0u8; PW_SIZE_MD5];
1614
Base64ShaCrypt::encode(&transposed, &mut buf).unwrap();
17-
buf.to_vec()
15+
buf
1816
}
1917

20-
#[cfg(feature = "simple")]
21-
pub fn decode_md5(source: &[u8]) -> Result<Vec<u8>, DecodeError> {
18+
#[cfg(any(feature = "subtle", test))]
19+
pub fn decode_md5(source: &[u8]) -> Result<[u8; BLOCK_SIZE], DecodeError> {
2220
let mut buf = [0u8; PW_SIZE_MD5];
2321
Base64ShaCrypt::decode(source, &mut buf).map_err(|_| DecodeError)?;
24-
2522
let mut transposed = [0u8; BLOCK_SIZE];
2623
for (i, &ti) in MAP_MD5.iter().enumerate() {
2724
transposed[ti as usize] = buf[i];
2825
}
29-
Ok(transposed.to_vec())
26+
Ok(transposed)
3027
}
3128

3229
mod tests {
33-
#[cfg(feature = "simple")]
3430
#[test]
3531
fn test_encode_decode_md5() {
3632
let original: [u8; 16] = [

md5-crypt/src/defs.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ pub const BLOCK_SIZE: usize = 16;
55
pub const PW_SIZE_MD5: usize = 22;
66

77
/// Maximum length of a salt
8-
#[cfg(feature = "simple")]
98
pub const SALT_MAX_LEN: usize = 8;
109

1110
/// Encoding table.

md5-crypt/src/errors.rs

+7-24
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,42 @@
11
//! Error types.
22
3+
#[cfg(feature = "alloc")]
34
use alloc::string;
45

5-
#[cfg(feature = "simple")]
6-
use alloc::string::String;
7-
8-
#[cfg(feature = "std")]
9-
use std::io;
10-
116
/// Error type.
127
#[derive(Debug)]
138
pub enum CryptError {
149
/// RNG failed.
1510
RandomError,
1611

17-
/// I/O error.
18-
#[cfg(feature = "std")]
19-
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
20-
IoError(io::Error),
21-
2212
/// UTF-8 error.
13+
#[cfg(feature = "alloc")]
2314
StringError(string::FromUtf8Error),
2415
}
2516

26-
#[cfg(feature = "std")]
27-
impl From<io::Error> for CryptError {
28-
fn from(e: io::Error) -> Self {
29-
CryptError::IoError(e)
30-
}
31-
}
32-
17+
#[cfg(feature = "alloc")]
3318
impl From<string::FromUtf8Error> for CryptError {
3419
fn from(e: string::FromUtf8Error) -> Self {
3520
CryptError::StringError(e)
3621
}
3722
}
3823

39-
#[cfg(feature = "simple")]
40-
#[cfg_attr(docsrs, doc(cfg(feature = "simple")))]
4124
#[derive(Debug)]
4225
pub enum CheckError {
43-
InvalidFormat(String),
26+
InvalidFormat(&'static str),
27+
#[cfg(feature = "subtle")]
4428
Crypt(CryptError),
29+
#[cfg(feature = "subtle")]
4530
HashMismatch,
4631
}
4732

4833
/// Decoding errors.
49-
#[cfg(feature = "simple")]
5034
#[cfg_attr(docsrs, doc(cfg(feature = "simple")))]
5135
#[derive(Debug)]
5236
pub struct DecodeError;
5337

54-
#[cfg(feature = "simple")]
5538
impl From<DecodeError> for CheckError {
5639
fn from(_: DecodeError) -> CheckError {
57-
CheckError::InvalidFormat("invalid B64".into())
40+
CheckError::InvalidFormat("invalid B64")
5841
}
5942
}

md5-crypt/src/lib.rs

+23-32
Original file line numberDiff line numberDiff line change
@@ -33,34 +33,31 @@
3333
#![warn(missing_docs, rust_2018_idioms)]
3434

3535
// TODO(tarcieri): heapless support
36-
#[macro_use]
36+
#[cfg(feature = "alloc")]
3737
extern crate alloc;
3838

39-
#[cfg(feature = "std")]
40-
extern crate std;
41-
4239
mod b64;
4340
mod defs;
4441
mod errors;
4542

46-
pub use crate::{defs::BLOCK_SIZE, errors::CryptError};
43+
pub use crate::{
44+
defs::{BLOCK_SIZE, PW_SIZE_MD5, SALT_MAX_LEN},
45+
errors::CryptError,
46+
};
4747

48-
use alloc::string::String;
4948
use md5::{Digest, Md5};
5049

50+
#[cfg(feature = "subtle")]
51+
use crate::errors::CheckError;
52+
5153
#[cfg(feature = "simple")]
5254
use {
53-
crate::{
54-
defs::{SALT_MAX_LEN, TAB},
55-
errors::CheckError,
56-
},
57-
alloc::string::ToString,
55+
crate::defs::TAB,
56+
alloc::string::String,
5857
rand::{distributions::Distribution, thread_rng, Rng},
5958
};
6059

61-
#[cfg(feature = "simple")]
6260
static MD5_SALT_PREFIX: &str = "$1$";
63-
#[cfg(feature = "simple")]
6461

6562
/// The MD5 crypt function returned as byte vector
6663
///
@@ -160,10 +157,9 @@ pub fn md5_crypt(password: &[u8], salt: &[u8]) -> Result<[u8; BLOCK_SIZE], Crypt
160157
/// # Returns
161158
/// - `Ok(())` if calculation was successful
162159
/// - `Err(errors::CryptError)` otherwise
163-
pub fn md5_crypt_b64(password: &[u8], salt: &[u8]) -> Result<String, CryptError> {
160+
pub fn md5_crypt_b64(password: &[u8], salt: &[u8]) -> Result<[u8; PW_SIZE_MD5], CryptError> {
164161
let output = md5_crypt(password, salt)?;
165-
let r = String::from_utf8(b64::encode_md5(&output))?;
166-
Ok(r)
162+
Ok(b64::encode_md5(&output))
167163
}
168164

169165
/// Simple interface for generating a MD5 password hash.
@@ -191,7 +187,7 @@ pub fn md5_simple(password: &str) -> Result<String, CryptError> {
191187
result.push_str(MD5_SALT_PREFIX);
192188
result.push_str(&salt);
193189
result.push('$');
194-
let s = String::from_utf8(b64::encode_md5(&out))?;
190+
let s = String::from_utf8(b64::encode_md5(&out).to_vec())?;
195191
result.push_str(&s);
196192
Ok(result)
197193
}
@@ -206,40 +202,35 @@ pub fn md5_simple(password: &str) -> Result<String, CryptError> {
206202
/// # Return
207203
/// `OK(())` if password matches otherwise Err(CheckError) in case of invalid
208204
/// format or password mismatch.
209-
#[cfg(feature = "simple")]
205+
#[cfg(feature = "subtle")]
210206
#[cfg_attr(docsrs, doc(cfg(feature = "simple")))]
211207
pub fn md5_check(password: &str, hashed_value: &str) -> Result<(), CheckError> {
212208
let mut iter = hashed_value.split('$');
213209

214210
// Check that there are no characters before the first "$"
215211
if iter.next() != Some("") {
216-
return Err(CheckError::InvalidFormat(
217-
"Should start with '$".to_string(),
218-
));
212+
return Err(CheckError::InvalidFormat("Should start with '$"));
219213
}
220214

221215
if iter.next() != Some("1") {
222-
return Err(CheckError::InvalidFormat(format!(
223-
"does not contain MD5 identifier: '{}'",
224-
MD5_SALT_PREFIX
225-
)));
216+
return Err(CheckError::InvalidFormat(
217+
"does not contain MD5 identifier: '$1$'",
218+
));
226219
}
227220

228-
let next = iter.next().ok_or_else(|| {
229-
CheckError::InvalidFormat("Does not contain a salt or hash string".to_string())
230-
})?;
221+
let next = iter.next().ok_or(CheckError::InvalidFormat(
222+
"Does not contain a salt or hash string",
223+
))?;
231224

232225
let salt = next;
233226

234227
let hash = iter
235228
.next()
236-
.ok_or_else(|| CheckError::InvalidFormat("Does not contain a hash string".to_string()))?;
229+
.ok_or(CheckError::InvalidFormat("Does not contain a hash string"))?;
237230

238231
// Make sure there is no trailing data after the final "$"
239232
if iter.next().is_some() {
240-
return Err(CheckError::InvalidFormat(
241-
"Trailing characters present".to_string(),
242-
));
233+
return Err(CheckError::InvalidFormat("Trailing characters present"));
243234
}
244235

245236
let output = md5_crypt(password.as_bytes(), salt.as_bytes()).map_err(CheckError::Crypt)?;

md5-crypt/tests/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use md5_crypt::md5_crypt_b64;
33
#[cfg(feature = "simple")]
44
use md5_crypt::{md5_check, md5_simple};
55

6+
use std::str;
7+
68
struct TestVector {
79
input: &'static str,
810
salt: &'static str,
@@ -76,7 +78,8 @@ const TEST_VECTORS: &[TestVector] = &[
7678
#[test]
7779
fn test_md5_crypt() {
7880
for t in TEST_VECTORS {
79-
let result = md5_crypt_b64(t.input.as_bytes(), t.salt.as_bytes()).unwrap();
81+
let result_array = md5_crypt_b64(t.input.as_bytes(), t.salt.as_bytes()).unwrap();
82+
let result = str::from_utf8(&result_array).unwrap();
8083
assert!(result == t.result);
8184
}
8285
}

0 commit comments

Comments
 (0)