Commit Graph

145 Commits

Author SHA1 Message Date
Jordan Rose
f7acf9005e Add SessionRecord.currentRatchetKeyMatches
This checks if there is an active sender state using the given ratchet
key, for use with decryption error messages. In this case, the app may
choose to archive the current session, or take even stronger actions
such as fetching new prekeys for the recipient.
2021-05-26 15:41:04 -07:00
Jordan Rose
3f3a6e1aca Expose DecryptionErrorMessage and PlaintextContent to Java/Swift/TS 2021-05-26 15:41:04 -07:00
Jordan Rose
a41233936f Bump version to 0.6.0 2021-05-21 15:04:27 -07:00
Jordan Rose
6f9083175e Get registration IDs from sessions for Sealed Sender v2
The app-visible change is that sealedSenderMultiRecipientEncrypt now
takes a SessionStore as well. Sessions will be looked up in bulk using
a new SessionStore API, 'loadExistingSessions' or
'getExistingSessions`. The registration ID is then loaded from each
session and included in the resulting SSv2 payload.

The implementation is a bit of a divergence from some other APIs in
libsignal-client in that the "look up in bulk" step is performed in
the Java, Swift, or TypeScript layer, with the resulting sessions
passed down to Rust. Why? Because otherwise we'd pass a list of
addresses into Rust, which would have to turn them back into a Java,
Swift, or TypeScript array to call the SessionStore method. This would
be (1) a bunch of extra work to implement, and (2) a waste of CPU when
we already /have/ a list of addresses in the correct format: the
argument to sealedSenderMultiRecipientEncrypt.

This is an example of "the boundaries between the Rust and
Java/Swift/TypeScript parts of the library don't have to be perfect;
they're internal to the overall product". In this case, we've taken
that a little further than usual: usually we try to make the
libsignal-protocol API as convenient as possible as well, but here it
had to be a bit lower-level to satisfy the needs of the app language
wrappers. (Specifically, callers need to fetch the list of
SessionRecords themselves.)

P.S. Why doesn't v1 of sealed sender include registration IDs? Because
for SSv1, libsignal-client isn't producing the entire request body to
upload to the server; it's only producing the message content that
will be decrypted by the recipient. With SSv2, the serialized message
the recipient downloads has both shared and per-recipient data in it,
which the server must assemble from the uploaded request. Because of
this, SSv2's encrypt API might as well produce the entire request.
2021-05-20 18:04:03 -07:00
Jordan Rose
1fd8da669b Revert "Add registration IDs to the Sealed Sender v2 upload (encrypt) format" (#303) 2021-05-17 10:03:49 -07:00
Jordan Rose
b5cddf9dbb Add registration IDs to the Sealed Sender v2 upload (encrypt) format
Registration IDs are used to detect if a device ID has been reused,
since the new device will (with high probability) use a different
randomly-generated registration ID from the old one. The server should
be able to validate this for SSv2 like it does for SSv1, though the
handling of this for SSv1 is in the various apps.
2021-05-14 15:38:31 -07:00
Jordan Rose
11d9c40cc1 Merge pull request #300 from signalapp/jrose/java-SenderKeyStore-doc-comment
Java: fix doc comment for SenderKeyStore.loadSenderKey
2021-05-11 15:56:44 -07:00
Jordan Rose
a9729bbf82 Java: fix doc comment for SenderKeyStore.loadSenderKey
The summary was out of sync with the `@return` command.
2021-05-11 14:46:16 -07:00
Jordan Rose
5ef78c0004 Merge pull request #293 from signalapp/jrose/SenderKey-message-versions
A SenderKeyMessage's version must match the SenderKeyState
2021-05-10 17:02:23 -07:00
Jordan Rose
4569e1ffaf SenderKey: Use the session version as the message version
We still encode the "current" version in the message version byte, but
the part that the receiver will check is now based on the session's
original message version rather than the "current" version in the
sender. (Note that these are the /same/ version right now, so this
change won't have any effect on the current wire format.)

This matches the behavior of SignalMessage and PreKeySignalMessage.
2021-05-07 18:24:44 -07:00
Jordan Rose
8af0ab17f2 Remove public constructors for *Message types
The parameters for these constructors cannot be chosen correctly in
isolation; messages always need to be created as part of a session.

The Node APIs have been renamed with leading underscores rather than
removed because we *did* have tests that explicitly constructed
messages just to test that they faithfully preserve information. In
this case the parameters are plausible values but not used for
anything.
2021-05-07 18:17:46 -07:00
Jordan Rose
f962e387b7 Java: allow a null info for HKDF (treated as empty)
Restores compatibility with libsignal-protocol-java.
2021-05-07 10:47:34 -07:00
Jordan Rose
73a15db929 Java: record native code size for 0.5.0 and 0.5.1 2021-04-29 10:12:56 -07:00
Jordan Rose
b5f6d50b53 Bump version to 0.5.1 2021-04-28 17:05:25 -07:00
Jordan Rose
113e849d76 Bump version to 0.5.0 2021-04-21 19:07:56 -07:00
Jordan Rose
5380131e7c Java: switch to Debian for Docker builds instead of Ubuntu
Debian has a more stable retention period for pinned dependencies (the
version of OpenJDK 8 we were using for Ubuntu is gone already!), and
it matches what the Signal-Android repository is doing.
2021-04-21 12:15:33 -07:00
Jordan Rose
7d62e674b5 Bump version to v0.4.0 across all languages 2021-04-05 13:13:09 -07:00
Jordan Rose
18463e8357 Switch to a flat (non-protobuf) encoding for SealedSender v2
We're optimizing for size overhead in this encoding, so forego the
flexibility of protobufs in favor of a flat encoding (though one that
still uses protobuf's varints). Additionally, this encoding includes
the recipients inline in the message so the client can dump it all to
server in one go.

As a side effect, this means an SSv2 message encoded for sending no
longer has the same format as one encoded for receiving when there's
only one recipient. Consequently, all the tests need to be modified to
"fan out" a multi-recipient message to several single-recipient
messages. For simplicity, the wrapper language tests only support this
operation for SSv2 messages sent to exactly one recipient.
2021-04-05 11:46:52 -07:00
Jordan Rose
06431b3745 Java: remove UnidentifiedSenderMessage class
This was only used for testing when libsignal-metadata-java was first
merged into this repo, and those tests have since been moved to the
Rust layer.
2021-04-05 11:46:52 -07:00
Jordan Rose
690dfde027 Add contentHint and groupId fields to UnidentifiedSenderMessageContent
And to the ProtocolExceptions for Java, thrown when a sealed sender
message's content fails to decrypt. (Eventually all languages will
support this.)
2021-04-05 11:46:52 -07:00
Jordan Rose
d339d5a072 Expose Sealed Sender v2 to clients
- Add a new "multi-recipient encrypt" entry point
- Add an "encrypt v1 sealed sender from UnidentifiedSenderMessage-
  Content" entry point
- Add a public constructor for UnidentifiedSenderMessageContent
- Change group_encrypt to return a CiphertextMessage instead of bytes,
  so it can be used with the above
- Java: add SenderKeyStore to SignalProtocolStore requirements
2021-04-05 11:31:27 -07:00
Jordan Rose
d0f34935b9 JNI: Handle CiphertextMessage results in bridge_fns
Unlike the other two bridges, the Java representation of a
CiphertextMessage uses an interface with implementing classes, rather
than an opaque wrapper. But bridge_fn's ResultTypeInfo can model this
too, and it simplifies things to do so.
2021-04-05 11:31:27 -07:00
Jordan Rose
8509374928 SenderKeyDistributionMessage is not a CiphertextMessage
It's a payload message, something that would go inside a SignalMessage
or PreKeySignalMessage. Drop it from all the enums, and while we're
here let's sync up the CiphertextMessageType::SenderKey case with the
sealed sender content type and the envelope content type.
2021-04-05 11:31:27 -07:00
Jordan Rose
fd21109476 Use a strongly-typed UUID for the distribution ID of SenderKeyMessages
That's a java.util.UUID for Android, Foundation.UUID for iOS, and, uh,
strings for Electron.
2021-03-25 12:48:14 -07:00
Jordan Rose
f6267f3391 Remove SenderKeyName abstraction
With distribution IDs embedded in SenderKeyMessage and
SenderKeyDistributionMessage, the abstraction of SenderKeyName (a
sender address + distribution ID tuple) is no longer pulling its
weight. Remove it from the implementation and the public API.
2021-03-25 09:44:31 -07:00
Jordan Rose
4ce9f7c192 Include distribution ID inside SenderKey[Distribution]Message
The distribution ID is used to identify which key a particular sender
is using to encrypt their SenderKeyMessage, so it has to be known as
part of decryption. The previous design had the distribution ID stored
alongside each message (perhaps on the "envelope" structure that's
received from the server), but that's harder to keep track of, and it
would only be present for certain message kinds anyway.
2021-03-25 09:44:04 -07:00
Jordan Rose
1a25f63a95 SenderKey: Rename 'keyId' to 'chainId', 'groupId' to 'distributionId'
Clarifies the use of "ID" in SenderKey-related APIs. I've left
deprecated entry points for Java but not for Swift and TypeScript
(which are not in use yet).

- SenderKeyMessage::key_id -> chain_id (avoids double "key" in name)
- SenderKeyDistributionMessage::id -> chain_id (to match SKM)
- SenderKeyName::group_id -> distribution_id (it's not the global group ID)
2021-03-25 09:40:20 -07:00
Jordan Rose
6aa8ed43d2 JNI: support &mut buffers in bridge_fns, and use it for AES APIs 2021-03-24 11:02:41 -07:00
Jordan Rose
7be34d7446 Merge pull request #253 from signalapp/jrose/java-unsynchronized-GroupCipher
Java: Move burden of GroupCipher/SessionBuilder locking to the client
2021-03-22 16:49:51 -07:00
Jack Lloyd
0cef003771 Add a JCE compat layer 2021-03-19 16:49:15 -04:00
Jack Lloyd
50bca9817f Fix visibility on Java AES interfaces 2021-03-19 16:33:15 -04:00
Jack Lloyd
3be3b28e7c Fix Java binding 2021-03-19 15:29:48 -04:00
Jack Lloyd
b890265231 Provide the GCM APIs only with offset/length params
Java really wants this, and Swift can use them or not
2021-03-19 15:18:11 -04:00
Jack Lloyd
1ec8c3a729 Support offset/length params for GCM encryption in Java API
As Java has no concept of slices and we need some way of doing partial
updates, since this is required to implement the JCE Cipher interface,
and Android uses it.
2021-03-19 15:01:20 -04:00
Jack Lloyd
ca28718e3b Add Java binding for CTR and GCM 2021-03-18 11:28:42 -04:00
Jordan Rose
7d35556205 Java: Move burden of GroupCipher/SessionBuilder locking to the client
Same as a1468f737 but for SenderKey encryption.
2021-03-16 17:29:31 -07:00
Jordan Rose
1142c5f43c CI: Add a check for code size growth in the arm64 Android library
Sample output:

    current build is 0% larger than v0.3.4 (current: 1957208 bytes, v0.3.4: 1949016 bytes)
       0.1.5: *********** (1079472 bytes)
       0.1.6: *********** (1153216 bytes)
       0.1.7: *********** (1153216 bytes)
       0.2.0: ************ (1222832 bytes)
       0.2.2: ************* (1267888 bytes)
       0.2.2: ************** (1382592 bytes)
       0.2.3: *************** (1489088 bytes)
       0.3.4: ******************* (1949016 bytes)
     current: ******************* (1957208 bytes)
2021-03-15 18:40:47 -07:00
Jack Lloyd
f8648c21cd Add hashes and HMAC for Java 2021-03-15 13:30:39 -04:00
Jordan Rose
70e495446d Bridge: add ignored Context args to methods taking stores for JNI/Node
Previously we defined one entry point for FFI (Swift) that took an
extra "context" parameter (to pass through iOS's database
transactions), and one for JNI+Node that did not (no context needed
currently). But this is all in our glue layer, which doesn't need to
be a perfect reflection of the outside interface. Remove that
duplication by accepting a Context parameter for both JNI and Node
that, for now, must be null.
2021-03-10 17:59:08 -08:00
Jack Lloyd
8641994ee7 Bump Java version to 0.3.4 2021-03-09 15:35:53 -05:00
Jack Lloyd
9050c5d000 Make the public things public 2021-03-09 13:22:21 -05:00
Jack Lloyd
846bcdfe7d Fix the Java interface for DeviceTransferKey 2021-03-09 10:23:19 -05:00
Jack Lloyd
1944d16dec Device Sender Utilities - Generate Key + Self-Signed Certificate 2021-03-08 16:46:19 -05:00
Jordan Rose
f9dc12947e Bridge: Limit bridge_get_bytearray so it can use bridge_fn_buffer
By disallowing arbitrary expressions, bridge_get_bytearray (and
bridge_get_optional_bytearray) ends up a lot more like bridge_get,
and can reuse the infrastructure in bridge_fn_buffer instead of
needing a separate per-bridge implementation.
2021-02-25 18:08:13 -08:00
Greyson Parrelli
a1468f7371 Move the burden of SessionCipher locking to the client. 2021-02-18 12:45:34 -05:00
Jack Lloyd
334231fbf0 Merge pull request #178 from signalapp/jack/remove-displayable-format
Remove DisplayableFingerprint_Format from bridge
2021-02-04 16:40:39 -05:00
Jack Lloyd
26d46e3d2d Remove DisplayableFingerprint_Format from bridge
This should only be done by the fingerprint generator.

Was exposed in Java but never called by Android. Not even exposed in Swift
2021-02-04 16:18:18 -05:00
Jordan Rose
512d0226bc Reject SenderCertificates without UUIDs
Additionally, never look up a session by e164 when decrypting
sealed-sender messages.

This is an API-breaking change for both Java and Swift clients;
certain fields and arguments are no longer Optional. On top of that,
some tests may need to be updated to provide UUIDs instead of just
phone numbers.
2021-02-04 11:25:33 -08:00
Jordan Rose
b522c42526 Bridge: use Node's bridge_fn HKDF for JNI as well
FFI's is still separate because it generates its output into an
existing buffer, which is a different signature than the other two.
2021-02-03 17:01:11 -08:00
Jordan Rose
478e178ac4 Add bridge_fn_void and use it for SessionRecord_ArchiveCurrentState
This also builds on the mutable borrow groundwork in the previous
commit.
2021-02-03 15:38:34 -08:00