wolfcose 0.1.0

Safe Rust API for wolfSSL wolfCOSE.
use crate::raw;

/// CBOR major type.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct CborMajorType(u8);

impl CborMajorType {
    /// Unsigned integer.
    pub const UINT: Self = Self(raw::WOLFCOSE_CBOR_UINT as u8);
    /// Negative integer.
    pub const NEGATIVE_INT: Self = Self(raw::WOLFCOSE_CBOR_NEGINT as u8);
    /// Byte string.
    pub const BYTES: Self = Self(raw::WOLFCOSE_CBOR_BSTR as u8);
    /// Text string.
    pub const TEXT: Self = Self(raw::WOLFCOSE_CBOR_TSTR as u8);
    /// Array.
    pub const ARRAY: Self = Self(raw::WOLFCOSE_CBOR_ARRAY as u8);
    /// Map.
    pub const MAP: Self = Self(raw::WOLFCOSE_CBOR_MAP as u8);
    /// Semantic tag.
    pub const TAG: Self = Self(raw::WOLFCOSE_CBOR_TAG as u8);
    /// Simple value or float.
    pub const SIMPLE: Self = Self(raw::WOLFCOSE_CBOR_SIMPLE as u8);

    /// Convert from a raw major type value.
    pub fn from_raw(value: u8) -> Option<Self> {
        if value <= raw::WOLFCOSE_CBOR_SIMPLE as u8 {
            Some(Self(value))
        } else {
            None
        }
    }

    /// Raw major type value.
    pub fn raw(self) -> u8 {
        self.0
    }
}

/// COSE algorithm identifier.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Algorithm(i32);

/// Broad COSE algorithm family.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum AlgorithmClass {
    /// Signature algorithm.
    Signature,
    /// Content encryption algorithm.
    Encryption,
    /// Message authentication algorithm.
    Mac,
    /// Key management algorithm.
    KeyManagement,
    /// Unknown or unset algorithm.
    Unknown,
}

/// Intended COSE use for an algorithm.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum AlgorithmUse {
    /// Signing or signature verification.
    Sign,
    /// Content encryption or decryption.
    Encrypt,
    /// MAC creation or verification.
    Mac,
    /// Recipient key management.
    KeyManagement,
}

impl Algorithm {
    /// No algorithm selected.
    pub const UNSET: Self = Self(0);
    /// ECDSA w/ SHA-256.
    pub const ES256: Self = Self(raw::WOLFCOSE_ALG_ES256);
    /// ECDSA w/ SHA-384.
    pub const ES384: Self = Self(raw::WOLFCOSE_ALG_ES384);
    /// ECDSA w/ SHA-512.
    pub const ES512: Self = Self(raw::WOLFCOSE_ALG_ES512);
    /// EdDSA.
    pub const EDDSA: Self = Self(raw::WOLFCOSE_ALG_EDDSA);
    /// RSA-PSS w/ SHA-256.
    pub const PS256: Self = Self(raw::WOLFCOSE_ALG_PS256);
    /// RSA-PSS w/ SHA-384.
    pub const PS384: Self = Self(raw::WOLFCOSE_ALG_PS384);
    /// RSA-PSS w/ SHA-512.
    pub const PS512: Self = Self(raw::WOLFCOSE_ALG_PS512);
    /// AES-128-GCM.
    pub const A128GCM: Self = Self(raw::WOLFCOSE_ALG_A128GCM as i32);
    /// AES-192-GCM.
    pub const A192GCM: Self = Self(raw::WOLFCOSE_ALG_A192GCM as i32);
    /// AES-256-GCM.
    pub const A256GCM: Self = Self(raw::WOLFCOSE_ALG_A256GCM as i32);
    /// HMAC SHA-256 with 256-bit tag.
    pub const HMAC256: Self = Self(raw::WOLFCOSE_ALG_HMAC_256_256 as i32);
    /// HMAC SHA-384 with 384-bit tag.
    pub const HMAC384: Self = Self(raw::WOLFCOSE_ALG_HMAC_384_384 as i32);
    /// HMAC SHA-512 with 512-bit tag.
    pub const HMAC512: Self = Self(raw::WOLFCOSE_ALG_HMAC_512_512 as i32);
    /// ChaCha20-Poly1305.
    pub const CHACHA20_POLY1305: Self = Self(raw::WOLFCOSE_ALG_CHACHA20_POLY1305 as i32);
    /// AES-CCM-16-64-128.
    pub const AES_CCM_16_64_128: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_16_64_128 as i32);
    /// AES-CCM-16-64-256.
    pub const AES_CCM_16_64_256: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_16_64_256 as i32);
    /// AES-CCM-64-64-128.
    pub const AES_CCM_64_64_128: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_64_64_128 as i32);
    /// AES-CCM-64-64-256.
    pub const AES_CCM_64_64_256: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_64_64_256 as i32);
    /// AES-CCM-16-128-128.
    pub const AES_CCM_16_128_128: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_16_128_128 as i32);
    /// AES-CCM-16-128-256.
    pub const AES_CCM_16_128_256: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_16_128_256 as i32);
    /// AES-CCM-64-128-128.
    pub const AES_CCM_64_128_128: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_64_128_128 as i32);
    /// AES-CCM-64-128-256.
    pub const AES_CCM_64_128_256: Self = Self(raw::WOLFCOSE_ALG_AES_CCM_64_128_256 as i32);
    /// AES-CBC-MAC 128-bit key, 64-bit tag.
    pub const AES_MAC_128_64: Self = Self(raw::WOLFCOSE_ALG_AES_MAC_128_64 as i32);
    /// AES-CBC-MAC 256-bit key, 64-bit tag.
    pub const AES_MAC_256_64: Self = Self(raw::WOLFCOSE_ALG_AES_MAC_256_64 as i32);
    /// AES-CBC-MAC 128-bit key, 128-bit tag.
    pub const AES_MAC_128_128: Self = Self(raw::WOLFCOSE_ALG_AES_MAC_128_128 as i32);
    /// AES-CBC-MAC 256-bit key, 128-bit tag.
    pub const AES_MAC_256_128: Self = Self(raw::WOLFCOSE_ALG_AES_MAC_256_128 as i32);
    /// AES-128 key wrap.
    pub const A128KW: Self = Self(raw::WOLFCOSE_ALG_A128KW);
    /// AES-192 key wrap.
    pub const A192KW: Self = Self(raw::WOLFCOSE_ALG_A192KW);
    /// AES-256 key wrap.
    pub const A256KW: Self = Self(raw::WOLFCOSE_ALG_A256KW);
    /// Direct key use.
    pub const DIRECT: Self = Self(raw::WOLFCOSE_ALG_DIRECT);
    /// ECDH-ES HKDF-256.
    pub const ECDH_ES_HKDF_256: Self = Self(raw::WOLFCOSE_ALG_ECDH_ES_HKDF_256);
    /// ECDH-ES HKDF-512.
    pub const ECDH_ES_HKDF_512: Self = Self(raw::WOLFCOSE_ALG_ECDH_ES_HKDF_512);
    /// ECDH-SS HKDF-256.
    pub const ECDH_SS_HKDF_256: Self = Self(raw::WOLFCOSE_ALG_ECDH_SS_HKDF_256);
    /// ECDH-SS HKDF-512.
    pub const ECDH_SS_HKDF_512: Self = Self(raw::WOLFCOSE_ALG_ECDH_SS_HKDF_512);
    /// ECDH-ES AES-128 key wrap.
    pub const ECDH_ES_A128KW: Self = Self(raw::WOLFCOSE_ALG_ECDH_ES_A128KW);
    /// ECDH-ES AES-192 key wrap.
    pub const ECDH_ES_A192KW: Self = Self(raw::WOLFCOSE_ALG_ECDH_ES_A192KW);
    /// ECDH-ES AES-256 key wrap.
    pub const ECDH_ES_A256KW: Self = Self(raw::WOLFCOSE_ALG_ECDH_ES_A256KW);
    /// ML-DSA-44.
    pub const ML_DSA_44: Self = Self(raw::WOLFCOSE_ALG_ML_DSA_44);
    /// ML-DSA-65.
    pub const ML_DSA_65: Self = Self(raw::WOLFCOSE_ALG_ML_DSA_65);
    /// ML-DSA-87.
    pub const ML_DSA_87: Self = Self(raw::WOLFCOSE_ALG_ML_DSA_87);

    /// Build an algorithm from a raw COSE ID.
    pub const fn from_id(id: i32) -> Self {
        Self(id)
    }

    /// Raw COSE algorithm identifier.
    pub const fn id(self) -> i32 {
        self.0
    }

    /// Broad algorithm family.
    pub const fn class(self) -> AlgorithmClass {
        match self {
            Self::ES256
            | Self::ES384
            | Self::ES512
            | Self::EDDSA
            | Self::PS256
            | Self::PS384
            | Self::PS512
            | Self::ML_DSA_44
            | Self::ML_DSA_65
            | Self::ML_DSA_87 => AlgorithmClass::Signature,
            Self::A128GCM
            | Self::A192GCM
            | Self::A256GCM
            | Self::CHACHA20_POLY1305
            | Self::AES_CCM_16_64_128
            | Self::AES_CCM_16_64_256
            | Self::AES_CCM_64_64_128
            | Self::AES_CCM_64_64_256
            | Self::AES_CCM_16_128_128
            | Self::AES_CCM_16_128_256
            | Self::AES_CCM_64_128_128
            | Self::AES_CCM_64_128_256 => AlgorithmClass::Encryption,
            Self::HMAC256
            | Self::HMAC384
            | Self::HMAC512
            | Self::AES_MAC_128_64
            | Self::AES_MAC_256_64
            | Self::AES_MAC_128_128
            | Self::AES_MAC_256_128 => AlgorithmClass::Mac,
            Self::A128KW
            | Self::A192KW
            | Self::A256KW
            | Self::DIRECT
            | Self::ECDH_ES_HKDF_256
            | Self::ECDH_ES_HKDF_512
            | Self::ECDH_SS_HKDF_256
            | Self::ECDH_SS_HKDF_512
            | Self::ECDH_ES_A128KW
            | Self::ECDH_ES_A192KW
            | Self::ECDH_ES_A256KW => AlgorithmClass::KeyManagement,
            _ => AlgorithmClass::Unknown,
        }
    }

    /// Whether this is a signing algorithm.
    pub const fn is_signing(self) -> bool {
        matches!(self.class(), AlgorithmClass::Signature)
    }

    /// Whether this is a content encryption algorithm.
    pub const fn is_encryption(self) -> bool {
        matches!(self.class(), AlgorithmClass::Encryption)
    }

    /// Whether this is a MAC algorithm.
    pub const fn is_mac(self) -> bool {
        matches!(self.class(), AlgorithmClass::Mac)
    }

    /// Whether this is a key management algorithm.
    pub const fn is_key_management(self) -> bool {
        matches!(self.class(), AlgorithmClass::KeyManagement)
    }

    /// Expected key size in bits for symmetric algorithms, where fixed.
    pub const fn key_bits_hint(self) -> Option<usize> {
        match self {
            Self::A128GCM
            | Self::AES_CCM_16_64_128
            | Self::AES_CCM_64_64_128
            | Self::AES_CCM_16_128_128
            | Self::AES_CCM_64_128_128
            | Self::AES_MAC_128_64
            | Self::AES_MAC_128_128
            | Self::A128KW => Some(128),
            Self::A192GCM | Self::A192KW => Some(192),
            Self::A256GCM
            | Self::CHACHA20_POLY1305
            | Self::AES_CCM_16_64_256
            | Self::AES_CCM_64_64_256
            | Self::AES_CCM_16_128_256
            | Self::AES_CCM_64_128_256
            | Self::AES_MAC_256_64
            | Self::AES_MAC_256_128
            | Self::A256KW
            | Self::HMAC256 => Some(256),
            Self::HMAC384 => Some(384),
            Self::HMAC512 => Some(512),
            _ => None,
        }
    }

    /// Expected IV length in bytes for common content encryption algorithms.
    pub const fn iv_len_hint(self) -> Option<usize> {
        match self {
            Self::A128GCM | Self::A192GCM | Self::A256GCM | Self::CHACHA20_POLY1305 => Some(12),
            _ => None,
        }
    }
}

/// COSE key type.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct KeyType(i32);

impl KeyType {
    /// Octet key pair.
    pub const OKP: Self = Self(raw::WOLFCOSE_KTY_OKP as i32);
    /// Elliptic curve key pair.
    pub const EC2: Self = Self(raw::WOLFCOSE_KTY_EC2 as i32);
    /// RSA key.
    pub const RSA: Self = Self(raw::WOLFCOSE_KTY_RSA as i32);
    /// Symmetric key.
    pub const SYMMETRIC: Self = Self(raw::WOLFCOSE_KTY_SYMMETRIC as i32);

    /// Raw key type.
    pub const fn id(self) -> i32 {
        self.0
    }

    /// Build from a raw COSE key type ID.
    pub const fn from_id(id: i32) -> Self {
        Self(id)
    }
}

/// COSE curve identifier.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Curve(i32);

impl Curve {
    /// NIST P-256.
    pub const P256: Self = Self(raw::WOLFCOSE_CRV_P256 as i32);
    /// NIST P-384.
    pub const P384: Self = Self(raw::WOLFCOSE_CRV_P384 as i32);
    /// NIST P-521.
    pub const P521: Self = Self(raw::WOLFCOSE_CRV_P521 as i32);
    /// Ed25519.
    pub const ED25519: Self = Self(raw::WOLFCOSE_CRV_ED25519 as i32);
    /// Ed448.
    pub const ED448: Self = Self(raw::WOLFCOSE_CRV_ED448 as i32);
    /// ML-DSA-44.
    pub const ML_DSA_44: Self = Self(raw::WOLFCOSE_CRV_ML_DSA_44);
    /// ML-DSA-65.
    pub const ML_DSA_65: Self = Self(raw::WOLFCOSE_CRV_ML_DSA_65);
    /// ML-DSA-87.
    pub const ML_DSA_87: Self = Self(raw::WOLFCOSE_CRV_ML_DSA_87);

    /// Raw curve identifier.
    pub const fn id(self) -> i32 {
        self.0
    }

    /// Build from a raw COSE curve ID.
    pub const fn from_id(id: i32) -> Self {
        Self(id)
    }
}