Skip to content

Commit 1b6efc9

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 3a2659a commit 1b6efc9

File tree

4 files changed

+75
-98
lines changed

4 files changed

+75
-98
lines changed

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 {

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

Lines changed: 21 additions & 24 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 KeyExchangeSecP521r1 {
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; 66],
1715
qx_len: word32,
18-
qy: Vec<u8>,
16+
qy: [u8; 66],
1917
qy_len: word32,
2018
}
2119

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

@@ -51,7 +49,7 @@ impl KeyExchangeSecP521r1 {
5149
};
5250
check_if_zero(ret).unwrap();
5351

54-
let mut priv_key_raw: Vec<u8> = vec![0; key_size as usize];
52+
let mut priv_key_raw = [0u8; 66];
5553
let mut priv_key_raw_len: word32 = priv_key_raw.len() as word32;
5654

5755
ret = unsafe {
@@ -74,20 +72,21 @@ impl KeyExchangeSecP521r1 {
7472
};
7573
check_if_zero(ret).unwrap();
7674

77-
let mut pub_key_bytes = Vec::new();
75+
let mut pub_key_bytes = [0x04; 133]; // One byte prefix + 66 bytes X + 66 bytes Y
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 X coordinate into bytes 1-66
78+
pub_key_bytes[1..67].copy_from_slice(&pub_key_raw.qx);
79+
80+
// Copy Y coordinate into bytes 67-133
81+
pub_key_bytes[67..133].copy_from_slice(&pub_key_raw.qy);
8382

8483
KeyExchangeSecP521r1 {
85-
priv_key_bytes: priv_key_raw.to_vec(),
86-
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),
8786
}
8887
}
8988

90-
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]> {
9190
let mut priv_key: ecc_key = unsafe { mem::zeroed() };
9291
let priv_key_object: ECCKeyObject = ECCKeyObject::new(&mut priv_key);
9392
let mut pub_key: ecc_key = unsafe { mem::zeroed() };
@@ -135,9 +134,7 @@ impl KeyExchangeSecP521r1 {
135134
ret = unsafe { wc_ecc_set_rng(priv_key_object.as_ptr(), rng_object.as_ptr()) };
136135
check_if_zero(ret).unwrap();
137136

138-
let key_size = unsafe { wc_ecc_get_curve_size_from_id(ecc_curve_id_ECC_SECP521R1) };
139-
140-
let mut out: Vec<u8> = vec![0; key_size as usize];
137+
let mut out = [0u8; 66];
141138
let mut out_len: word32 = out.len() as word32;
142139

143140
ret = unsafe {
@@ -150,7 +147,7 @@ impl KeyExchangeSecP521r1 {
150147
};
151148
check_if_zero(ret).unwrap();
152149

153-
out.to_vec()
150+
Box::new(out)
154151
}
155152
}
156153

@@ -161,13 +158,13 @@ impl rustls::crypto::ActiveKeyExchange for KeyExchangeSecP521r1 {
161158
) -> Result<rustls::crypto::SharedSecret, rustls::Error> {
162159
// We derive the shared secret with our private key and
163160
// the received public key.
164-
let secret = self.derive_shared_secret(peer_pub_key.to_vec());
161+
let secret = self.derive_shared_secret(peer_pub_key);
165162

166-
Ok(rustls::crypto::SharedSecret::from(secret.as_slice()))
163+
Ok(rustls::crypto::SharedSecret::from(&*secret))
167164
}
168165

169166
fn pub_key(&self) -> &[u8] {
170-
self.pub_key_bytes.as_slice()
167+
&self.pub_key_bytes
171168
}
172169

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

0 commit comments

Comments
 (0)