Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  hkdf.rs   Sprache: unbekannt

 
use super::{
    super::hpke::{Aead, Kdf},
    p11::{
        sys::{
            self, CKA_DERIVE, CKF_HKDF_SALT_DATA, CKF_HKDF_SALT_NULL, CKM_AES_GCM,
            CKM_CHACHA20_POLY1305, CKM_HKDF_DATA, CKM_HKDF_DERIVE, CKM_SHA256, CK_BBOOL,
            CK_HKDF_PARAMS, CK_INVALID_HANDLE, CK_MECHANISM_TYPE, CK_OBJECT_HANDLE, CK_ULONG,
        },
        ParamItem, SymKey,
    },
};
use crate::err::Res;
use log::trace;
use std::{convert::TryFrom, os::raw::c_int, ptr::null_mut};

#[derive(Clone, Copy)]
pub enum KeyMechanism {
    Aead(Aead),
    #[allow(dead_code)] // We don't use this one.
    Hkdf,
}

impl KeyMechanism {
    fn mech(self) -> CK_MECHANISM_TYPE {
        CK_MECHANISM_TYPE::from(match self {
            Self::Aead(Aead::Aes128Gcm) | Self::Aead(Aead::Aes256Gcm) => CKM_AES_GCM,
            Self::Aead(Aead::ChaCha20Poly1305) => CKM_CHACHA20_POLY1305,
            Self::Hkdf => CKM_HKDF_DERIVE,
        })
    }

    fn len(self) -> usize {
        match self {
            Self::Aead(a) => a.n_k(),
            Self::Hkdf => 0, // Let the underlying module decide.
        }
    }
}

pub struct Hkdf {
    kdf: Kdf,
}

impl Hkdf {
    pub fn new(kdf: Kdf) -> Self {
        Self { kdf }
    }

    #[cfg(test)]
    pub fn import_ikm(ikm: &[u8]) -> Res<SymKey> {
        let slot = super::p11::Slot::internal()?;
        let ptr = unsafe {
            sys::PK11_ImportSymKey(
                *slot,
                CK_MECHANISM_TYPE::from(sys::CKM_HKDF_KEY_GEN),
                sys::PK11Origin::PK11_OriginUnwrap,
                sys::CK_ATTRIBUTE_TYPE::from(sys::CKA_SIGN),
                &mut super::p11::Item::wrap(ikm),
                null_mut(),
            )
        };
        SymKey::from_ptr(ptr)
    }

    fn mech(&self) -> CK_MECHANISM_TYPE {
        CK_MECHANISM_TYPE::from(match self.kdf {
            Kdf::HkdfSha256 => CKM_SHA256,
            _ => unimplemented!(),
        })
    }

    pub fn extract(&self, salt: &[u8], ikm: &SymKey) -> Res<SymKey> {
        let salt_type = if salt.is_empty() {
            CKF_HKDF_SALT_NULL
        } else {
            CKF_HKDF_SALT_DATA
        };
        let mut params = CK_HKDF_PARAMS {
            bExtract: CK_BBOOL::from(true),
            bExpand: CK_BBOOL::from(false),
            prfHashMechanism: self.mech(),
            ulSaltType: CK_ULONG::from(salt_type),
            pSalt: salt.as_ptr() as *mut _, // const-cast = bad API
            ulSaltLen: CK_ULONG::try_from(salt.len()).unwrap(),
            hSaltKey: CK_OBJECT_HANDLE::from(CK_INVALID_HANDLE),
            pInfo: null_mut(),
            ulInfoLen: 0,
        };
        let mut params_item = ParamItem::new(&mut params);
        let ptr = unsafe {
            sys::PK11_Derive(
                **ikm,
                CK_MECHANISM_TYPE::from(CKM_HKDF_DERIVE),
                params_item.ptr(),
                CK_MECHANISM_TYPE::from(CKM_HKDF_DERIVE),
                CK_MECHANISM_TYPE::from(CKA_DERIVE),
                0,
            )
        };

        let prk = SymKey::from_ptr(ptr)?;
        trace!(
            "HKDF extract: salt={} ikm={} prk={}",
            hex::encode(salt),
            hex::encode(ikm.key_data()?),
            hex::encode(prk.key_data()?),
        );
        Ok(prk)
    }

    // NB: `info` must outlive the returned value.
    fn expand_params(&self, info: &[u8]) -> CK_HKDF_PARAMS {
        CK_HKDF_PARAMS {
            bExtract: CK_BBOOL::from(false),
            bExpand: CK_BBOOL::from(true),
            prfHashMechanism: self.mech(),
            ulSaltType: CK_ULONG::from(CKF_HKDF_SALT_NULL),
            pSalt: null_mut(),
            ulSaltLen: 0,
            hSaltKey: CK_OBJECT_HANDLE::from(CK_INVALID_HANDLE),
            pInfo: info.as_ptr() as *mut _, // const-cast = bad API
            ulInfoLen: CK_ULONG::try_from(info.len()).unwrap(),
        }
    }

    pub fn expand_key(&self, prk: &SymKey, info: &[u8], key_mech: KeyMechanism) -> Res<SymKey> {
        let mut params = self.expand_params(info);
        let mut params_item = ParamItem::new(&mut params);
        let ptr = unsafe {
            sys::PK11_Derive(
                **prk,
                CK_MECHANISM_TYPE::from(CKM_HKDF_DERIVE),
                params_item.ptr(),
                key_mech.mech(),
                CK_MECHANISM_TYPE::from(CKA_DERIVE),
                c_int::try_from(key_mech.len()).unwrap(),
            )
        };
        let okm = SymKey::from_ptr(ptr)?;
        trace!(
            "HKDF expand_key: prk={} info={} okm={}",
            hex::encode(prk.key_data()?),
            hex::encode(info),
            hex::encode(okm.key_data()?),
        );
        Ok(okm)
    }

    pub fn expand_data(&self, prk: &SymKey, info: &[u8], len: usize) -> Res<Vec<u8>> {
        let mut params = self.expand_params(info);
        let mut params_item = ParamItem::new(&mut params);
        let ptr = unsafe {
            sys::PK11_Derive(
                **prk,
                CK_MECHANISM_TYPE::from(CKM_HKDF_DATA),
                params_item.ptr(),
                CK_MECHANISM_TYPE::from(CKM_HKDF_DERIVE),
                CK_MECHANISM_TYPE::from(CKA_DERIVE),
                c_int::try_from(len).unwrap(),
            )
        };
        let k = SymKey::from_ptr(ptr)?;
        let r = Vec::from(k.key_data()?);
        trace!(
            "HKDF expand_data: prk={} info={} okm={}",
            hex::encode(prk.key_data()?),
            hex::encode(info),
            hex::encode(&r),
        );
        Ok(r)
    }
}

#[cfg(test)]
mod test {
    use super::{super::super::hpke::Kdf, Hkdf};
    use crate::init;

    fn sha256_example(
        ikm: &[u8],
        salt: &[u8],
        info: &[u8],
        l: usize,
        expected_prk: &[u8],
        expected_okm: &[u8],
    ) {
        init();
        let hkdf = Hkdf::new(Kdf::HkdfSha256);
        let k_ikm = Hkdf::import_ikm(ikm).unwrap();
        let prk = hkdf.extract(salt, &k_ikm).unwrap();
        let prk_data = prk.key_data().unwrap();
        assert_eq!(prk_data, expected_prk);

        let out = hkdf.expand_data(&prk, info, l).unwrap();
        assert_eq!(&out[..], expected_okm);
    }

    /// Example 1 from <https://tools.ietf.org/html/rfc5869#appendix-A.1>
    #[test]
    fn example1() {
        const IKM: &[u8] = &[
            0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
            0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
        ];
        const SALT: &[u8] = &[
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
        ];
        const INFO: &[u8] = &[0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9];
        const L: usize = 42;
        const PRK: &[u8] = &[
            0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b,
            0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a,
            0xd7, 0xc2, 0xb3, 0xe5,
        ];
        const OKM: &[u8] = &[
            0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36,
            0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56,
            0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65,
        ];
        sha256_example(IKM, SALT, INFO, L, PRK, OKM);
    }

    /// Example 2 from <https://tools.ietf.org/html/rfc5869#appendix-A.2>
    #[test]
    fn example2() {
        const IKM: &[u8] = &[
            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
            0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
            0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
            0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
            0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
            0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
        ];
        const SALT: &[u8] = &[
            0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d,
            0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b,
            0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
            0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
            0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
            0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
        ];
        const INFO: &[u8] = &[
            0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd,
            0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
            0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
            0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
            0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
            0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
        ];
        const L: usize = 82;
        const PRK: &[u8] = &[
            0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35,
            0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, 0x4a, 0x19, 0x3f, 0x40,
            0xc1, 0x5f, 0xc2, 0x44,
        ];
        const OKM: &[u8] = &[
            0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a,
            0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c,
            0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb,
            0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8,
            0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec,
            0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87,
        ];
        sha256_example(IKM, SALT, INFO, L, PRK, OKM);
    }

    /// Example 3 from <https://tools.ietf.org/html/rfc5869#appendix-A.3>
    #[test]
    fn example3() {
        const IKM: &[u8] = &[
            0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
            0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
        ];
        const SALT: &[u8] = &[];
        const INFO: &[u8] = &[];
        const L: usize = 42;
        const PRK: &[u8] = &[
            0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64,
            0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c,
            0x29, 0x3c, 0xcb, 0x04,
        ];
        const OKM: &[u8] = &[
            0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c,
            0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f,
            0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8,
        ];
        sha256_example(IKM, SALT, INFO, L, PRK, OKM);
    }
}

[ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge