|
24 | 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25 | 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26 | 26 |
|
27 |
| -use std::borrow::Borrow; |
| 27 | +use std::borrow::{Borrow, Cow}; |
28 | 28 | use std::convert::TryInto;
|
29 | 29 | use std::mem;
|
30 | 30 | use std::result;
|
@@ -511,6 +511,76 @@ pub struct Key {
|
511 | 511 | id: KeyringSerial,
|
512 | 512 | }
|
513 | 513 |
|
| 514 | +/// Hashes supported by the kernel. |
| 515 | +#[derive(Debug, Clone)] |
| 516 | +// #[non_exhaustive] |
| 517 | +pub enum KeyctlHash { |
| 518 | + /// The MD4 hash. |
| 519 | + Md4, |
| 520 | + /// The MD5 hash. |
| 521 | + Md5, |
| 522 | + /// The SHA1 hash. |
| 523 | + Sha1, |
| 524 | + /// The sha224 hash. |
| 525 | + Sha224, |
| 526 | + /// The sha256 hash. |
| 527 | + Sha256, |
| 528 | + /// The sha384 hash. |
| 529 | + Sha384, |
| 530 | + /// The sha512 hash. |
| 531 | + Sha512, |
| 532 | + /// The rmd128 hash. |
| 533 | + RipeMd128, |
| 534 | + /// The rmd160 hash. |
| 535 | + RipeMd160, |
| 536 | + /// The rmd256 hash. |
| 537 | + RipeMd256, |
| 538 | + /// The rmd320 hash. |
| 539 | + RipeMd320, |
| 540 | + /// The wp256 hash. |
| 541 | + Wp256, |
| 542 | + /// The wp384 hash. |
| 543 | + Wp384, |
| 544 | + /// The wp512 hash. |
| 545 | + Wp512, |
| 546 | + /// The tgr128 hash. |
| 547 | + Tgr128, |
| 548 | + /// The tgr160 hash. |
| 549 | + Tgr160, |
| 550 | + /// The tgr192 hash. |
| 551 | + Tgr192, |
| 552 | + /// The sm3-256 hash. |
| 553 | + Sm3_256, |
| 554 | + /// For extensibility. |
| 555 | + OtherEncoding(Cow<'static, str>), |
| 556 | +} |
| 557 | + |
| 558 | +impl KeyctlHash { |
| 559 | + fn hash(&self) -> &str { |
| 560 | + match *self { |
| 561 | + KeyctlHash::Md4 => "md4", |
| 562 | + KeyctlHash::Md5 => "md5", |
| 563 | + KeyctlHash::Sha1 => "sha1", |
| 564 | + KeyctlHash::Sha224 => "sha224", |
| 565 | + KeyctlHash::Sha256 => "sha256", |
| 566 | + KeyctlHash::Sha384 => "sha384", |
| 567 | + KeyctlHash::Sha512 => "sha512", |
| 568 | + KeyctlHash::RipeMd128 => "rmd128", |
| 569 | + KeyctlHash::RipeMd160 => "rmd160", |
| 570 | + KeyctlHash::RipeMd256 => "rmd256", |
| 571 | + KeyctlHash::RipeMd320 => "rmd320", |
| 572 | + KeyctlHash::Wp256 => "wp256", |
| 573 | + KeyctlHash::Wp384 => "wp384", |
| 574 | + KeyctlHash::Wp512 => "wp512", |
| 575 | + KeyctlHash::Tgr128 => "tgr128", |
| 576 | + KeyctlHash::Tgr160 => "tgr160", |
| 577 | + KeyctlHash::Tgr192 => "tgr192", |
| 578 | + KeyctlHash::Sm3_256 => "sm3-256", |
| 579 | + KeyctlHash::OtherEncoding(ref s) => &s, |
| 580 | + } |
| 581 | + } |
| 582 | +} |
| 583 | + |
514 | 584 | impl Key {
|
515 | 585 | /// Instantiate a key from an ID.
|
516 | 586 | ///
|
@@ -681,6 +751,69 @@ impl Key {
|
681 | 751 | buffer.truncate(sz);
|
682 | 752 | Ok(buffer)
|
683 | 753 | }
|
| 754 | + |
| 755 | + /// Compute a key from a Diffie-Hellman shared secret. |
| 756 | + /// |
| 757 | + /// The `base` key contains the remote public key to create a share secret which is then |
| 758 | + /// processed using `hash`. |
| 759 | + /// |
| 760 | + /// See [SP800-56A][] for details. |
| 761 | + /// |
| 762 | + /// [SP800-56A]: https://csrc.nist.gov/publications/detail/sp/800-56a/revised/archive/2007-03-14 |
| 763 | + pub fn compute_dh_kdf<O>( |
| 764 | + private: &Key, |
| 765 | + prime: &Key, |
| 766 | + base: &Key, |
| 767 | + hash: KeyctlHash, |
| 768 | + other: Option<O>, |
| 769 | + ) -> Result<Vec<u8>> |
| 770 | + where |
| 771 | + O: AsRef<[u8]>, |
| 772 | + { |
| 773 | + Self::compute_dh_kdf_impl( |
| 774 | + private, |
| 775 | + prime, |
| 776 | + base, |
| 777 | + hash, |
| 778 | + other.as_ref().map(AsRef::as_ref), |
| 779 | + ) |
| 780 | + } |
| 781 | + |
| 782 | + fn compute_dh_kdf_impl( |
| 783 | + private: &Key, |
| 784 | + prime: &Key, |
| 785 | + base: &Key, |
| 786 | + hash: KeyctlHash, |
| 787 | + other: Option<&[u8]>, |
| 788 | + ) -> Result<Vec<u8>> { |
| 789 | + // Get the size of the description. |
| 790 | + let mut sz = |
| 791 | + keyctl_dh_compute_kdf(private.id, prime.id, base.id, hash.hash(), other, None)?; |
| 792 | + // Allocate this description. |
| 793 | + let mut buffer = vec![0; sz]; |
| 794 | + loop { |
| 795 | + let write_buffer = buffer.get_backing_buffer(); |
| 796 | + // Fetch the description. |
| 797 | + sz = keyctl_dh_compute_kdf( |
| 798 | + private.id, |
| 799 | + prime.id, |
| 800 | + base.id, |
| 801 | + hash.hash(), |
| 802 | + other, |
| 803 | + Some(write_buffer), |
| 804 | + )?; |
| 805 | + |
| 806 | + // If we got everything, exit. |
| 807 | + if sz <= buffer.capacity() { |
| 808 | + break; |
| 809 | + } |
| 810 | + |
| 811 | + // Resize for the additional capacity we need. |
| 812 | + buffer.resize(sz, 0); |
| 813 | + } |
| 814 | + buffer.truncate(sz); |
| 815 | + Ok(buffer) |
| 816 | + } |
684 | 817 | }
|
685 | 818 |
|
686 | 819 | /// Structure representing the metadata about a key or keyring.
|
|
0 commit comments