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}