libsignal_protocol/messages/
signal_message.rs1use crate::{
2 errors::InternalError,
3 keys::PublicKey,
4 messages::{CiphertextMessage, CiphertextType},
5 raw_ptr::Raw,
6 Context, ContextInner,
7};
8use failure::Error;
9use std::{convert::TryFrom, rc::Rc};
10
11#[allow(unused_imports)]
13use crate::keys::IdentityKeyPair;
14
15#[derive(Debug, Clone)]
17pub struct SignalMessage {
18 pub(crate) raw: Raw<sys::signal_message>,
19 pub(crate) _ctx: Rc<ContextInner>,
20}
21
22impl SignalMessage {
23 pub fn is_legacy(msg: &[u8]) -> bool {
25 unsafe { sys::signal_message_is_legacy(msg.as_ptr(), msg.len()) != 0 }
26 }
27
28 pub fn sender_ratchet_key(&self) -> PublicKey {
30 unsafe {
31 let raw = sys::signal_message_get_sender_ratchet_key(
32 self.raw.as_const_ptr(),
33 );
34 PublicKey {
35 raw: Raw::copied_from(raw),
36 }
37 }
38 }
39
40 pub fn message_version(&self) -> u8 {
42 unsafe {
43 sys::signal_message_get_message_version(self.raw.as_const_ptr())
44 }
45 }
46
47 pub fn counter(&self) -> u32 {
49 unsafe { sys::signal_message_get_counter(self.raw.as_const_ptr()) }
50 }
51
52 pub fn body(&self) -> &[u8] {
54 unsafe {
55 let buffer = sys::signal_message_get_body(self.raw.as_const_ptr());
56 assert!(!buffer.is_null());
57
58 let len = sys::signal_buffer_len(buffer);
59 let data = sys::signal_buffer_data(buffer);
60
61 std::slice::from_raw_parts(data, len)
62 }
63 }
64
65 pub fn verify_mac(
67 &self,
68 sender_identity_key: &PublicKey,
69 receiver_identity_key: &PublicKey,
70 mac: &[u8],
71 ctx: &Context,
72 ) -> Result<bool, InternalError> {
73 unsafe {
74 let code = sys::signal_message_verify_mac(
75 self.raw.as_ptr(),
76 sender_identity_key.raw.as_ptr(),
77 receiver_identity_key.raw.as_ptr(),
78 mac.as_ptr(),
79 mac.len(),
80 ctx.raw(),
81 );
82
83 match code {
84 0 => Ok(false),
85 1 => Ok(true),
86 other => Err(InternalError::from_error_code(other)
87 .unwrap_or(InternalError::Unknown)),
88 }
89 }
90 }
91}
92
93impl TryFrom<CiphertextMessage> for SignalMessage {
94 type Error = Error;
95
96 fn try_from(other: CiphertextMessage) -> Result<Self, Self::Error> {
97 if other.get_type()? != CiphertextType::Signal {
98 Err(failure::err_msg("Expected a signal message"))
99 } else {
100 let raw = unsafe {
103 Raw::copied_from(other.raw.as_ptr() as *mut sys::signal_message)
104 };
105 Ok(SignalMessage {
106 raw,
107 _ctx: other._ctx,
108 })
109 }
110 }
111}
112
113impl From<SignalMessage> for CiphertextMessage {
114 fn from(other: SignalMessage) -> CiphertextMessage {
115 CiphertextMessage {
116 raw: other.raw.upcast(),
117 _ctx: other._ctx,
118 }
119 }
120}
121
122impl_is_a!(sys::signal_message => sys::ciphertext_message);