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}