nss/
cert.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::error::*;
use crate::pk11::types::{Certificate, PublicKey};
use crate::util::{ensure_nss_initialized, sec_item_as_slice, ScopedPtr};
use nss_sys::{CERT_ExtractPublicKey, CERT_GetDefaultCertDB, CERT_NewTempCertificate};

pub fn extract_ec_public_key(der: &[u8]) -> Result<Vec<u8>> {
    ensure_nss_initialized();

    let certdb = unsafe { CERT_GetDefaultCertDB() };
    let mut data = nss_sys::SECItem {
        len: u32::try_from(der.len())?,
        data: der.as_ptr() as *mut u8,
        type_: nss_sys::SECItemType::siBuffer as u32,
    };

    let cert = unsafe {
        Certificate::from_ptr(CERT_NewTempCertificate(
            certdb,
            &mut data,
            std::ptr::null_mut(),
            nss_sys::PR_FALSE,
            nss_sys::PR_TRUE,
        ))?
    };

    let pub_key = unsafe { PublicKey::from_ptr(CERT_ExtractPublicKey(cert.as_mut_ptr()))? };
    let pub_key_raw = unsafe { &*pub_key.as_ptr() };

    if pub_key_raw.keyType != nss_sys::KeyType::ecKey as u32 {
        return Err(
            ErrorKind::InputError("public key is not of type EC (Elliptic Curve).".into()).into(),
        );
    }

    let mut pub_key_data = unsafe { pub_key_raw.u.ec.publicValue };
    let pub_key_data_raw = unsafe { sec_item_as_slice(&mut pub_key_data)? };

    Ok(pub_key_data_raw.to_vec())
}