fido2-rs 0.1.0

Rust bindings to Yubico fido2
use crate::error::FidoError;
use openssl::ec::EcKey;
use openssl::pkey::{PKey, Public};
use std::ptr::NonNull;

macro_rules! impl_key {
    (
        type CType = $ctype:ty;
        fn new = $new:expr;
        $(fn from<$t:ty> = $from:expr;)*
        fn drop = $drop:expr;

        pub struct $ty:ident;
    ) => {
        pub struct $ty(NonNull<$ctype>);

        $(impl TryFrom<$t> for $ty {
            type Error = FidoError;

            fn try_from(value: $t) -> Result<Self, Self::Error> {
                use foreign_types::ForeignType;

                unsafe {
                    let pk = $new();
                    crate::utils::check($from(pk, value.as_ptr() as _))?;

                    Ok($ty(NonNull::new_unchecked(pk)))
                }
            }
        })*

        impl Drop for $ty {
            fn drop(&mut self) {
                let mut ptr = self.0.as_ptr();
                unsafe {
                    $drop(&mut ptr);
                }

                let _ = std::mem::replace(&mut self.0, NonNull::dangling());
            }
        }

        impl $ty {
            pub(crate) fn as_ptr(&self) -> *const $ctype {
                self.0.as_ptr()
            }
        }
    };
}

impl_key! {
    type CType = ffi::eddsa_pk_t;
    fn new = ffi::eddsa_pk_new;
    fn from<PKey<Public>> = ffi::eddsa_pk_from_EVP_PKEY;
    fn drop = ffi::eddsa_pk_free;

    pub struct Eddsa;
}

impl_key! {
    type CType = ffi::rs256_pk_t;
    fn new = ffi::rs256_pk_new;
    fn from<PKey<Public>> = ffi::rs256_pk_from_EVP_PKEY;
    fn drop = ffi::rs256_pk_free;

    pub struct Rsa;
}

impl_key! {
    type CType = ffi::es256_pk_t;
    fn new = ffi::es256_pk_new;
    fn from<EcKey<Public>> = ffi::es256_pk_from_EC_KEY;
    fn drop = ffi::es256_pk_free;

    pub struct ES256;
}

impl_key! {
    type CType = ffi::es384_pk_t;
    fn new = ffi::es384_pk_new;
    fn from<EcKey<Public>> = ffi::es384_pk_from_EC_KEY;
    fn drop = ffi::es384_pk_free;

    pub struct ES384;
}