Skip to content

Commit 4ea667e

Browse files
committed
kx.rs: replace Vec with fixed buffers in key exchange modules
Switch from Vec<u8> to Box<[u8]> and fixed-size arrays in key exchange implementations since crypto keys have known sizes. This reduces heap allocations and improves memory efficiency with no functional changes.
1 parent 26437d0 commit 4ea667e

File tree

5 files changed

+89
-103
lines changed

5 files changed

+89
-103
lines changed

rustls-wolfcrypt-provider/src/error.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub fn check_if_one(stat: i32) -> WCResult {
8989
match stat {
9090
1 => Ok(()),
9191
0 => Err(WCError::Failure),
92-
_ => check_error(stat)
92+
_ => check_error(stat),
9393
}
9494
}
9595

@@ -106,7 +106,7 @@ pub fn check_if_greater_than_zero(ret: i32) -> WCResult {
106106
match ret {
107107
x if x > 0 => Ok(()),
108108
0 => Err(WCError::Failure),
109-
_ => check_error(ret)
109+
_ => check_error(ret),
110110
}
111111
}
112112

@@ -119,10 +119,16 @@ mod tests {
119119
assert_eq!(WCError::Success.to_string(), "Operation successful");
120120
assert_eq!(WCError::Failure.to_string(), "Operation failed");
121121
assert_eq!(WCError::Memory.to_string(), "Memory allocation error");
122-
assert_eq!(WCError::InvalidArgument.to_string(), "Invalid argument or state");
122+
assert_eq!(
123+
WCError::InvalidArgument.to_string(),
124+
"Invalid argument or state"
125+
);
123126
assert_eq!(WCError::Buffer.to_string(), "Buffer error");
124127
assert_eq!(WCError::Authentication.to_string(), "Authentication failed");
125-
assert_eq!(WCError::RandomError.to_string(), "Random number generation error");
128+
assert_eq!(
129+
WCError::RandomError.to_string(),
130+
"Random number generation error"
131+
);
126132
assert_eq!(WCError::ASNParse.to_string(), "ASN parsing error");
127133
assert_eq!(WCError::KeyError.to_string(), "Key-related error");
128134
assert_eq!(WCError::NotAvailable.to_string(), "Feature not available");
@@ -160,6 +166,9 @@ mod tests {
160166
fn test_check_if_greater_than_zero() {
161167
assert!(check_if_greater_than_zero(1).is_ok());
162168
assert!(check_if_greater_than_zero(0).is_err());
163-
assert!(matches!(check_if_greater_than_zero(-1), Err(WCError::Failure)));
169+
assert!(matches!(
170+
check_if_greater_than_zero(-1),
171+
Err(WCError::Failure)
172+
));
164173
}
165174
}

rustls-wolfcrypt-provider/src/kx/sec256r1.rs

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
use crate::{error::check_if_zero, types::*};
22
use alloc::boxed::Box;
3-
use alloc::vec;
4-
use alloc::vec::Vec;
53
use core::mem;
64
use core::ptr;
75
use foreign_types::ForeignType;
86
use wolfcrypt_rs::*;
97

108
pub struct KeyExchangeSecP256r1 {
11-
priv_key_bytes: Vec<u8>,
12-
pub_key_bytes: Vec<u8>,
9+
priv_key_bytes: Box<[u8]>,
10+
pub_key_bytes: Box<[u8]>,
1311
}
1412

1513
pub struct ECCPubKey {
16-
qx: Vec<u8>,
14+
qx: [u8; 32],
1715
qx_len: word32,
18-
qy: Vec<u8>,
16+
qy: [u8; 32],
1917
qy_len: word32,
2018
}
2119

@@ -27,21 +25,18 @@ impl KeyExchangeSecP256r1 {
2725
let rng_object: WCRngObject = WCRngObject::new(&mut rng);
2826
let mut ret;
2927
let mut pub_key_raw = ECCPubKey {
30-
qx: [0; 32].to_vec(),
28+
qx: [0; 32],
3129
qx_len: 32,
32-
qy: [0; 32].to_vec(),
30+
qy: [0; 32],
3331
qy_len: 32,
3432
};
3533

36-
// We initiliaze the ecc key object.
3734
key_object.init();
38-
39-
// We initiliaze the rng object.
4035
rng_object.init();
4136

4237
let key_size = unsafe { wc_ecc_get_curve_size_from_id(ecc_curve_id_ECC_SECP256R1) };
4338

44-
let mut priv_key_raw: Vec<u8> = vec![0; key_size as usize];
39+
let mut priv_key_raw = [0u8; 32];
4540
let mut priv_key_raw_len: word32 = priv_key_raw.len() as word32;
4641

4742
ret = unsafe {
@@ -73,33 +68,31 @@ impl KeyExchangeSecP256r1 {
7368
)
7469
};
7570
check_if_zero(ret).unwrap();
71+
// One byte prefix (0x04) + 32 bytes X coord + 32 bytes Y coord
72+
let mut pub_key_bytes = [0x04; 65];
7673

77-
let mut pub_key_bytes = Vec::new();
74+
// Copy X coordinate into bytes 1-32
75+
pub_key_bytes[1..33].copy_from_slice(&pub_key_raw.qx);
7876

79-
pub_key_bytes.push(0x04);
80-
pub_key_bytes.extend(pub_key_raw.qx.clone());
81-
pub_key_bytes.extend(pub_key_raw.qy.clone());
82-
pub_key_bytes.as_slice();
77+
// Copy Y coordinate into bytes 33-64
78+
pub_key_bytes[33..65].copy_from_slice(&pub_key_raw.qy);
8379

8480
KeyExchangeSecP256r1 {
85-
priv_key_bytes: priv_key_raw.to_vec(),
86-
pub_key_bytes: pub_key_bytes.to_vec(),
81+
priv_key_bytes: Box::new(priv_key_raw),
82+
pub_key_bytes: Box::new(pub_key_bytes),
8783
}
8884
}
8985

90-
pub fn derive_shared_secret(&self, peer_pub_key: Vec<u8>) -> Vec<u8> {
86+
pub fn derive_shared_secret(&self, peer_pub_key: &[u8]) -> Box<[u8]> {
9187
let mut priv_key: ecc_key = unsafe { mem::zeroed() };
9288
let priv_key_object = ECCKeyObject::new(&mut priv_key);
9389
let mut pub_key: ecc_key = unsafe { mem::zeroed() };
9490
let pub_key_object = ECCKeyObject::new(&mut pub_key);
95-
let mut ret;
9691
let mut rng: WC_RNG = unsafe { mem::zeroed() };
9792
let rng_object = WCRngObject::new(&mut rng);
93+
let mut ret: i32;
9894

99-
// We initialize the private key before we import it.
10095
priv_key_object.init();
101-
102-
// We initiliaze the public key before we import it.
10396
pub_key_object.init();
10497

10598
ret = unsafe {
@@ -114,10 +107,6 @@ impl KeyExchangeSecP256r1 {
114107
};
115108
check_if_zero(ret).unwrap();
116109

117-
/*
118-
* Skipping first byte because rustls uses this format:
119-
* https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.2.
120-
* */
121110
ret = unsafe {
122111
wc_ecc_import_unsigned(
123112
pub_key_object.as_ptr(),
@@ -129,7 +118,6 @@ impl KeyExchangeSecP256r1 {
129118
};
130119
check_if_zero(ret).unwrap();
131120

132-
// We initialize the rng object.
133121
rng_object.init();
134122

135123
ret = unsafe { wc_ecc_set_rng(pub_key_object.as_ptr(), rng_object.as_ptr()) };
@@ -138,9 +126,7 @@ impl KeyExchangeSecP256r1 {
138126
ret = unsafe { wc_ecc_set_rng(priv_key_object.as_ptr(), rng_object.as_ptr()) };
139127
check_if_zero(ret).unwrap();
140128

141-
let key_size = unsafe { wc_ecc_get_curve_size_from_id(ecc_curve_id_ECC_SECP256R1) };
142-
143-
let mut out: Vec<u8> = vec![0; key_size as usize];
129+
let mut out = [0u8; 32];
144130
let mut out_len: word32 = out.len() as word32;
145131

146132
ret = unsafe {
@@ -153,7 +139,7 @@ impl KeyExchangeSecP256r1 {
153139
};
154140
check_if_zero(ret).unwrap();
155141

156-
out.to_vec()
142+
Box::new(out)
157143
}
158144
}
159145

@@ -162,15 +148,12 @@ impl rustls::crypto::ActiveKeyExchange for KeyExchangeSecP256r1 {
162148
self: Box<Self>,
163149
peer_pub_key: &[u8],
164150
) -> Result<rustls::crypto::SharedSecret, rustls::Error> {
165-
// We derive the shared secret with our private key and
166-
// the received public key.
167-
let secret = self.derive_shared_secret(peer_pub_key.to_vec());
168-
169-
Ok(rustls::crypto::SharedSecret::from(secret.as_slice()))
151+
let secret = self.derive_shared_secret(peer_pub_key);
152+
Ok(rustls::crypto::SharedSecret::from(&*secret))
170153
}
171154

172155
fn pub_key(&self) -> &[u8] {
173-
self.pub_key_bytes.as_slice()
156+
&self.pub_key_bytes
174157
}
175158

176159
fn group(&self) -> rustls::NamedGroup {
@@ -189,8 +172,8 @@ mod tests {
189172
let bob = Box::new(KeyExchangeSecP256r1::use_secp256r1());
190173

191174
assert_eq!(
192-
alice.derive_shared_secret(bob.pub_key().try_into().unwrap()),
193-
bob.derive_shared_secret(alice.pub_key().try_into().unwrap()),
175+
alice.derive_shared_secret(bob.pub_key()),
176+
bob.derive_shared_secret(alice.pub_key()),
194177
)
195178
}
196179
}

rustls-wolfcrypt-provider/src/kx/sec384r1.rs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
use crate::error::*;
22
use crate::types::*;
33
use alloc::boxed::Box;
4-
use alloc::vec;
5-
use alloc::vec::Vec;
64
use core::mem;
75
use core::ptr;
86
use foreign_types::ForeignType;
97
use wolfcrypt_rs::*;
108

119
pub struct KeyExchangeSecP384r1 {
12-
priv_key_bytes: Vec<u8>,
13-
pub_key_bytes: Vec<u8>,
10+
priv_key_bytes: Box<[u8]>,
11+
pub_key_bytes: Box<[u8]>,
1412
}
1513

1614
pub struct ECCPubKey {
17-
qx: Vec<u8>,
15+
qx: [u8; 48],
1816
qx_len: word32,
19-
qy: Vec<u8>,
17+
qy: [u8; 48],
2018
qy_len: word32,
2119
}
2220

@@ -28,9 +26,9 @@ impl KeyExchangeSecP384r1 {
2826
let rng_object: WCRngObject = WCRngObject::new(&mut rng);
2927
let mut ret;
3028
let mut pub_key_raw = ECCPubKey {
31-
qx: [0; 48].to_vec(),
29+
qx: [0; 48],
3230
qx_len: 48,
33-
qy: [0; 48].to_vec(),
31+
qy: [0; 48],
3432
qy_len: 48,
3533
};
3634

@@ -50,7 +48,7 @@ impl KeyExchangeSecP384r1 {
5048
};
5149
check_if_zero(ret).unwrap();
5250

53-
let mut priv_key_raw: Vec<u8> = vec![0; key_size as usize];
51+
let mut priv_key_raw = [0u8; 48];
5452
let mut priv_key_raw_len: word32 = priv_key_raw.len() as word32;
5553

5654
ret = unsafe {
@@ -73,20 +71,22 @@ impl KeyExchangeSecP384r1 {
7371
};
7472
check_if_zero(ret).unwrap();
7573

76-
let mut pub_key_bytes = Vec::new();
74+
// One byte prefix + 48 bytes X + 48 bytes Y
75+
let mut pub_key_bytes = [0x04; 97];
7776

78-
pub_key_bytes.push(0x04);
79-
pub_key_bytes.extend(pub_key_raw.qx.clone());
80-
pub_key_bytes.extend(pub_key_raw.qy.clone());
81-
pub_key_bytes.as_slice();
77+
// Copy X coordinate into bytes 1-49
78+
pub_key_bytes[1..49].copy_from_slice(&pub_key_raw.qx);
79+
80+
// Copy Y coordinate into bytes 49-97
81+
pub_key_bytes[49..97].copy_from_slice(&pub_key_raw.qy);
8282

8383
KeyExchangeSecP384r1 {
84-
priv_key_bytes: priv_key_raw.to_vec(),
85-
pub_key_bytes: pub_key_bytes.to_vec(),
84+
priv_key_bytes: Box::new(priv_key_raw),
85+
pub_key_bytes: Box::new(pub_key_bytes),
8686
}
8787
}
8888

89-
pub fn derive_shared_secret(&self, peer_pub_key: Vec<u8>) -> Vec<u8> {
89+
pub fn derive_shared_secret(&self, peer_pub_key: &[u8]) -> Box<[u8]> {
9090
let mut priv_key: ecc_key = unsafe { mem::zeroed() };
9191
let priv_key_object: ECCKeyObject = ECCKeyObject::new(&mut priv_key);
9292
let mut pub_key: ecc_key = unsafe { mem::zeroed() };
@@ -133,9 +133,7 @@ impl KeyExchangeSecP384r1 {
133133
ret = unsafe { wc_ecc_set_rng(priv_key_object.as_ptr(), rng_object.as_ptr()) };
134134
check_if_zero(ret).unwrap();
135135

136-
let key_size = unsafe { wc_ecc_get_curve_size_from_id(ecc_curve_id_ECC_SECP384R1) };
137-
138-
let mut out: Vec<u8> = vec![0; key_size as usize];
136+
let mut out = [0u8; 48];
139137
let mut out_len: word32 = out.len() as word32;
140138

141139
ret = unsafe {
@@ -148,7 +146,7 @@ impl KeyExchangeSecP384r1 {
148146
};
149147
check_if_zero(ret).unwrap();
150148

151-
out.to_vec()
149+
Box::new(out)
152150
}
153151
}
154152

@@ -159,13 +157,13 @@ impl rustls::crypto::ActiveKeyExchange for KeyExchangeSecP384r1 {
159157
) -> Result<rustls::crypto::SharedSecret, rustls::Error> {
160158
// We derive the shared secret with our private key and
161159
// the received public key.
162-
let secret = self.derive_shared_secret(peer_pub_key.to_vec());
160+
let secret = self.derive_shared_secret(peer_pub_key);
163161

164-
Ok(rustls::crypto::SharedSecret::from(secret.as_slice()))
162+
Ok(rustls::crypto::SharedSecret::from(&*secret))
165163
}
166164

167165
fn pub_key(&self) -> &[u8] {
168-
self.pub_key_bytes.as_slice()
166+
&self.pub_key_bytes
169167
}
170168

171169
fn group(&self) -> rustls::NamedGroup {

0 commit comments

Comments
 (0)