Skip to main content

cosec/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5extern crate cose;
6
7use std::slice;
8use cose::decoder::decode_signature;
9use cose::SignatureAlgorithm;
10use std::os::raw;
11
12unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
13    slice::from_raw_parts(ptr, len).to_vec()
14}
15
16type VerifyCallback = extern "C" fn(*const u8, /* payload */
17                                    usize, /* payload len */
18                                    *const *const u8, /* cert_chain */
19                                    usize, /* # certs */
20                                    *const usize, /* cert lengths in cert_chain */
21                                    *const u8, /* signer cert */
22                                    usize, /* signer cert len */
23                                    *const u8, /* signature bytes */
24                                    usize, /* signature len */
25                                    u8, /* signature algorithm */
26                                    *const raw::c_void /* some context of the app */)
27                                    -> bool;
28
29#[no_mangle]
30pub extern "C" fn verify_cose_signature_ffi(
31    payload: *const u8,
32    payload_len: usize,
33    cose_signature: *const u8,
34    cose_signature_len: usize,
35    ctx: *const raw::c_void,
36    verify_callback: VerifyCallback,
37) -> bool {
38    if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
39        cose_signature_len == 0
40    {
41        return false;
42    }
43
44    // Build Rust variables from C parameters.
45    let payload = unsafe { from_raw(payload, payload_len) };
46    let cose_signature = unsafe { from_raw(cose_signature, cose_signature_len) };
47
48    // Parse the incoming signature.
49    let cose_signatures = decode_signature(&cose_signature, &payload);
50    let cose_signatures = match cose_signatures {
51        Ok(signatures) => signatures,
52        Err(_) => Vec::new(),
53    };
54    if cose_signatures.len() == 0 {
55        return false;
56    }
57
58    return cose_signatures.into_iter().all(|cose_signature| {
59        let signature_type = cose_signature.signature_type;
60        // ES256 = 0, ES384 = 1, ES512 = 2, PS256 = 3
61        let signature_type = match signature_type {
62            SignatureAlgorithm::ES256 => 0,
63            SignatureAlgorithm::ES384 => 1,
64            SignatureAlgorithm::ES512 => 2,
65            SignatureAlgorithm::PS256 => 3,
66        };
67        let signature_bytes = cose_signature.signature;
68        let real_payload = cose_signature.to_verify;
69
70        // Build cert chain params.
71        let certs: Vec<_> = cose_signature.certs.iter().map(|c| c.as_ptr()).collect();
72        let cert_lens: Vec<_> = cose_signature.certs.iter().map(|c| c.len()).collect();
73
74        // Call callback to verify the parsed signatures.
75        verify_callback(
76            real_payload.as_ptr(),
77            real_payload.len(),
78            certs.as_ptr(),
79            certs.len(),
80            cert_lens.as_ptr(),
81            cose_signature.signer_cert.as_ptr(),
82            cose_signature.signer_cert.len(),
83            signature_bytes.as_ptr(),
84            signature_bytes.len(),
85            signature_type,
86            ctx,
87        )
88    });
89}