keyutils/api.rs
1// Copyright (c) 2018, Ben Boeckel
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification,
5// are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of this project nor the names of its contributors
13// may be used to endorse or promote products derived from this software
14// without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27use std::borrow::{Borrow, Cow};
28use std::convert::TryInto;
29use std::mem;
30use std::result;
31use std::str;
32use std::time::Duration;
33
34use keyutils_raw::*;
35use log::error;
36use uninit::extension_traits::VecCapacity;
37
38use crate::constants::{KeyctlSupportFlags, Permission, SpecialKeyring};
39use crate::keytype::*;
40use crate::keytypes;
41
42/// Reexport of `Errno` as `Error`.
43pub type Error = errno::Errno;
44/// Simpler `Result` type with the error already set.
45pub type Result<T> = result::Result<T, Error>;
46
47/// Request a key from the kernel.
48fn request_impl<K: KeyType>(
49 description: &str,
50 info: Option<&str>,
51 id: Option<KeyringSerial>,
52) -> Result<KeyringSerial> {
53 request_key(K::name(), description, info, id)
54}
55
56fn read_impl(id: KeyringSerial) -> Result<Vec<u8>> {
57 // Get the size of the description.
58 let mut sz = keyctl_read(id, None)?;
59 // Allocate this description.
60 let mut buffer = vec![0; sz];
61 loop {
62 let write_buffer = buffer.get_backing_buffer();
63 // Fetch the description.
64 sz = keyctl_read(id, Some(write_buffer))?;
65
66 // If we got everything, exit.
67 if sz <= buffer.capacity() {
68 break;
69 }
70
71 // Resize for the additional capacity we need.
72 buffer.resize(sz, 0);
73 }
74 buffer.truncate(sz);
75 Ok(buffer)
76}
77
78/// Representation of a kernel keyring.
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct Keyring {
81 id: KeyringSerial,
82}
83
84impl Keyring {
85 /// Instantiate a keyring from an ID.
86 ///
87 /// This is unsafe because no keyring is known to exist with the given ID.
88 ///
89 /// # Safety
90 ///
91 /// This method assumes that the given serial is a valid keyring ID at the kernel level.
92 pub unsafe fn new(id: KeyringSerial) -> Self {
93 Keyring {
94 id,
95 }
96 }
97
98 fn new_impl(id: KeyringSerial) -> Self {
99 Keyring {
100 id,
101 }
102 }
103
104 pub(crate) fn serial(&self) -> KeyringSerial {
105 self.id
106 }
107
108 /// Set the default keyring to use when implicit requests on the current thread.
109 ///
110 /// Returns the old default keyring.
111 ///
112 /// # Panics
113 ///
114 /// If the kernel returns a keyring value which the library does not understand, the conversion
115 /// from the return value into a `DefaultKeyring` will panic.
116 pub fn set_default(keyring: DefaultKeyring) -> Result<DefaultKeyring> {
117 keyctl_set_reqkey_keyring(keyring)
118 }
119
120 /// Requests a keyring with the given description by searching the thread, process, and session
121 /// keyrings.
122 ///
123 /// If it is not found, the `info` string (if provided) will be handed off to
124 /// `/sbin/request-key` to generate the key.
125 ///
126 /// If `target` is given, the found keyring will be linked into it. If `target` is not given
127 /// and a new key is constructed due to the request, it will be linked into the default
128 /// keyring (see `Keyring::set_default`).
129 pub fn request<'s, 'a, D, I, T>(description: D, info: I, target: T) -> Result<Self>
130 where
131 D: AsRef<str>,
132 I: Into<Option<&'s str>>,
133 T: Into<Option<TargetKeyring<'a>>>,
134 {
135 request_impl::<keytypes::Keyring>(
136 description.as_ref(),
137 info.into().as_ref().copied(),
138 target.into().map(TargetKeyring::serial),
139 )
140 .map(Self::new_impl)
141 }
142
143 fn get_keyring(id: SpecialKeyring, create: bool) -> Result<Keyring> {
144 keyctl_get_keyring_id(id.serial(), create).map(Self::new_impl)
145 }
146
147 /// Attach to a special keyring. Fails if the keyring does not already exist.
148 pub fn attach(id: SpecialKeyring) -> Result<Self> {
149 Self::get_keyring(id, false)
150 }
151
152 /// Attach to a special keyring or create it if it does not exist.
153 pub fn attach_or_create(id: SpecialKeyring) -> Result<Self> {
154 Self::get_keyring(id, true)
155 }
156
157 /// Create a new anonymous keyring and set it as the session keyring.
158 pub fn join_anonymous_session() -> Result<Self> {
159 keyctl_join_session_keyring(None).map(Self::new_impl)
160 }
161
162 /// Attached to a named session keyring.
163 ///
164 /// If a keyring named `name` exists, attach it as the session keyring (requires the `search`
165 /// permission). If a keyring does not exist, create it and attach it as the session keyring.
166 pub fn join_session<N>(name: N) -> Result<Self>
167 where
168 N: AsRef<str>,
169 {
170 keyctl_join_session_keyring(Some(name.as_ref())).map(Self::new_impl)
171 }
172
173 /// Clears the contents of the keyring.
174 ///
175 /// Requires `write` permission on the keyring.
176 pub fn clear(&mut self) -> Result<()> {
177 keyctl_clear(self.id)
178 }
179
180 /// Adds a link to `key` to the keyring.
181 ///
182 /// Any link to an existing key with the same description is removed. Requires `write`
183 /// permission on the keyring and `link` permission on the key.
184 pub fn link_key(&mut self, key: &Key) -> Result<()> {
185 keyctl_link(key.id, self.id)
186 }
187
188 /// Removes the link to `key` from the keyring.
189 ///
190 /// Requires `write` permission on the keyring.
191 pub fn unlink_key(&mut self, key: &Key) -> Result<()> {
192 keyctl_unlink(key.id, self.id)
193 }
194
195 /// Adds a link to `keyring` to the keyring.
196 ///
197 /// Any link to an existing keyring with the same description is removed. Requires `write`
198 /// permission on the current keyring and `link` permission on the linked keyring.
199 pub fn link_keyring(&mut self, keyring: &Keyring) -> Result<()> {
200 keyctl_link(keyring.id, self.id)
201 }
202
203 /// Removes the link to `keyring` from the keyring.
204 ///
205 /// Requires `write` permission on the keyring.
206 pub fn unlink_keyring(&mut self, keyring: &Keyring) -> Result<()> {
207 keyctl_unlink(keyring.id, self.id)
208 }
209
210 fn search_impl<K>(
211 &self,
212 description: &str,
213 destination: Option<&mut Keyring>,
214 ) -> Result<KeyringSerial>
215 where
216 K: KeyType,
217 {
218 keyctl_search(
219 self.id,
220 K::name(),
221 description,
222 destination.map(|dest| dest.id),
223 )
224 }
225
226 /// Recursively search the keyring for a key with the matching description.
227 ///
228 /// If it is found, it is attached to the keyring (if `write` permission to the keyring and
229 /// `link` permission on the key exist) and return it. Requires the `search` permission on the
230 /// keyring. Any children keyrings without the `search` permission are ignored.
231 pub fn search_for_key<'a, K, D, DK>(&self, description: D, destination: DK) -> Result<Key>
232 where
233 K: KeyType,
234 D: Borrow<K::Description>,
235 DK: Into<Option<&'a mut Keyring>>,
236 {
237 self.search_impl::<K>(&description.borrow().description(), destination.into())
238 .map(Key::new_impl)
239 }
240
241 /// Recursively search the keyring for a keyring with the matching description.
242 ///
243 /// If it is found, it is attached to the keyring (if `write` permission to the keyring and
244 /// `link` permission on the found keyring exist) and return it. Requires the `search`
245 /// permission on the keyring. Any children keyrings without the `search` permission are
246 /// ignored.
247 pub fn search_for_keyring<'a, D, DK>(&self, description: D, destination: DK) -> Result<Self>
248 where
249 D: Borrow<<keytypes::Keyring as KeyType>::Description>,
250 DK: Into<Option<&'a mut Keyring>>,
251 {
252 self.search_impl::<keytypes::Keyring>(
253 &description.borrow().description(),
254 destination.into(),
255 )
256 .map(Self::new_impl)
257 }
258
259 /// Return all immediate children of the keyring.
260 ///
261 /// Requires `read` permission on the keyring.
262 pub fn read(&self) -> Result<(Vec<Key>, Vec<Keyring>)> {
263 // The `description` check below hides this error code from the kernel.
264 if self.id.get() == 0 {
265 return Err(errno::Errno(libc::ENOKEY));
266 }
267
268 // Avoid a panic in the code below be ensuring that we actually have a keyring. Parsing
269 // a key's payload as a keyring payload.
270 let desc = self.description()?;
271 if desc.type_ != keytypes::Keyring::name() {
272 return Err(errno::Errno(libc::ENOTDIR));
273 }
274
275 let buffer = read_impl(self.id)?;
276 let keyring_children = {
277 let chunk_size = mem::size_of::<KeyringSerial>();
278 let chunks = buffer.chunks(chunk_size);
279 chunks.map(|chunk| {
280 let bytes = chunk.try_into().map_err(|err| {
281 error!(
282 "A keyring did not have the right number of bytes for a child key or \
283 keyring ID: {}",
284 err,
285 );
286 errno::Errno(libc::EINVAL)
287 })?;
288 let id = i32::from_ne_bytes(bytes);
289 let serial = KeyringSerial::new(id).ok_or_else(|| {
290 error!("A keyring had a child key or keyring ID of 0");
291 errno::Errno(libc::EINVAL)
292 })?;
293 Ok(Key::new_impl(serial))
294 })
295 };
296
297 let mut keys = Vec::new();
298 let mut keyrings = Vec::new();
299 for key in keyring_children {
300 let key = key?;
301 match key.description() {
302 Ok(description) => {
303 if description.type_ == keytypes::Keyring::name() {
304 keyrings.push(Keyring::new_impl(key.id))
305 } else {
306 keys.push(key)
307 }
308 },
309 // Keys can be invalidated between reading the keyring and
310 // reading the child key's description. If this happens, we get
311 // ENOKEY and just skip that key.
312 Err(errno::Errno(libc::ENOKEY)) => {},
313 Err(e) => return Err(e),
314 }
315 }
316 Ok((keys, keyrings))
317 }
318
319 /// Attach the persistent keyring for the current user to the current keyring.
320 ///
321 /// If one does not exist, it will be created. Requires `write` permission on the keyring.
322 pub fn attach_persistent(&mut self) -> Result<Self> {
323 keyctl_get_persistent(!0, self.id).map(Self::new_impl)
324 }
325
326 /// Adds a key of a specific type to the keyring.
327 ///
328 /// If a key with the same description already exists and has the `update` permission, it will
329 /// be updated, otherwise the link to the old key will be removed. Requires `write` permission.
330 pub fn add_key<K, D, P>(&mut self, description: D, payload: P) -> Result<Key>
331 where
332 K: KeyType,
333 D: Borrow<K::Description>,
334 P: Borrow<K::Payload>,
335 {
336 self.add_key_impl::<K>(description.borrow(), payload.borrow())
337 .map(Key::new_impl)
338 }
339
340 /// Monomorphization of adding a key.
341 fn add_key_impl<K>(
342 &mut self,
343 description: &K::Description,
344 payload: &K::Payload,
345 ) -> Result<KeyringSerial>
346 where
347 K: KeyType,
348 {
349 add_key(
350 K::name(),
351 &description.description(),
352 &payload.payload(),
353 self.id,
354 )
355 }
356
357 /// Adds a keyring to the current keyring.
358 ///
359 /// If a keyring with the same description already, the link to the old keyring will be
360 /// removed. Requires `write` permission on the keyring.
361 pub fn add_keyring<D>(&mut self, description: D) -> Result<Self>
362 where
363 D: Borrow<<keytypes::Keyring as KeyType>::Description>,
364 {
365 self.add_key_impl::<keytypes::Keyring>(description.borrow(), &())
366 .map(Self::new_impl)
367 }
368
369 /// Revokes the keyring.
370 ///
371 /// Requires `write` permission on the keyring.
372 pub fn revoke(self) -> Result<()> {
373 keyctl_revoke(self.id)
374 }
375
376 /// Change the user which owns the keyring.
377 ///
378 /// Requires the `setattr` permission on the keyring and the SysAdmin capability to change it
379 /// to anything other than the current user.
380 pub fn chown(&mut self, uid: libc::uid_t) -> Result<()> {
381 keyctl_chown(self.id, Some(uid), None)
382 }
383
384 /// Change the group which owns the keyring.
385 ///
386 /// Requires the `setattr` permission on the keyring and the SysAdmin capability to change it
387 /// to anything other than a group of which the current user is a member.
388 pub fn chgrp(&mut self, gid: libc::gid_t) -> Result<()> {
389 keyctl_chown(self.id, None, Some(gid))
390 }
391
392 /// Set the permissions on the keyring.
393 ///
394 /// Requires the `setattr` permission on the keyring and the SysAdmin capability if the current
395 /// user does not own the keyring.
396 pub fn set_permissions(&mut self, perms: Permission) -> Result<()> {
397 keyctl_setperm(self.id, perms.bits())
398 }
399
400 #[cfg(test)]
401 pub(crate) fn set_permissions_raw(&mut self, perms: KeyPermissions) -> Result<()> {
402 keyctl_setperm(self.id, perms)
403 }
404
405 /// Restrict all links into the keyring.
406 ///
407 /// Requires the `setattr` permission on the keyring and the SysAdmin capability to change it to
408 /// anything other than the current user.
409 pub fn restrict_all(&mut self) -> Result<()> {
410 keyctl_restrict_keyring(self.id, Restriction::AllLinks)
411 }
412
413 /// Restrict links into the keyring.
414 ///
415 /// Requires the `setattr` permission on the keyring and the SysAdmin capability to change it to
416 /// anything other than the current user.
417 pub fn restrict_by_type<K, R>(&mut self, restriction: R) -> Result<()>
418 where
419 K: RestrictableKeyType,
420 R: Borrow<K::Restriction>,
421 {
422 keyctl_restrict_keyring(
423 self.id,
424 Restriction::ByType {
425 type_: K::name(),
426 restriction: &restriction.borrow().restriction(),
427 },
428 )
429 }
430
431 fn description_raw(&self) -> Result<String> {
432 // Get the size of the description.
433 let mut sz = keyctl_describe(self.id, None)?;
434 // Allocate this description.
435 let mut buffer = vec![0; sz];
436 loop {
437 let write_buffer = buffer.get_backing_buffer();
438 // Fetch the description.
439 sz = keyctl_describe(self.id, Some(write_buffer))?;
440
441 // If we got everything, exit.
442 if sz <= buffer.capacity() {
443 break;
444 }
445
446 // Resize for the additional capacity we need.
447 buffer.resize(sz, 0);
448 }
449 // Remove 1 from the size for the trailing NUL the kernel adds.
450 buffer.truncate(sz.saturating_sub(1));
451 // The kernel guarantees that we get ASCII data from this.
452 let str_slice = str::from_utf8(&buffer[..]).unwrap();
453 Ok(str_slice.to_owned())
454 }
455
456 /// Retrieve metadata about the keyring.
457 ///
458 /// # Panics
459 ///
460 /// If the kernel returns malformed data, the the parser will panic.
461 pub fn description(&self) -> Result<Description> {
462 self.description_raw()
463 .and_then(|desc| Description::parse(&desc).ok_or(errno::Errno(libc::EINVAL)))
464 }
465
466 /// Set an expiration timer on the keyring to `timeout`.
467 ///
468 /// Any partial seconds are ignored. A timeout of 0 means "no expiration". Requires the
469 /// `setattr` permission on the keyring.
470 pub fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
471 keyctl_set_timeout(self.id, timeout.as_secs() as TimeoutSeconds)
472 }
473
474 /// The security context of the keyring. Depends on the security manager loaded into the kernel
475 /// (e.g., SELinux or AppArmor).
476 pub fn security(&self) -> Result<String> {
477 // Get the size of the description.
478 let mut sz = keyctl_get_security(self.id, None)?;
479 // Allocate this description.
480 let mut buffer = vec![0; sz];
481 loop {
482 let write_buffer = buffer.get_backing_buffer();
483 // Fetch the description.
484 sz = keyctl_get_security(self.id, Some(write_buffer))?;
485
486 // If we got everything, exit.
487 if sz <= buffer.capacity() {
488 break;
489 }
490
491 // Resize for the additional capacity we need.
492 buffer.resize(sz, 0);
493 }
494 // Remove 1 from the size for the trailing NUL the kernel adds.
495 buffer.truncate(sz.saturating_sub(1));
496 // The kernel guarantees that we get ASCII data from this.
497 let str_slice = str::from_utf8(&buffer[..]).unwrap();
498 Ok(str_slice.to_owned())
499 }
500
501 /// Invalidates the keyring and schedules it for removal. Requires the `search` permission on
502 /// the keyring.
503 pub fn invalidate(self) -> Result<()> {
504 keyctl_invalidate(self.id)
505 }
506}
507
508/// Representation of a kernel key.
509#[derive(Debug, Clone, PartialEq, Eq)]
510pub struct Key {
511 id: KeyringSerial,
512}
513
514/// Structure to store results from a query on optional feature support for a key.
515#[derive(Debug, Clone, Copy)]
516pub struct KeySupportInfo {
517 /// Features supported by the key.
518 pub supported_ops: KeyctlSupportFlags,
519 /// The size of the key (in bits).
520 pub key_size: u32,
521 /// The maximum size of a data blob which may be signed.
522 pub max_data_size: u16,
523 /// The maximum size of a signature blob.
524 pub max_sig_size: u16,
525 /// The maximum size of a blob to be encrypted.
526 pub max_enc_size: u16,
527 /// The maximum size of a blob to be decrypted.
528 pub max_dec_size: u16,
529}
530
531impl KeySupportInfo {
532 fn from_c(c_info: PKeyQuery) -> Self {
533 KeySupportInfo {
534 supported_ops: c_info.supported_ops,
535 key_size: c_info.key_size,
536 max_data_size: c_info.max_data_size,
537 max_sig_size: c_info.max_sig_size,
538 max_enc_size: c_info.max_enc_size,
539 max_dec_size: c_info.max_dec_size,
540 }
541 }
542}
543
544/// Encodings supported by the kernel.
545#[derive(Debug, Clone)]
546// #[non_exhaustive]
547pub enum KeyctlEncoding {
548 /// The RSASSA-PKCS1-v1.5 encoding.
549 RsassaPkcs1V15,
550 /// The RSAES-PKCS1-v1.5 encoding.
551 RsaesPkcs1V15,
552 /// The RSASSA-PSS encoding.
553 RsassaPss,
554 /// The RSAES-OAEP encoding.
555 RsaesOaep,
556 /// For extensibility.
557 OtherEncoding(Cow<'static, str>),
558}
559
560impl KeyctlEncoding {
561 fn encoding(&self) -> &str {
562 match *self {
563 KeyctlEncoding::RsassaPkcs1V15 => "pkcs1",
564 KeyctlEncoding::RsaesPkcs1V15 => "pkcs1",
565 KeyctlEncoding::RsassaPss => "pss",
566 KeyctlEncoding::RsaesOaep => "oaep",
567 KeyctlEncoding::OtherEncoding(ref s) => s,
568 }
569 }
570}
571
572/// Hashes supported by the kernel.
573#[derive(Debug, Clone)]
574// #[non_exhaustive]
575pub enum KeyctlHash {
576 /// The MD4 hash.
577 Md4,
578 /// The MD5 hash.
579 Md5,
580 /// The SHA1 hash.
581 Sha1,
582 /// The sha224 hash.
583 Sha224,
584 /// The sha256 hash.
585 Sha256,
586 /// The sha384 hash.
587 Sha384,
588 /// The sha512 hash.
589 Sha512,
590 /// The rmd128 hash.
591 RipeMd128,
592 /// The rmd160 hash.
593 RipeMd160,
594 /// The rmd256 hash.
595 RipeMd256,
596 /// The rmd320 hash.
597 RipeMd320,
598 /// The wp256 hash.
599 Wp256,
600 /// The wp384 hash.
601 Wp384,
602 /// The wp512 hash.
603 Wp512,
604 /// The tgr128 hash.
605 Tgr128,
606 /// The tgr160 hash.
607 Tgr160,
608 /// The tgr192 hash.
609 Tgr192,
610 /// The sm3-256 hash.
611 Sm3_256,
612 /// For extensibility.
613 OtherEncoding(Cow<'static, str>),
614}
615
616impl KeyctlHash {
617 fn hash(&self) -> &str {
618 match *self {
619 KeyctlHash::Md4 => "md4",
620 KeyctlHash::Md5 => "md5",
621 KeyctlHash::Sha1 => "sha1",
622 KeyctlHash::Sha224 => "sha224",
623 KeyctlHash::Sha256 => "sha256",
624 KeyctlHash::Sha384 => "sha384",
625 KeyctlHash::Sha512 => "sha512",
626 KeyctlHash::RipeMd128 => "rmd128",
627 KeyctlHash::RipeMd160 => "rmd160",
628 KeyctlHash::RipeMd256 => "rmd256",
629 KeyctlHash::RipeMd320 => "rmd320",
630 KeyctlHash::Wp256 => "wp256",
631 KeyctlHash::Wp384 => "wp384",
632 KeyctlHash::Wp512 => "wp512",
633 KeyctlHash::Tgr128 => "tgr128",
634 KeyctlHash::Tgr160 => "tgr160",
635 KeyctlHash::Tgr192 => "tgr192",
636 KeyctlHash::Sm3_256 => "sm3-256",
637 KeyctlHash::OtherEncoding(ref s) => s,
638 }
639 }
640}
641
642/// Options for output from public key functions (encryption, decryption, signing, and verifying).
643#[derive(Debug, Clone)]
644pub struct PublicKeyOptions {
645 /// The encoding of the encrypted blob or the signature.
646 pub encoding: Option<KeyctlEncoding>,
647 /// Hash algorithm to use (if the encoding uses it).
648 pub hash: Option<KeyctlHash>,
649}
650
651impl PublicKeyOptions {
652 fn info(&self) -> String {
653 let options = [
654 ("enc", self.encoding.as_ref().map(KeyctlEncoding::encoding)),
655 ("hash", self.hash.as_ref().map(KeyctlHash::hash)),
656 ]
657 .iter()
658 .map(|&(key, value)| value.map_or_else(String::new, |v| format!("{}={}", key, v)))
659 .collect::<Vec<_>>();
660 options.join(" ").trim().to_owned()
661 }
662}
663
664impl Key {
665 /// Instantiate a key from an ID.
666 ///
667 /// This is unsafe because no key is known to exist with the given ID.
668 ///
669 /// # Safety
670 ///
671 /// This method assumes that the given serial is a valid key ID at the kernel level.
672 pub unsafe fn new(id: KeyringSerial) -> Self {
673 Self::new_impl(id)
674 }
675
676 fn new_impl(id: KeyringSerial) -> Self {
677 Key {
678 id,
679 }
680 }
681
682 pub(crate) fn serial(&self) -> KeyringSerial {
683 self.id
684 }
685
686 /// Requests a key with the given type and description by searching the thread, process, and
687 /// session keyrings.
688 ///
689 /// If it is not found, the `info` string (if provided) will be handed off to
690 /// `/sbin/request-key` to generate the key.
691 ///
692 /// If `target` is given, the found keyring will be linked into it. If `target` is not given
693 /// and a new key is constructed due to the request, it will be linked into the default
694 /// keyring (see `Keyring::set_default`).
695 pub fn request<'s, 'a, K, D, I, T>(description: D, info: I, target: T) -> Result<Self>
696 where
697 K: KeyType,
698 D: Borrow<K::Description>,
699 I: Into<Option<&'s str>>,
700 T: Into<Option<TargetKeyring<'a>>>,
701 {
702 request_impl::<K>(
703 &description.borrow().description(),
704 info.into().as_ref().copied(),
705 target.into().map(TargetKeyring::serial),
706 )
707 .map(Self::new_impl)
708 }
709
710 /// Determine whether the key is of a specific implementation or not.
711 pub fn is_keytype<K>(&self) -> Result<bool>
712 where
713 K: KeyType,
714 {
715 let desc = self.description()?;
716 Ok(desc.type_ == K::name())
717 }
718
719 /// Update the payload in the key.
720 pub fn update<K, P>(&mut self, payload: P) -> Result<()>
721 where
722 K: KeyType,
723 P: Borrow<K::Payload>,
724 {
725 keyctl_update(self.id, &payload.borrow().payload())
726 }
727
728 /// Revokes the key. Requires `write` permission on the key.
729 pub fn revoke(self) -> Result<()> {
730 Keyring::new_impl(self.id).revoke()
731 }
732
733 /// Change the user which owns the key.
734 ///
735 /// Requires the `setattr` permission on the key and the SysAdmin capability to change it to
736 /// anything other than the current user.
737 pub fn chown(&mut self, uid: libc::uid_t) -> Result<()> {
738 Keyring::new_impl(self.id).chown(uid)
739 }
740
741 /// Change the group which owns the key.
742 ///
743 /// Requires the `setattr` permission on the key and the SysAdmin capability to change it to
744 /// anything other than a group of which the current user is a member.
745 pub fn chgrp(&mut self, gid: libc::gid_t) -> Result<()> {
746 Keyring::new_impl(self.id).chgrp(gid)
747 }
748
749 /// Set the permissions on the key.
750 ///
751 /// Requires the `setattr` permission on the key and the SysAdmin capability if the current
752 /// user does not own the key.
753 pub fn set_permissions(&mut self, perms: Permission) -> Result<()> {
754 Keyring::new_impl(self.id).set_permissions(perms)
755 }
756
757 #[cfg(test)]
758 pub(crate) fn set_permissions_raw(&mut self, perms: KeyPermissions) -> Result<()> {
759 Keyring::new_impl(self.id).set_permissions_raw(perms)
760 }
761
762 /// Retrieve metadata about the key.
763 ///
764 /// # Panics
765 ///
766 /// If the kernel returns malformed data, the parser will panic.
767 pub fn description(&self) -> Result<Description> {
768 Keyring::new_impl(self.id).description()
769 }
770
771 /// Read the payload of the key. Requires `read` permissions on the key.
772 pub fn read(&self) -> Result<Vec<u8>> {
773 read_impl(self.id)
774 }
775
776 /// Set an expiration timer on the keyring to `timeout`.
777 ///
778 /// Any partial seconds are ignored. A timeout of 0 means "no expiration". Requires the
779 /// `setattr` permission on the key.
780 pub fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
781 Keyring::new_impl(self.id).set_timeout(timeout)
782 }
783
784 /// The security context of the key.
785 ///
786 /// Depends on the security manager loaded into the kernel (e.g., SELinux or AppArmor).
787 pub fn security(&self) -> Result<String> {
788 Keyring::new_impl(self.id).security()
789 }
790
791 /// Invalidates the key and schedules it for removal.
792 ///
793 /// Requires the `search` permission on the key.
794 pub fn invalidate(self) -> Result<()> {
795 Keyring::new_impl(self.id).invalidate()
796 }
797
798 /// Create an object to manage a key request.
799 ///
800 /// Before a key may be managed on a thread, an authorization key must be attached to an
801 /// available thread keyring.
802 ///
803 /// Only one key may be managed on a thread at a time. Managing a second key will
804 /// invalidate any previous `KeyManager` constructions.
805 ///
806 /// See `KeyManager::request_key_auth_key`.
807 pub fn manage(&mut self) -> Result<KeyManager> {
808 keyctl_assume_authority(Some(self.id))?;
809 Ok(KeyManager::new(Key::new_impl(self.id)))
810 }
811
812 /// Compute a Diffie-Hellman prime for use as a shared secret or public key.
813 pub fn compute_dh(private: &Key, prime: &Key, base: &Key) -> Result<Vec<u8>> {
814 // Get the size of the description.
815 let mut sz = keyctl_dh_compute(private.id, prime.id, base.id, None)?;
816 // Allocate this description.
817 let mut buffer = vec![0; sz];
818 loop {
819 let write_buffer = buffer.get_backing_buffer();
820 // Fetch the description.
821 sz = keyctl_dh_compute(private.id, prime.id, base.id, Some(write_buffer))?;
822
823 // If we got everything, exit.
824 if sz <= buffer.capacity() {
825 break;
826 }
827
828 // Resize for the additional capacity we need.
829 buffer.resize(sz, 0);
830 }
831 buffer.truncate(sz);
832 Ok(buffer)
833 }
834
835 /// Compute a key from a Diffie-Hellman shared secret.
836 ///
837 /// The `base` key contains the remote public key to create a share secret which is then
838 /// processed using `hash`.
839 ///
840 /// See [SP800-56A][] for details.
841 ///
842 /// [SP800-56A]: https://csrc.nist.gov/publications/detail/sp/800-56a/revised/archive/2007-03-14
843 pub fn compute_dh_kdf<O>(
844 private: &Key,
845 prime: &Key,
846 base: &Key,
847 hash: KeyctlHash,
848 other: Option<O>,
849 ) -> Result<Vec<u8>>
850 where
851 O: AsRef<[u8]>,
852 {
853 Self::compute_dh_kdf_impl(
854 private,
855 prime,
856 base,
857 hash,
858 other.as_ref().map(AsRef::as_ref),
859 )
860 }
861
862 fn compute_dh_kdf_impl(
863 private: &Key,
864 prime: &Key,
865 base: &Key,
866 hash: KeyctlHash,
867 other: Option<&[u8]>,
868 ) -> Result<Vec<u8>> {
869 // Get the size of the description.
870 let mut sz =
871 keyctl_dh_compute_kdf(private.id, prime.id, base.id, hash.hash(), other, None)?;
872 // Allocate this description.
873 let mut buffer = vec![0; sz];
874 loop {
875 let write_buffer = buffer.get_backing_buffer();
876 // Fetch the description.
877 sz = keyctl_dh_compute_kdf(
878 private.id,
879 prime.id,
880 base.id,
881 hash.hash(),
882 other,
883 Some(write_buffer),
884 )?;
885
886 // If we got everything, exit.
887 if sz <= buffer.capacity() {
888 break;
889 }
890
891 // Resize for the additional capacity we need.
892 buffer.resize(sz, 0);
893 }
894 buffer.truncate(sz);
895 Ok(buffer)
896 }
897
898 fn pkey_query_support_impl(&self, info: &str) -> Result<PKeyQuery> {
899 keyctl_pkey_query(self.id, info)
900 }
901
902 /// Query which optionally supported features may be used by the key.
903 pub fn pkey_query_support(&self, query: &PublicKeyOptions) -> Result<KeySupportInfo> {
904 let info = query.info();
905 self.pkey_query_support_impl(&info)
906 .map(KeySupportInfo::from_c)
907 }
908
909 /// Encrypt data using the key.
910 pub fn encrypt(&self, options: &PublicKeyOptions, data: &[u8]) -> Result<Vec<u8>> {
911 let info = options.info();
912 let support = self.pkey_query_support_impl(&info)?;
913 let mut buffer = Vec::with_capacity(support.max_enc_size as usize);
914 let write_buffer = buffer.get_backing_buffer();
915 let sz = keyctl_pkey_encrypt(self.id, &info, data, write_buffer)?;
916 buffer.truncate(sz);
917 Ok(buffer)
918 }
919
920 /// Decrypt data using the key.
921 pub fn decrypt(&self, options: &PublicKeyOptions, data: &[u8]) -> Result<Vec<u8>> {
922 let info = options.info();
923 let support = self.pkey_query_support_impl(&info)?;
924 let mut buffer = Vec::with_capacity(support.max_dec_size as usize);
925 let write_buffer = buffer.get_backing_buffer();
926 let sz = keyctl_pkey_decrypt(self.id, &info, data, write_buffer)?;
927 buffer.truncate(sz);
928 Ok(buffer)
929 }
930
931 /// Sign data using the key.
932 pub fn sign(&self, options: &PublicKeyOptions, data: &[u8]) -> Result<Vec<u8>> {
933 let info = options.info();
934 let support = self.pkey_query_support_impl(&info)?;
935 let mut buffer = Vec::with_capacity(support.max_sig_size as usize);
936 let write_buffer = buffer.get_backing_buffer();
937 let sz = keyctl_pkey_sign(self.id, &info, data, write_buffer)?;
938 buffer.truncate(sz);
939 Ok(buffer)
940 }
941
942 /// Verify a signature of the data using the key.
943 pub fn verify(
944 &self,
945 options: &PublicKeyOptions,
946 data: &[u8],
947 signature: &[u8],
948 ) -> Result<bool> {
949 keyctl_pkey_verify(self.id, &options.info(), data, signature)
950 }
951}
952
953/// Structure representing the metadata about a key or keyring.
954#[derive(Debug, Clone)]
955pub struct Description {
956 /// The type of the key.
957 pub type_: String,
958 /// The user owner of the key.
959 pub uid: libc::uid_t,
960 /// The group owner of the key.
961 pub gid: libc::gid_t,
962 /// The permissions of the key.
963 pub perms: Permission,
964 /// The plaintext description of the key.
965 pub description: String,
966}
967
968impl Description {
969 fn parse(desc: &str) -> Option<Description> {
970 let mut pieces = desc.split(';').collect::<Vec<_>>();
971 // Reverse the string because the kernel plans to extend it by adding fields to the
972 // beginning of the string. By doing this, the fields are at a constant position in the
973 // split string.
974 pieces.reverse();
975 let len = pieces.len();
976 if len < 5 {
977 None
978 } else {
979 if len > 5 {
980 error!(
981 "New fields detected! Please report this upstream to \
982 https://github.com/mathstuf/rust-keyutils: {}",
983 desc,
984 );
985 }
986 let bits = KeyPermissions::from_str_radix(pieces[1], 16).unwrap();
987 if Permission::from_bits(bits).is_none() {
988 error!(
989 "New permission bits detected! Please report this upstream to \
990 https://github.com/mathstuf/rust-keyutils: {}",
991 bits,
992 );
993 }
994 Some(Description {
995 type_: pieces[4].to_owned(),
996 uid: pieces[3].parse::<libc::uid_t>().unwrap(),
997 gid: pieces[2].parse::<libc::gid_t>().unwrap(),
998 perms: Permission::from_bits_truncate(bits),
999 description: pieces[0].to_owned(),
1000 })
1001 }
1002 }
1003}
1004
1005/// The destination keyring of an instantiation request.
1006#[derive(Debug)]
1007pub enum TargetKeyring<'a> {
1008 /// A special keyring.
1009 Special(SpecialKeyring),
1010 /// A specific keyring.
1011 Keyring(&'a mut Keyring),
1012}
1013
1014impl<'a> TargetKeyring<'a> {
1015 fn serial(self) -> KeyringSerial {
1016 match self {
1017 TargetKeyring::Special(special) => special.serial(),
1018 TargetKeyring::Keyring(keyring) => keyring.id,
1019 }
1020 }
1021}
1022
1023impl<'a> From<SpecialKeyring> for TargetKeyring<'a> {
1024 fn from(special: SpecialKeyring) -> Self {
1025 TargetKeyring::Special(special)
1026 }
1027}
1028
1029impl<'a> From<&'a mut Keyring> for TargetKeyring<'a> {
1030 fn from(keyring: &'a mut Keyring) -> Self {
1031 TargetKeyring::Keyring(keyring)
1032 }
1033}
1034
1035impl<'a> From<SpecialKeyring> for Option<TargetKeyring<'a>> {
1036 fn from(special: SpecialKeyring) -> Self {
1037 Some(special.into())
1038 }
1039}
1040
1041impl<'a> From<&'a mut Keyring> for Option<TargetKeyring<'a>> {
1042 fn from(keyring: &'a mut Keyring) -> Self {
1043 Some(keyring.into())
1044 }
1045}
1046
1047/// A manager for a key to respond to instantiate a key request by the kernel.
1048#[derive(Debug, PartialEq, Eq)]
1049pub struct KeyManager {
1050 key: Key,
1051}
1052
1053impl KeyManager {
1054 fn new(key: Key) -> Self {
1055 KeyManager {
1056 key,
1057 }
1058 }
1059
1060 #[cfg(test)]
1061 pub(crate) fn test_new(key: Key) -> Self {
1062 Self::new(key)
1063 }
1064
1065 /// Requests the authorization key created by `request_key`.
1066 ///
1067 /// This key must be present in an available keyring before `Key::manage` may be called.
1068 pub fn request_key_auth_key(create: bool) -> Result<Key> {
1069 keyctl_get_keyring_id(KEY_SPEC_REQKEY_AUTH_KEY, create).map(Key::new_impl)
1070 }
1071
1072 /// Drop authority for the current thread.
1073 ///
1074 /// This invalidates
1075 pub fn drop_authority() -> Result<()> {
1076 keyctl_assume_authority(None)
1077 }
1078
1079 /// Instantiate the key with the given payload.
1080 pub fn instantiate<'a, T, P>(self, keyring: T, payload: P) -> Result<()>
1081 where
1082 T: Into<Option<TargetKeyring<'a>>>,
1083 P: AsRef<[u8]>,
1084 {
1085 keyctl_instantiate(
1086 self.key.id,
1087 payload.as_ref(),
1088 keyring.into().map(TargetKeyring::serial),
1089 )
1090 }
1091
1092 /// Reject the key with the given `error`.
1093 ///
1094 /// Requests for the key will fail until `timeout` has elapsed (partial
1095 /// seconds are ignored). This is to prevent a denial-of-service by
1096 /// requesting a non-existant key repeatedly. The requester must have
1097 /// `write` permission on the keyring.
1098 pub fn reject<'a, T>(self, keyring: T, timeout: Duration, error: errno::Errno) -> Result<()>
1099 where
1100 T: Into<Option<TargetKeyring<'a>>>,
1101 {
1102 keyctl_reject(
1103 self.key.id,
1104 timeout.as_secs() as TimeoutSeconds,
1105 error,
1106 keyring.into().map(TargetKeyring::serial),
1107 )
1108 }
1109
1110 /// Reject the key with `ENOKEY`.
1111 ///
1112 /// Requests for the key will fail until `timeout` has elapsed (partial
1113 /// seconds are ignored). This is to prevent a denial-of-service by
1114 /// requesting a non-existant key repeatedly. The requester must have
1115 /// `write` permission on the keyring.
1116 pub fn negate<'a, T>(self, keyring: T, timeout: Duration) -> Result<()>
1117 where
1118 T: Into<Option<TargetKeyring<'a>>>,
1119 {
1120 keyctl_negate(
1121 self.key.id,
1122 timeout.as_secs() as TimeoutSeconds,
1123 keyring.into().map(TargetKeyring::serial),
1124 )
1125 }
1126}