Skip to main content

optee_teec/
uuid.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::raw;
19use crate::{ErrorKind, Result};
20use core::fmt;
21use uuid as uuid_crate;
22
23/// A Universally Unique Resource Identifier (UUID) type as defined in RFC4122.
24/// The value is used to identify a trusted application.
25pub struct Uuid {
26    raw: raw::TEEC_UUID,
27}
28
29impl Uuid {
30    /// Parses a Uuid from a string of hexadecimal digits with optional hyphens.
31    ///
32    /// # Examples
33    ///
34    /// ```
35    /// # use optee_teec::Uuid;
36    /// # fn main() -> optee_teec::Result<()> {
37    /// let uuid = Uuid::parse_str("8abcf200-2450-11e4-abe2-0002a5d5c51b")?;
38    /// # Ok(())
39    /// # }
40    /// ```
41    pub fn parse_str(input: &str) -> Result<Uuid> {
42        let uuid = uuid_crate::Uuid::parse_str(input).map_err(|_| ErrorKind::BadFormat)?;
43        let (time_low, time_mid, time_hi_and_version, clock_seq_and_node) = uuid.as_fields();
44        Ok(Self::new_raw(
45            time_low,
46            time_mid,
47            time_hi_and_version,
48            *clock_seq_and_node,
49        ))
50    }
51
52    /// Creates a `Uuid` using the supplied big-endian bytes.
53    ///
54    /// # Examples
55    ///
56    /// ```
57    /// # use optee_teec::Uuid;
58    /// let bytes: [u8; 16] = [70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62,];
59    /// let uuid = Uuid::from_bytes(bytes);
60    /// ```
61    pub fn from_bytes(bytes: [u8; 16]) -> Uuid {
62        let uuid = uuid_crate::Uuid::from_bytes(bytes);
63        let (time_low, time_mid, time_hi_and_version, clock_seq_and_node) = uuid.as_fields();
64        Self::new_raw(time_low, time_mid, time_hi_and_version, *clock_seq_and_node)
65    }
66
67    /// Creates a `Uuid` using a slice of supplied big-endian bytes.
68    ///
69    /// # Examples
70    ///
71    /// ```
72    /// # use optee_teec::Uuid;
73    /// # fn main() -> optee_teec::Result<()> {
74    /// let bytes: &[u8; 16] = &[70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62,];
75    /// let uuid = Uuid::from_slice(bytes)?;
76    /// # Ok(())
77    /// # }
78    /// ```
79    pub fn from_slice(b: &[u8]) -> Result<Uuid> {
80        let uuid = uuid_crate::Uuid::from_slice(b).map_err(|_| ErrorKind::BadFormat)?;
81        let (time_low, time_mid, time_hi_and_version, clock_seq_and_node) = uuid.as_fields();
82        Ok(Self::new_raw(
83            time_low,
84            time_mid,
85            time_hi_and_version,
86            *clock_seq_and_node,
87        ))
88    }
89
90    /// Crates a raw TEE client uuid object with specified parameters.
91    pub fn new_raw(
92        time_low: u32,
93        time_mid: u16,
94        time_hi_and_version: u16,
95        clock_seq_and_nod: [u8; 8],
96    ) -> Uuid {
97        let raw_uuid = raw::TEEC_UUID {
98            timeLow: time_low,
99            timeMid: time_mid,
100            timeHiAndVersion: time_hi_and_version,
101            clockSeqAndNode: clock_seq_and_nod,
102        };
103        Self { raw: raw_uuid }
104    }
105
106    /// Converts a uuid to a const raw `TEEC_UUID` pointer.
107    pub fn as_raw_ptr(&self) -> *const raw::TEEC_UUID {
108        &self.raw
109    }
110}
111
112impl Clone for Uuid {
113    fn clone(&self) -> Self {
114        Self::new_raw(
115            self.raw.timeLow,
116            self.raw.timeMid,
117            self.raw.timeHiAndVersion,
118            self.raw.clockSeqAndNode,
119        )
120    }
121}
122
123impl fmt::Display for Uuid {
124    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125        write!(
126            f,
127            "{:08x}-{:04x}-{:04x}-{}-{}",
128            self.raw.timeLow,
129            self.raw.timeMid,
130            self.raw.timeHiAndVersion,
131            hex::encode(&self.raw.clockSeqAndNode[0..2]),
132            hex::encode(&self.raw.clockSeqAndNode[2..8]),
133        )
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::Uuid;
140
141    #[test]
142    fn test_to_string() {
143        let uuids = [
144            "00173366-2aca-49bc-beb7-10c975e6131e", // uuid with timeLow leading zeros
145            "11173366-0aca-49bc-beb7-10c975e6131e", // uuid with timeMid leading zeros
146            "11173366-2aca-09bc-beb7-10c975e6131e", // uuid with timeHiAndVersion leading zeros
147            "11173366-2aca-19bc-beb7-10c975e6131e", // random uuid
148        ];
149        for origin in uuids.iter() {
150            let uuid = Uuid::parse_str(origin).expect("Test UUID should be valid");
151            let formatted = uuid.to_string();
152            assert_eq!(*origin, formatted);
153        }
154    }
155}