How to return a section of an array using slice

Hello Rust Experts,

Please how do I get my function to return a slice of an array? For consistency, I need to maintain a &[u8] or [u8; N]. Thanks

Reference code: https://github.com/eshikafe/ngr/blob/master/ngr/src/security/ts_33_401/crypto.rs

use hmac_sha256::*;


fn main() {

    let kenb: &[u8] = &[0u8; 32];
    let k = k_rrc_int_key(kenb);
    println!("{:?}", k);
    
}

// A.7 Algorithm Key Derivation Functions
fn algo_kdf(k_enb: &[u8], algo_type: u8, algo_id: u8) -> [u8; 32] {
	let fc: u8 = 0x15; 
	let p0: u8 = algo_type;            // algorithm type distinguisher
	let l0: [u8;2] = [0x00, 0x01];     // length of algorithm type distinguisher (i.e 0x00 0x01)
	let p1: u8 = algo_id;              // algorithm identity
	let l1: [u8;2] = [0x00, 0x01];     // length of algorithm identity (i.e. 0x00 0x01)

    // S = FC || P0 || L0 || P1 || L1 || P2 || L2 || P3 || L3 ||... || Pn || Ln
    let s = [fc, p0, l0[0], l0[1], p1, l1[0], l1[1]]; 
    return kdf(k_enb, &s);
}

fn kdf(key: &[u8], s: &[u8]) -> [u8; 32] {
 	let h1 = HMAC::mac(s, key);
    return h1; // 256 bits
 }

 fn k_rrc_int_key(k_enb: &[u8]) -> &[u8] {
	let k = algo_kdf(k_enb, 0x3, 0x2);
    let r: &[u8] = &k[16..32];
	return r; // Truncate to 128 bits
}

Output:

C:\Users\eshikafe\Documents\hello> cargo run
   Compiling hello v0.1.0 (C:\Users\eshikafe\Documents\hello)
error[E0515]: cannot return value referencing local variable `k`
  --> src\main.rs:34:9
   |
34 |     return &k[16..32]; // Truncate to 128 bits
   |            ^-^^^^^^^^
   |            ||
   |            |`k` is borrowed here
   |            returns a value referencing data owned by the current function

error: aborting due to previous error

For more information about this error, try `rustc --explain E0515`.
error: Could not compile `hello`.

Thanks.

Regards,
Austin

If we look at k_rrc_int_key where the compiler says the error is we can see that it’s attempting to return a slice of k. k in this case is a [u8;32] created by the algo_kdf function. It would be invalid to return a slice of an array that’s owned by the function. Once k_rrc_int_key returns the array would be destroyed and the slice returned would point to invalid memory. The simplest fix is that k_rrc_int_key should return an owned value [u8;16].

something like:

fn k_rrc_int_key(k_enb: &[u8]) -> [u8; 16] {
    let k = algo_kdf(k_enb, 0x3, 0x2);
    let mut r: [u8; 16] = Default::default();
    r.clone_from_slice(&k[16..32]);
	return r; // Truncate to 128 bits
}
1 Like

You can also use TryFrom

fn k_rrc_int_key(k_enb: &[u8]) -> [u8; 16] {
    use std::convert::TryFrom;

    let k = algo_kdf(k_enb, 0x3, 0x2);
    TryFrom::try_from(&k[16..32]).unwrap()
}

And maybe you already know it but you don’t have to return explicitly in Rust, for example:

fn kdf(key: &[u8], s: &[u8]) -> [u8; 32] {
    HMAC::mac(s, key) // 256 bits
}
1 Like

Thanks ggriffinii and leudz for your response.