Packages

Elixir NIF wrapper for `gpgme`.

Retired package: Deprecated - This package is no longer maintained

Current section

Files

Jump to
ex_openssl native exopenssl src crypto pkcs7 mod.rs
Raw

native/exopenssl/src/crypto/pkcs7/mod.rs

#![allow(deprecated)]
pub mod smime;
use openssl::symm::Cipher;
use openssl::crypto::pkcs7::pk7_smime::PKCS7;
use rustler::{Env, Term, TermType, NifResult, Encoder, Error};
use rustler::types::atom::Atom;
use crate::symm::cipher::decode_cypher;
use crate::crypto::x509::decode_stack;
use crate::crypto::x509::decode_store;
use crate::errors::to_term as error_stack_to_term;
use rustler::resource::ResourceArc;
use crate::pkey::PKeyResource;
use openssl::pkey::PKey;
use crate::crypto::x509::X509Resource;
use openssl::x509::X509;
use openssl::crypto::pkcs7::pk7_smime;
use openssl::crypto::pkcs7::pk7_smime::PKCS7Flags;
use std::ops::Deref;
mod atoms {
rustler::rustler_atoms! {
atom ok;
atom error;
}
}
pub struct PKCS7Resource {
pub pkcs7: PKCS7,
}
unsafe impl Send for PKCS7Resource {}
unsafe impl Sync for PKCS7Resource {}
pub fn pkcs7_to_resource(pkcs7: PKCS7) -> ResourceArc<PKCS7Resource> {
ResourceArc::new(PKCS7Resource {
pkcs7: pkcs7,
})
}
pub fn decode_flag(flag: &Atom, env: Env) -> NifResult<PKCS7Flags> {
let flag: String = flag.to_term(env).atom_to_string()?;
match flag.as_str() {
"text" => Ok(pk7_smime::PKCS7_TEXT),
"nocerts" => Ok(pk7_smime::PKCS7_NOCERTS),
"nosigs" => Ok(pk7_smime::PKCS7_NOSIGS),
"nochain" => Ok(pk7_smime::PKCS7_NOCHAIN),
"nointern" => Ok(pk7_smime::PKCS7_NOINTERN),
"noverify" => Ok(pk7_smime::PKCS7_NOVERIFY),
"detached" => Ok(pk7_smime::PKCS7_DETACHED),
"binary" => Ok(pk7_smime::PKCS7_BINARY),
"noattr" => Ok(pk7_smime::PKCS7_NOATTR),
"nosmimecap" => Ok(pk7_smime::PKCS7_NOSMIMECAP),
"nooldmimetype" => Ok(pk7_smime::PKCS7_NOOLDMIMETYPE),
"crlfeol" => Ok(pk7_smime::PKCS7_CRLFEOL),
"stream" => Ok(pk7_smime::PKCS7_STREAM),
"nocrl" => Ok(pk7_smime::PKCS7_NOCRL),
"partial" => Ok(pk7_smime::PKCS7_PARTIAL),
"reuse_digest" => Ok(pk7_smime::PKCS7_REUSE_DIGEST),
// "no_dual_content" => Ok(pk7_smime::PKCS7_NO_DUAL_CONTENT),
_ => Err(Error::BadArg)
}
}
pub fn decode_flags(flags: Vec<Atom>, env: Env) -> NifResult<PKCS7Flags> {
flags
.iter()
.fold(Ok(PKCS7Flags::empty()), | acc, term | {
match acc {
Ok(flags) => Ok(flags | decode_flag(term, env)?),
Err(err) => Err(err)
}
})
}
pub fn encrypt<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
match decode_stack(args[0].decode()?) {
Ok(certs) => {
let input: String = args[1].decode()?;
let cipher: Cipher = decode_cypher(args[2].decode()?, env)?;
if args[3].decode::<Vec<Atom>>()?.len() < 1 {
return Err(Error::BadArg);
}
let flags: PKCS7Flags = decode_flags(args[3].decode()?, env)?;
match PKCS7::encrypt(&certs, input.as_bytes(), cipher, flags) {
Ok(pkcs7) => Ok((atoms::ok(), pkcs7_to_resource(pkcs7)).encode(env)),
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
},
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
}
pub fn decrypt<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
let pkcs7_arc: ResourceArc<PKCS7Resource> = args[0].decode()?;
let pkcs7 = &pkcs7_arc.deref().pkcs7;
let pkey_arc: ResourceArc<PKeyResource> = args[1].decode()?;
let pkey: &PKey = &pkey_arc.key;
let cert_arc: ResourceArc<X509Resource> = args[2].decode()?;
let cert: &X509 = &cert_arc.cert;
match PKCS7::decrypt(&pkcs7, pkey, cert) {
Ok(decrypted) => {
Ok((atoms::ok(), decrypted).encode(env))
}
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
}
pub fn sign<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
let sign_cert_arc: ResourceArc<X509Resource> = args[0].decode()?;
let sign_cert = &sign_cert_arc.cert;
let pkey_arc: ResourceArc<PKeyResource> = args[1].decode()?;
let pkey: &PKey = &pkey_arc.key;
match decode_stack(args[2].decode()?) {
Ok(certs) => {
let input: String = args[3].decode()?;
if args[4].decode::<Vec<Atom>>()?.len() < 1 {
return Err(Error::BadArg);
}
let flags: PKCS7Flags = decode_flags(args[4].decode()?, env)?;
match PKCS7::sign(sign_cert, pkey, &certs, input.as_bytes(), flags) {
Ok(pkcs7) => Ok((atoms::ok(), pkcs7_to_resource(pkcs7)).encode(env)),
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
},
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
}
pub fn verify<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
let pkcs7_arc: ResourceArc<PKCS7Resource> = args[0].decode()?;
let pkcs7 = &pkcs7_arc.deref().pkcs7;
if args[4].decode::<Vec<Atom>>()?.len() < 1 {
return Err(Error::BadArg);
}
let flags: PKCS7Flags = decode_flags(args[4].decode()?, env)?;
let mut out: Vec<u8> = Vec::new();
match decode_stack(args[1].decode()?) {
Ok(certs) => {
match decode_store(args[2].decode()?) {
Ok(store) => {
let data_term: Term = args[3].decode()?;
match data_term.get_type() {
TermType::Atom => {
match data_term.atom_to_string()?.as_str() {
"nil" => {
match pkcs7.verify(&certs, &store, None, Some(&mut out), flags) {
Ok(_) => Ok((atoms::ok(), (true, out)).encode(env)),
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
}
_ => Err(Error::BadArg)
}
},
TermType::Binary => {
let bcount: &[u8] = data_term.into_binary()?.as_slice();
match pkcs7.verify(&certs, &store, Some(bcount), Some(&mut out), flags) {
Ok(_) => Ok((atoms::ok(), (true, out)).encode(env)),
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
},
_ => Err(Error::BadArg)
}
},
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
},
Err(errors) => Ok((atoms::error(), error_stack_to_term(errors, env)).encode(env))
}
}