1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use super::{digest, utils};
use super::{
    ATTEST_KEY_CURVE_ECC_SECP384R1, PLAT_TOKEN, REALM_ATTEST_KEY, RMM_SHARED_BUFFER_LOCK,
    SHA256_DIGEST_SIZE,
};
use crate::asm::smc;
use crate::{config, rmi};
use spinning_top::SpinlockGuard;

#[derive(Debug)]
enum RmmEl3IfcError {
    Unk,
    BadAddr,
    BadPas,
    NoMem,
    Inval,
}

impl From<isize> for RmmEl3IfcError {
    fn from(value: isize) -> Self {
        match value {
            -1 => RmmEl3IfcError::Unk,
            -2 => RmmEl3IfcError::BadAddr,
            -3 => RmmEl3IfcError::BadPas,
            -4 => RmmEl3IfcError::NoMem,
            -5 => RmmEl3IfcError::Inval,
            _ => panic!("Uknown RMM-EL3 SMC error code"),
        }
    }
}

pub(super) fn get_realm_attest_key() {
    trace!("GET_REALM_ATTEST_KEY");

    let guard: SpinlockGuard<'_, _> = super::RMM_SHARED_BUFFER_LOCK.lock();

    let ret = smc(
        rmi::GET_REALM_ATTEST_KEY,
        &[*guard, config::PAGE_SIZE, ATTEST_KEY_CURVE_ECC_SECP384R1],
    );

    let ret_code = ret[0] as isize;
    let buflen = ret[1] as usize;
    debug!(
        "GET_REALM_ATTEST_KEY returned with: {}, {}",
        ret_code, buflen
    );

    if ret_code != 0 {
        let e: RmmEl3IfcError = ret_code.into();
        error!("GET_REALM_ATTEST_KEY failed with {:?}", e);
    }

    let v = utils::va_to_vec(*guard, buflen);
    utils::set_vector(v, &REALM_ATTEST_KEY);

    debug!("{:x?}", super::realm_attest_key());
}

pub(super) fn get_plat_token() {
    trace!("GET_PLAT_TOKEN");

    let guard: SpinlockGuard<'_, _> = RMM_SHARED_BUFFER_LOCK.lock();

    let dak_priv = utils::get_vector(&REALM_ATTEST_KEY);
    let dak_pub_hash = digest::get_realm_public_key_hash(dak_priv);
    utils::vec_to_va(&dak_pub_hash, *guard, config::PAGE_SIZE);

    let ret = smc(
        rmi::GET_PLAT_TOKEN,
        &[*guard, config::PAGE_SIZE, SHA256_DIGEST_SIZE],
    );

    let ret_code = ret[0] as isize;
    let buflen = ret[1] as usize;
    debug!("GET_PLAT_TOKEN returned with: {}, {}", ret_code, buflen);

    if ret_code != 0 {
        let e: RmmEl3IfcError = ret_code.into();
        error!("GET_PLAT_TOKEN failed with {:?}", e);
    }

    let v = utils::va_to_vec(*guard, buflen);
    utils::set_vector(v, &PLAT_TOKEN);

    debug!("{:x?}", super::plat_token());
}