diff options
author | Neal H. Walfield <neal@pep.foundation> | 2020-06-17 14:50:21 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2020-06-17 15:05:39 +0200 |
commit | caa2801b87cb055c2a2fe27c67c3e13cd44fc71d (patch) | |
tree | 7f80a63c7125852f604e81de3b6ad7756d097564 /openpgp-ffi/src | |
parent | cd20d026549c26ef81a7ebc53abf7ed1b7b4764e (diff) |
openpgp-ffi: Wrap the password handling functionality.
- Wrap functions to create a password-protected
certificate (`pgp_cert_builder_set_password`), and to work with
keys that are password
protected (`pgp_key_has_unencrypted_secret`,
`pgp_key_decrypt_secret`).
Diffstat (limited to 'openpgp-ffi/src')
-rw-r--r-- | openpgp-ffi/src/cert.rs | 17 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/key.rs | 94 |
2 files changed, 110 insertions, 1 deletions
diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs index b2e8a576..c1040c11 100644 --- a/openpgp-ffi/src/cert.rs +++ b/openpgp-ffi/src/cert.rs @@ -13,6 +13,7 @@ use libc::{c_char, c_int, size_t, time_t}; extern crate sequoia_openpgp as openpgp; use self::openpgp::{ crypto, + crypto::Password, types::ReasonForRevocation, parse::{ PacketParserResult, @@ -963,6 +964,22 @@ pub extern "C" fn pgp_cert_builder_set_cipher_suite *certb = box_raw!(certb_); } +/// Sets the password for primary and all subkeys. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_cert_builder_set_password + (certb: *mut *mut CertBuilder, password: *const u8, password_len: size_t) +{ + let certb = ffi_param_ref_mut!(certb); + let certb_ = ffi_param_move!(*certb); + assert!(!password.is_null()); + let password = unsafe { + slice::from_raw_parts(password, password_len as usize) + }; + let password: Password = password.into(); + let certb_ = certb_.set_password(Some(password)); + *certb = box_raw!(certb_); +} + /// Adds a new user ID. The first user ID added replaces the default /// ID that is just the empty string. /// diff --git a/openpgp-ffi/src/packet/key.rs b/openpgp-ffi/src/packet/key.rs index 6966acc1..088c3325 100644 --- a/openpgp-ffi/src/packet/key.rs +++ b/openpgp-ffi/src/packet/key.rs @@ -4,10 +4,12 @@ //! //! [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5 -use libc::{c_int, time_t}; +use libc::{c_int, time_t, size_t}; +use std::slice; extern crate sequoia_openpgp as openpgp; use self::openpgp::packet::key; +use self::openpgp::crypto::Password; use super::super::fingerprint::Fingerprint; use super::super::keyid::KeyID; @@ -85,3 +87,93 @@ fn pgp_key_into_key_pair(errp: Option<&mut *mut crate::error::Error>, let key = ffi_try!(key.move_from_raw().parts_into_secret()); ffi_try_box!(key.into_keypair()) } + +/// Returns whether the secret key material is unencrypted. +/// +/// Returns false if there is no secret key material. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" +fn pgp_key_has_unencrypted_secret(key: *const Key) -> bool +{ + let key = key.ref_raw(); + key.has_unencrypted_secret() +} + +/// Decrypts the secret key material. +/// +/// `password` is a byte array. `password_len` is its length. +/// +/// Returns NULL if there is no secret key material, or the password +/// is incorrect. +/// +/// This function takes ownership of `key`. On failure, `key` is +/// deallocated. +/// +/// # Example +/// +/// ```c +/// #include <assert.h> +/// #include <sequoia/openpgp.h> +/// +/// pgp_cert_builder_t builder; +/// pgp_cert_t cert; +/// pgp_signature_t revocation; +/// pgp_key_t encrypted_primary_key; +/// pgp_key_t primary_key; +/// pgp_key_pair_t primary_keypair; +/// const uint8_t password[] = "foobar"; +/// const size_t password_len = strlen ((char *) password); +/// +/// builder = pgp_cert_builder_new (); +/// pgp_cert_builder_set_cipher_suite (&builder, PGP_CERT_CIPHER_SUITE_CV25519); +/// pgp_cert_builder_set_password (&builder, password, password_len); +/// pgp_cert_builder_generate (NULL, builder, &cert, &revocation); +/// assert (cert); +/// assert (revocation); +/// pgp_signature_free (revocation); /* Free the generated one. */ +/// +/// encrypted_primary_key = pgp_cert_primary_key (cert); +/// assert(! pgp_key_has_unencrypted_secret (encrypted_primary_key)); +/// +/// // This will fail, because primary_key is password protected. +/// primary_keypair +/// = pgp_key_into_key_pair (NULL, pgp_key_clone (encrypted_primary_key)); +/// assert(! primary_keypair); +/// +/// // Try decrypting it with the wrong password. +/// primary_key +/// = pgp_key_decrypt_secret (NULL, pgp_key_clone (encrypted_primary_key), +/// password, password_len - 1); +/// assert(! primary_key); +/// +/// // If we decrypt it, then we can create a keypair. +/// primary_key +/// = pgp_key_decrypt_secret (NULL, pgp_key_clone (encrypted_primary_key), +/// password, password_len); +/// assert(primary_key); +/// assert(pgp_key_has_unencrypted_secret (primary_key)); +/// +/// primary_keypair +/// = pgp_key_into_key_pair (NULL, pgp_key_clone (primary_key)); +/// assert(primary_keypair); +/// +/// pgp_key_pair_free(primary_keypair); +/// pgp_key_free (primary_key); +/// pgp_key_free (encrypted_primary_key); +/// pgp_cert_free (cert); +/// ``` +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" +fn pgp_key_decrypt_secret(errp: Option<&mut *mut crate::error::Error>, + key: *mut Key, + password: *const u8, password_len: size_t) + -> *mut Key +{ + ffi_make_fry_from_errp!(errp); + assert!(!password.is_null()); + let password = unsafe { + slice::from_raw_parts(password, password_len as usize) + }; + let password: Password = password.into(); + let key = ffi_try!(key.move_from_raw().parts_into_secret()); + + ffi_try!(key.decrypt_secret(&password)).parts_into_unspecified().move_into_raw() +} |