Skip to main content

wacore_libsignal/protocol/state/
bundle.rs

1//
2// Copyright 2020 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use std::clone::Clone;
7
8use crate::protocol::state::{PreKeyId, SignedPreKeyId};
9use crate::protocol::{DeviceId, IdentityKey, PublicKey, Result, SignalProtocolError};
10
11#[derive(Clone)]
12struct SignedPreKey {
13    id: SignedPreKeyId,
14    public_key: PublicKey,
15    signature: Vec<u8>,
16}
17
18impl SignedPreKey {
19    fn new(id: SignedPreKeyId, public_key: PublicKey, signature: Vec<u8>) -> Self {
20        Self {
21            id,
22            public_key,
23            signature,
24        }
25    }
26}
27
28// Represents the raw contents of the pre-key bundle without any notion of required/optional
29// fields.
30// Can be used as a "builder" for PreKeyBundle, in which case all the validation will happen in
31// PreKeyBundle::new.
32pub struct PreKeyBundleContent {
33    pub registration_id: Option<u32>,
34    pub device_id: Option<DeviceId>,
35    pub pre_key_id: Option<PreKeyId>,
36    pub pre_key_public: Option<PublicKey>,
37    pub ec_pre_key_id: Option<SignedPreKeyId>,
38    pub ec_pre_key_public: Option<PublicKey>,
39    pub ec_pre_key_signature: Option<Vec<u8>>,
40    pub identity_key: Option<IdentityKey>,
41}
42
43impl From<PreKeyBundle> for PreKeyBundleContent {
44    fn from(bundle: PreKeyBundle) -> Self {
45        Self {
46            registration_id: Some(bundle.registration_id),
47            device_id: Some(bundle.device_id),
48            pre_key_id: bundle.pre_key_id,
49            pre_key_public: bundle.pre_key_public,
50            ec_pre_key_id: Some(bundle.ec_signed_pre_key.id),
51            ec_pre_key_public: Some(bundle.ec_signed_pre_key.public_key),
52            ec_pre_key_signature: Some(bundle.ec_signed_pre_key.signature),
53            identity_key: Some(bundle.identity_key),
54        }
55    }
56}
57
58impl TryFrom<PreKeyBundleContent> for PreKeyBundle {
59    type Error = SignalProtocolError;
60
61    fn try_from(content: PreKeyBundleContent) -> Result<Self> {
62        let bundle = PreKeyBundle::new(
63            content.registration_id.ok_or_else(|| {
64                SignalProtocolError::InvalidArgument("registration_id is required".to_string())
65            })?,
66            content.device_id.ok_or_else(|| {
67                SignalProtocolError::InvalidArgument("device_id is required".to_string())
68            })?,
69            content.pre_key_id.zip(content.pre_key_public),
70            content.ec_pre_key_id.ok_or_else(|| {
71                SignalProtocolError::InvalidArgument("signed_pre_key_id is required".to_string())
72            })?,
73            content.ec_pre_key_public.ok_or_else(|| {
74                SignalProtocolError::InvalidArgument(
75                    "signed_pre_key_public is required".to_string(),
76                )
77            })?,
78            content.ec_pre_key_signature.ok_or_else(|| {
79                SignalProtocolError::InvalidArgument(
80                    "signed_pre_key_signature is required".to_string(),
81                )
82            })?,
83            content.identity_key.ok_or_else(|| {
84                SignalProtocolError::InvalidArgument("identity_key is required".to_string())
85            })?,
86        )?;
87
88        Ok(bundle)
89    }
90}
91
92#[derive(Clone)]
93pub struct PreKeyBundle {
94    registration_id: u32,
95    device_id: DeviceId,
96    pre_key_id: Option<PreKeyId>,
97    pre_key_public: Option<PublicKey>,
98    ec_signed_pre_key: SignedPreKey,
99    identity_key: IdentityKey,
100}
101
102impl PreKeyBundle {
103    pub fn new(
104        registration_id: u32,
105        device_id: DeviceId,
106        pre_key: Option<(PreKeyId, PublicKey)>,
107        signed_pre_key_id: SignedPreKeyId,
108        signed_pre_key_public: PublicKey,
109        signed_pre_key_signature: Vec<u8>,
110        identity_key: IdentityKey,
111    ) -> Result<Self> {
112        let (pre_key_id, pre_key_public) = match pre_key {
113            None => (None, None),
114            Some((id, key)) => (Some(id), Some(key)),
115        };
116
117        let ec_signed_pre_key = SignedPreKey::new(
118            signed_pre_key_id,
119            signed_pre_key_public,
120            signed_pre_key_signature,
121        );
122
123        Ok(Self {
124            registration_id,
125            device_id,
126            pre_key_id,
127            pre_key_public,
128            ec_signed_pre_key,
129            identity_key,
130        })
131    }
132
133    pub fn registration_id(&self) -> Result<u32> {
134        Ok(self.registration_id)
135    }
136
137    pub fn device_id(&self) -> Result<DeviceId> {
138        Ok(self.device_id)
139    }
140
141    pub fn pre_key_id(&self) -> Result<Option<PreKeyId>> {
142        Ok(self.pre_key_id)
143    }
144
145    pub fn pre_key_public(&self) -> Result<Option<PublicKey>> {
146        Ok(self.pre_key_public)
147    }
148
149    pub fn signed_pre_key_id(&self) -> Result<SignedPreKeyId> {
150        Ok(self.ec_signed_pre_key.id)
151    }
152
153    pub fn signed_pre_key_public(&self) -> Result<PublicKey> {
154        Ok(self.ec_signed_pre_key.public_key)
155    }
156
157    pub fn signed_pre_key_signature(&self) -> Result<&[u8]> {
158        Ok(self.ec_signed_pre_key.signature.as_ref())
159    }
160
161    pub fn identity_key(&self) -> Result<&IdentityKey> {
162        Ok(&self.identity_key)
163    }
164
165    pub fn modify<F>(self, modify: F) -> Result<Self>
166    where
167        F: FnOnce(&mut PreKeyBundleContent),
168    {
169        let mut content = self.into();
170        modify(&mut content);
171        content.try_into()
172    }
173}