ctru/services/ps.rs
1//! Process Services.
2//!
3//! This service handles miscellaneous utility tasks used by the various processes.
4//! However, it is particularly important because it is used to generate cryptographically secure random data, which
5//! is required for commonly used functionality such as hashing (e.g. [`HashMap`](std::collections::HashMap) will not work without it).
6//!
7//! See also <https://www.3dbrew.org/wiki/Process_Services>
8
9use crate::Result;
10use crate::error::ResultCode;
11
12/// Type of AES algorithm to use.
13#[doc(alias = "PS_AESAlgorithm")]
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[repr(u8)]
16pub enum AESAlgorithm {
17 /// CBC encryption.
18 CbcEnc = ctru_sys::PS_ALGORITHM_CBC_ENC,
19 /// CBC decryption.
20 CbcDec = ctru_sys::PS_ALGORITHM_CBC_DEC,
21 /// CTR encryption.
22 CtrEnc = ctru_sys::PS_ALGORITHM_CTR_ENC,
23 /// CTR decryption.
24 CtrDec = ctru_sys::PS_ALGORITHM_CTR_DEC,
25 /// CCM encryption.
26 CcmEnc = ctru_sys::PS_ALGORITHM_CCM_ENC,
27 /// CCM decryption.
28 CcmDec = ctru_sys::PS_ALGORITHM_CCM_DEC,
29}
30
31/// PS Key slot to use.
32#[doc(alias = "PS_AESKeyType")]
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34#[repr(u8)]
35pub enum AESKeyType {
36 /// Keyslot 0x0D.
37 Keyslot0D = ctru_sys::PS_KEYSLOT_0D,
38 /// Keyslot 0x2D.
39 Keyslot2D = ctru_sys::PS_KEYSLOT_2D,
40 /// Keyslot 0x2E.
41 Keyslot2E = ctru_sys::PS_KEYSLOT_2E,
42 /// Keyslot 0x31.
43 Keyslot31 = ctru_sys::PS_KEYSLOT_31,
44 /// Keyslot 0x32.
45 Keyslot32 = ctru_sys::PS_KEYSLOT_32,
46 /// Keyslot 0x36.
47 Keyslot36 = ctru_sys::PS_KEYSLOT_36,
48 /// Keyslot 0x38.
49 Keyslot38 = ctru_sys::PS_KEYSLOT_38,
50 /// Keyslot 0x39 (DLP).
51 Keyslot39Dlp = ctru_sys::PS_KEYSLOT_39_DLP,
52 /// Keyslot 0x39 (NFC).
53 Keyslot39Nfc = ctru_sys::PS_KEYSLOT_39_NFC,
54 /// Invalid keyslot.
55 KeyslotInvalid = ctru_sys::PS_KEYSLOT_INVALID,
56}
57
58/// Handle to the PS service.
59pub struct Ps(());
60
61impl Ps {
62 /// Initialize a new service handle.
63 ///
64 /// # Example
65 ///
66 /// ```
67 /// # let _runner = test_runner::GdbRunner::default();
68 /// # use std::error::Error;
69 /// # fn main() -> Result<(), Box<dyn Error>> {
70 /// #
71 /// use ctru::services::ps::Ps;
72 ///
73 /// let ps = Ps::new()?;
74 /// #
75 /// # Ok(())
76 /// # }
77 /// ```
78 #[doc(alias = "psInit")]
79 pub fn new() -> Result<Self> {
80 unsafe {
81 ResultCode(ctru_sys::psInit())?;
82 Ok(Ps(()))
83 }
84 }
85
86 /// Returns the console's local friend code seed.
87 ///
88 /// # Example
89 ///
90 /// ```
91 /// # let _runner = test_runner::GdbRunner::default();
92 /// # use std::error::Error;
93 /// # fn main() -> Result<(), Box<dyn Error>> {
94 /// #
95 /// use ctru::services::ps::Ps;
96 /// let ps = Ps::new()?;
97 ///
98 /// let friend_code_seed = ps.local_friend_code_seed()?;
99 /// #
100 /// # Ok(())
101 /// # }
102 /// ```
103 #[doc(alias = "PS_GetLocalFriendCodeSeed")]
104 pub fn local_friend_code_seed(&self) -> crate::Result<u64> {
105 let mut seed: u64 = 0;
106
107 ResultCode(unsafe { ctru_sys::PS_GetLocalFriendCodeSeed(&mut seed) })?;
108 Ok(seed)
109 }
110
111 /// Returns the console's devide ID.
112 ///
113 /// # Example
114 ///
115 /// ```
116 /// # let _runner = test_runner::GdbRunner::default();
117 /// # use std::error::Error;
118 /// # fn main() -> Result<(), Box<dyn Error>> {
119 /// #
120 /// use ctru::services::ps::Ps;
121 /// let ps = Ps::new()?;
122 ///
123 /// let device_id = ps.device_id()?;
124 /// #
125 /// # Ok(())
126 /// # }
127 /// ```
128 #[doc(alias = "PS_GetDeviceId")]
129 pub fn device_id(&self) -> crate::Result<u32> {
130 let mut id: u32 = 0;
131
132 ResultCode(unsafe { ctru_sys::PS_GetDeviceId(&mut id) })?;
133 Ok(id)
134 }
135
136 /// Generates cryptografically secure random bytes and writes them into the `out` buffer.
137 ///
138 /// # Example
139 ///
140 /// ```
141 /// # let _runner = test_runner::GdbRunner::default();
142 /// # use std::error::Error;
143 /// # fn main() -> Result<(), Box<dyn Error>> {
144 /// #
145 /// use ctru::services::ps::Ps;
146 /// let ps = Ps::new()?;
147 ///
148 /// let mut buffer = vec![0; 128];
149 ///
150 /// // The buffer is now randomized!
151 /// ps.generate_random_bytes(&mut buffer)?;
152 /// #
153 /// # Ok(())
154 /// # }
155 /// ```
156 #[doc(alias = "PS_GenerateRandomBytes")]
157 pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> {
158 ResultCode(unsafe {
159 ctru_sys::PS_GenerateRandomBytes(out.as_mut_ptr().cast(), out.len())
160 })?;
161 Ok(())
162 }
163}
164
165impl Drop for Ps {
166 #[doc(alias = "psExit")]
167 fn drop(&mut self) {
168 unsafe {
169 ctru_sys::psExit();
170 }
171 }
172}
173
174from_impl!(AESAlgorithm, ctru_sys::PS_AESAlgorithm);
175from_impl!(AESKeyType, ctru_sys::PS_AESKeyType);
176
177#[cfg(test)]
178mod tests {
179 use std::collections::HashMap;
180
181 #[test]
182 fn construct_hash_map() {
183 let mut input = vec![
184 (1_i32, String::from("123")),
185 (2, String::from("2")),
186 (6, String::from("six")),
187 ];
188
189 let map: HashMap<i32, String> = HashMap::from_iter(input.clone());
190
191 let mut actual: Vec<_> = map.into_iter().collect();
192 input.sort();
193 actual.sort();
194
195 assert_eq!(input, actual);
196 }
197}