Commit Graph

277 Commits

Author SHA1 Message Date
Jordan Rose
47a142fde8 protocol: Generialize has_usable_sender_chain checking
It can now also check whether a session was established with PQXDH and
whether it's using SPQR.
2025-07-31 09:42:15 -07:00
Alex Bakon
e4972e9fa5 Use zerocopy to skip fallible unwraps 2025-07-21 13:42:04 -04:00
Jordan Rose
95612be1ba Remove some crates from our build
- arrayref can be replaced by split_first_chunk -- not quite as
  concisely, but actually a little safer, and no macros involved

- array-concat has an equivalent in const_str

- num_enum has already been replaced by derive_more

- The test using regex has been removed
2025-07-15 15:45:03 -07:00
Jordan Rose
2879220e93 Require Kyber keys/ciphertexts throughout all XDH APIs 2025-06-13 16:06:07 -07:00
Jordan Rose
69bb363840 protocol: Reject X3DH PreKey messages
- Drop X3DH tests

- Drop cross-version tests with libsignal v0.12 and v0.21

- Change session benchmarks to use PQXDH, which is relevant if doing
  comparisons before/after this commit.
2025-06-13 12:19:04 -07:00
Alex Bakon
02b786b07e Limit device ID to the range 1-127
This is already required for sealed sender messages and enforced by the server.
2025-06-13 14:18:16 -04:00
gram-signal
b7b8040e3a Integrate post-quantum ratchet SPQR.
This PR integrates a post-quantum ratchet (SPQR) into libsignal, using an API that maintains its own internal chain and provides per-message keys.  In doing so, it also aims to be fully backwards-compatible with current clients and stored session state.

## Backwards compatibility with current clients

Remote clients that connect to us or that we connect to may not have this integration.  If they don't, their SignalMessage wire format should still deserialize, and in doing so we'll receive an empty pq_ratchet field.  SQPR handles this internally, by downgrading the protocol version to "version 0" or "don't do anything".  Note that should we eventually want to disallow this, we can do so via increasing the `min_version` field passed into the SQPR init functions to V1.  This is also the method by which we would upgrade SQPR from v1 to a future v2, etc.

## Opt-in

The publicly facing API calls for this now expose an explicit opt-in via a passed-in `use_pq_ratchet` bool (and associated enums in language-specific APIs).  If false, they default to SQPR `v0`, IE: none.  If true, they try to set up SPQR on new sessions, but will downgrade if the remote party cannot or will not do the same.
2025-06-04 11:18:12 -07:00
Alex Bakon
8a9e18b6c6 Remove unused #[allow], replace with #[expect] 2025-06-03 16:07:06 -04:00
Alex Bakon
b56f448167 Remove some #[allow]s by addressing them 2025-06-03 16:04:36 -04:00
Alex Bakon
7ea82a72b9 Bump MSRV to 1.83.0 2025-05-30 17:32:04 -04:00
Alex Bakon
151c96e52b Apply lint fixes from latest clippy 2025-05-23 10:29:25 -04:00
Jordan Rose
7d1cacbaa8 protocol: Eagerly promote sessions during pre-key processing
This fixes a bug introduced by cd36118 where starting a new session
locally would prevent incoming messages on a previous session from
being decrypted if that session hadn't advanced past the "pre-key"
stage. Fix this by promoting the session *before* successful
decryption instead of after; since we won't *save* the promotion
unless the message decrypts successfully, there's ultimately no change
in either the failure or success cases *except* when hitting this bug.
2025-05-14 16:52:18 -07:00
Jordan Rose
ac99c0950d protocol: Dump sessions on a PreKey decryption failure, just in case
Logging change only.
2025-05-14 16:52:18 -07:00
Alex Bakon
2f1112c999 Persist pre-key message sender identity after message decryption 2025-04-29 16:19:55 -04:00
Alex Bakon
13b2b8aff4 Take RNG as a parameter when generating kyber keys 2025-04-29 10:54:21 -04:00
Alex Bakon
076e9dd34f Return an error on kyber en-/de-capsulation failure 2025-04-29 09:49:47 -04:00
Alex Bakon
00ca3f4fd8 Replace pqclean crate usages with libcrux 2025-04-29 09:22:09 -04:00
Alex Bakon
8f1baf561c Use an enum value for IdentityKeyStore.saveIdentity in libraries 2025-04-25 12:52:58 -04:00
Alex Bakon
aeb2f2a561 Bump rand dependency to 0.9 2025-04-24 13:12:56 -04:00
Alex Bakon
f6aacba338 Remove num_enum dependency 2025-04-23 15:57:25 -04:00
Alex Bakon
9392062a7e Return enum from IdentityKeyStore::save_identity 2025-04-23 09:16:51 -04:00
Jordan Rose
3a2c29277e cargo update, update to zerocopy 0.8
Held back for MSRV:
- base64ct v1.6.0
- half v2.4.1
- home v0.5.9
- litemap v0.7.4
- zerofrom v0.1.5 (and zerofrom-derive)
2025-04-07 11:14:54 -07:00
Alex Bakon
03a739a95c Use const_str::hex instead of hex_literal::hex 2025-03-28 14:48:19 -04:00
Jordan Rose
cd361186fb Don't bother trying to decrypt a PreKey message with older sessions
Co-authored-by: Rolfe Schmidt <rolfe@signal.org>
2025-03-28 10:39:33 -07:00
gram-signal
39f1e2a32e Store seeds for chains rather than generated key material. 2025-02-28 13:39:59 -08:00
Alex Bakon
2a6ebecb40 Upgrade nightly Rust compiler to 2025-02-25 2025-02-26 14:08:50 -05:00
Alex Bakon
86c0ffe1df Use derive_more instead of a few more manual impls 2025-01-17 13:02:42 -05:00
Alex Bakon
063db29a30 Use derive_more crate's From/Into 2025-01-14 11:47:32 -05:00
Alex Bakon
9d6c2acec9 Avoid heap allocations when decrypting SSv2 2025-01-06 11:44:24 -05:00
Jordan Rose
0b47709e98 Sink EC key types from libsignal_protocol to libsignal_core::curve
This is necessarily a breaking change because the EC key operations
can no longer return SignalProtocolError. However, the types are still
exported through libsignal_protocol, and SignalProtocolError
implements From<CurveError>, so hopefully any clients will be guided
to update to the new usage.

Other changes:

- PublicKey::public_key_bytes no longer uses Result; any future curve
  types will also need to keep their public key in a borrowable form.

- PublicKey::verify_signature also no longer uses Result; if a future
  curve type does not support verifying a signature, or if the
  signature is structurally invalid, that should be treated the same
  as a verification failure. (This is already how structurally invalid
  Curve25519 signatures were being treated.)

This change allows other crates to depend on the smaller
libsignal_core rather than all of libsignal_protocol (though it also
means libsignal_core is no longer as small as it used to be).
2024-12-18 10:12:25 -08:00
Alex Konradi
0e85fdfbd0 Update Rust compiler to nightly-2024-12-11 2024-12-16 10:02:46 -05:00
Jordan Rose
6876bf5699 Enable clippy::cast_possible_truncation for all libraries
...and deal with the fallout (usually switching to TryFrom,
occasionally allowing the lint)
2024-10-18 12:34:52 -07:00
Jordan Rose
bd7f1d13e2 protocol: Document MAX_UNACKNOWLEDGED_SESSION_AGE 2024-10-02 15:25:33 -07:00
andrew-signal
b9d3c8ad45 Minor cleanup on recent sender chain overflow change 2024-09-25 16:02:52 -04:00
andrew-signal
1a89b4cc48 Make sender chain overflow an explicit SignalProtocolError 2024-09-24 14:15:38 -04:00
Jordan Rose
ee87aebc79 Update MSRV to 1.75 2024-09-13 13:43:29 -07:00
Alex Konradi
a54e6b5b33 Format with group_imports=StdExternalCrate 2024-08-28 14:52:47 -04:00
Jordan Rose
2dd3896bba protocol: Remove legacy SSv2 receive support 2024-08-08 15:10:25 -07:00
Jordan Rose
85e0de9207 Update Rust dependencies
`cargo update` performed with Cargo 1.72 to avoid advancing our MSRV. assert_cmd, clap, protobuf, and protobuf-json-mapping needed to be manually held back.

Plus, explicit bumps for
- env_logger 0.11
- heck 0.5
- itertools 0.13
- num_enum 0.7
- prost 0.13
- tungstenite 0.23

And disallowing downgrading curve25519-dalek below the security update in 4.1.3.
2024-07-25 13:33:09 -07:00
Jordan Rose
44ff1e74e6 Update to a slightly newer rustc 2024-06-20 12:04:44 -07:00
Alex Konradi
fa1f8f7ea2 Implement Distribution for new Timestamp types
This fixes a compilation breakage of the cross-version tests.
2024-05-01 14:53:55 -04:00
Alex Konradi
09bffd5ab4 Use a named type for protocol timestamp 2024-04-30 16:33:11 -04:00
Jordan Rose
ff10bdc76b protocol: Improve logs around sealed sender certs
(Thanks, @max-signal!)
2024-04-17 17:17:03 -07:00
Jordan Rose
8ae45dcd27 protocol: Flip SSv2 encryption to the "new" key derivation
All official clients should now support receiving this format.
2024-03-05 14:54:51 -08:00
Alex Konradi
174919865d Make ffi::CallbackError::check return a Result
Use Result to signal success or failure instead of Option::Some
signalling an error. This makes it easy to use combinators like
Result::map_err to more succinctly express the same operations.
Introduce a helper for SignalProtocolError to more succinctly construct
ApplicationCallbackError instances.
2024-01-18 09:46:29 -05:00
Jordan Rose
897051d97c protocol: Disable mlkem1024 for slightly faster non-test compiles
Previously we had the feature off but listed the dependency on
pqcrypto-kyber as non-optional, which was wasted work.

Note that the two versions of pqcrypto-kyber don't actually coexist
today! This should be treated as an API proof-of-concept, much like
our Kyber768 wrapper.
2024-01-10 13:19:06 -08:00
moiseev-signal
23a68fb021 Make it harder to forget to clear pending session state fields 2024-01-05 16:23:06 -08:00
Jordan Rose
62aacf553d Avoid using div_ceil to maintain compatibility with Rust 1.72 2024-01-05 10:46:48 -08:00
Jordan Rose
75811b90dc Move ServiceId + ProtocolAddress to new libsignal-core crate
...as well as related types Aci, Pni, ServiceId,
ServiceIdFixedWidthBinaryBytes, ServiceIdKind, and DeviceId.

...so that zkgroup and libsignal-net don't have to depend on
libsignal-protocol (and indirectly on Kyber).

The types are still exported from libsignal-protocol, so this is not a
source-breaking change.

ProtocolAddress is still defined as a (String, DeviceId) pair; a
switch to (ServiceId, DeviceId) will probably still happen in the
future, but not in this commit.
2023-12-13 09:20:19 -08:00
Jordan Rose
bc18bb0ecf SSv2: Parallelize the generation of per-recipient key material
This uses the Rayon library to perform a MapReduce-like operation of
computing key material on recipients and folding them together into
intermediate buffers, with one final collection step at the end. As
written this uses Rayon's default thread pool, which will be lazily
initialized with one worker thread per logical core. We're not trying
to share thread pools with either libsignal-net's tokio contexts,
RingRTC's dedicated threads, or a platform-specific work queue like
iOS's Dispatch; let's keep things simple for now.

As a downside, the code now has to fetch all of the recipients'
identity keys up front, since it's not guaranteed that loading from
the IdentityKeyStore is thread-safe. However, the significant
improvement in wall time spent generating key material for large
recipient lists on even a dual-core system makes this worth it.
2023-12-11 12:36:54 -08:00