summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cose-c/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/cose-c/src/lib.rs')
-rw-r--r--third_party/rust/cose-c/src/lib.rs89
1 files changed, 89 insertions, 0 deletions
diff --git a/third_party/rust/cose-c/src/lib.rs b/third_party/rust/cose-c/src/lib.rs
new file mode 100644
index 0000000000..695d7908f8
--- /dev/null
+++ b/third_party/rust/cose-c/src/lib.rs
@@ -0,0 +1,89 @@
+/* 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<u8> {
+ 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,
+ )
+ });
+}