/* 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/. */ extern crate cose; use std::slice; use cose::decoder::decode_signature; use cose::SignatureAlgorithm; use std::os::raw; unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec { slice::from_raw_parts(ptr, len).to_vec() } type VerifyCallback = extern "C" fn(*const u8, /* payload */ usize, /* payload len */ *const *const u8, /* cert_chain */ usize, /* # certs */ *const usize, /* cert lengths in cert_chain */ *const u8, /* signer cert */ usize, /* signer cert len */ *const u8, /* signature bytes */ usize, /* signature len */ u8, /* signature algorithm */ *const raw::c_void /* some context of the app */) -> bool; #[no_mangle] pub extern "C" fn verify_cose_signature_ffi( payload: *const u8, payload_len: usize, cose_signature: *const u8, cose_signature_len: usize, ctx: *const raw::c_void, verify_callback: VerifyCallback, ) -> bool { if payload.is_null() || cose_signature.is_null() || payload_len == 0 || cose_signature_len == 0 { return false; } // Build Rust variables from C parameters. let payload = unsafe { from_raw(payload, payload_len) }; let cose_signature = unsafe { from_raw(cose_signature, cose_signature_len) }; // Parse the incoming signature. let cose_signatures = decode_signature(&cose_signature, &payload); let cose_signatures = match cose_signatures { Ok(signatures) => signatures, Err(_) => Vec::new(), }; if cose_signatures.len() == 0 { return false; } return cose_signatures.into_iter().all(|cose_signature| { let signature_type = cose_signature.signature_type; // ES256 = 0, ES384 = 1, ES512 = 2, PS256 = 3 let signature_type = match signature_type { SignatureAlgorithm::ES256 => 0, SignatureAlgorithm::ES384 => 1, SignatureAlgorithm::ES512 => 2, SignatureAlgorithm::PS256 => 3, }; let signature_bytes = cose_signature.signature; let real_payload = cose_signature.to_verify; // Build cert chain params. let certs: Vec<_> = cose_signature.certs.iter().map(|c| c.as_ptr()).collect(); let cert_lens: Vec<_> = cose_signature.certs.iter().map(|c| c.len()).collect(); // Call callback to verify the parsed signatures. verify_callback( real_payload.as_ptr(), real_payload.len(), certs.as_ptr(), certs.len(), cert_lens.as_ptr(), cose_signature.signer_cert.as_ptr(), cose_signature.signer_cert.len(), signature_bytes.as_ptr(), signature_bytes.len(), signature_type, ctx, ) }); }