Commit Graph

58 Commits

Author SHA1 Message Date
Jordan Rose
deeafcad51 java: Improve zkgroup's ByteArray helper class
- Don't validate sizes ahead of time if the subclass calls
  CheckValidContents anyway.
- Move serialize() up to ByteArray. Consequently, make ProfileKeyVersion
  *not* a ByteArray, since it serializes as a string.
2021-11-08 11:06:32 -08:00
Jordan Rose
3ed5fff78c java: Merge zkgroup's Hex utility class into libsignal's existing one 2021-11-08 11:06:31 -08:00
Jordan Rose
b8ec92d332 java: Update zkgroup license headers, remove codegen warnings 2021-11-08 11:06:31 -08:00
Jordan Rose
ef73a621f0 java: Get the zkgroup sources to build and pass tests
This is a pretty mechanical translation *except* for

- moving the RANDOM_LENGTH constant out of the obsolete Native class
  (libsignal-client has its own) into a new Constants class

- replacing the mocked SecureRandom with a custom subclass; Mockito
  was refusing to mock SecureRandom and honestly that's fair

- removing unused classes UUIDUtil and ZkGroupError

- updating to JUnit 4, which zkgroup's tests rely on
2021-11-08 11:06:31 -08:00
Jordan Rose
c2261d1701 java: Add the zkgroup sources verbatim (does not compile) 2021-11-08 11:04:58 -08:00
Jordan Rose
9a569f2ffe Standardize license headers
...to have a period after "Signal Messenger, LLC."

...except for the Java sources, which still need a cleanup pass.
2021-10-28 17:27:30 -07:00
Jordan Rose
64ad39c54d Remove support for HKDF "versions"
Previously, we had HKDF-for-session-version-3, which matches RFC 5869,
and HKDF-for-session-version-2, which produced slightly different
results. However, nothing in the current versions of Signal uses
anything but the RFC-compliant version. Therefore, this commit removes
support for version 2 and deprecates the entry points that take a
version:

- Java: The HKDFv3 class is deprecated in favor of static methods on
  the HKDF class.
- Swift: The hkdf function that takes a 'version' parameter is
  deprecated in favor of a new overload that does not.
- TypeScript: The HKDF class is deprecated in favor of a top-level
  hkdf function.
- Rust: The libsignal-protocol implementation of HKDF has been removed
  entirely in favor of the hkdf crate.

There are no significant benchmark deltas from this change, and a
minimal code size increase that's the cost for removing our own
implementation of HKDF. The deprecations can be removed as a later
breaking change.
2021-10-14 16:02:56 -07:00
Jordan Rose
304a90fe56 Java: Ensure finalizers don't run until Native calls complete
If garbage collection happens at exactly the wrong time, the Java
wrapper around a Rust object (such as SessionRecord) can be finalized
while the Rust object is being used, via its opaque 'nativeHandle'
(address cast as integer). Avoid this by adding a NativeHandleGuard
type that keeps the wrapper alive, as well as a low-level entry point
`Native.keepAlive(...)` that does nothing but serve as a sort of GC
guard, similar to `Reference.reachabilityFence()` in Java 9.
2021-10-14 14:26:46 -07:00
Jordan Rose
72d3c97890 Java: Add a test for SSv2 with 1000s of recipients
This previously caused the JVM to crash because we ran out of local
reference slots.
2021-10-08 14:58:26 -07:00
Graeme Connell
9caa6615b9 JNI for HSM enclave client. 2021-09-21 16:37:07 -06:00
Jordan Rose
8c5b6af3fa Sealed sender v2: add an InvalidRegistrationId exception/error
This dedicated error is thrown when a recipient has a registration ID
that's out of the range used by Signal [0, 0x3FFF]. These IDs cannot
be encoded in the sealed sender v2 format and are not supported, even
though they don't cause any problems for 1:1 messages.
2021-08-31 13:11:10 -07:00
Cody Henthorne
b8b6c285ad Java: Make toStringCondensed match output from other Signal implementations. 2021-07-09 15:23:58 -04:00
Jordan Rose
08e72307ca Java: include the sealed sender groupId on sucessful decryption
This is useful for PlaintextContent messages (just
DecryptionErrorMessage for now), which can't include a group ID when
sent outside of sealed sender because it would reveal group
membership.
2021-05-28 10:06:31 -07:00
Jordan Rose
b780409c1b Add a deviceId field to DecryptionErrorMessage
This allows a device to know whether it's the one that sent a bad
message, and take action accordingly.

We could have a slightly more typesafe API here by using
ProtocolAddress and extracting the device ID, but that doesn't match
up with getting the device ID out of a sealed sender certificate.
2021-05-26 17:23:42 -07:00
Jordan Rose
4c0141c31f Fix merge conflict in Java and Swift tests too. 2021-05-26 16:43:11 -07:00
Jordan Rose
2491447ee7 Merge pull request #316 from signalapp/jrose/DecryptionErrorMessage-and-PlaintextContent-2
Add DecryptionErrorMessage and PlaintextContent (alternate)
2021-05-26 16:27:49 -07:00
Jordan Rose
51dd86a1db Finalize ContentHint design
- Default: sender will not resend; an error should be shown
  immediately
- Resendable: sender will try to resend; delay any error UI if
  possible
- Implicit: don't show any error UI at all; this is something sent
  implicitly like a typing message or a receipt
2021-05-26 15:57:45 -07:00
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
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
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
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
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
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
6aa8ed43d2 JNI: support &mut buffers in bridge_fns, and use it for AES APIs 2021-03-24 11:02:41 -07: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
Jack Lloyd
f8648c21cd Add hashes and HMAC for Java 2021-03-15 13:30:39 -04:00
Jack Lloyd
1944d16dec Device Sender Utilities - Generate Key + Self-Signed Certificate 2021-03-08 16:46:19 -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
Jack Lloyd
d77fa218a2 Map errors through the bridge more carefully
Remove several errors that were very once-off.

In Java avoid throwing RuntimeException unless it's an internal error
that we really should crash on.
2021-01-28 14:26:17 -05:00
Jack Lloyd
6c030d56a5 Drop down to 25k 2021-01-16 15:07:42 -05:00
Jack Lloyd
6c4cd62d1d Many encryptings 2021-01-16 14:32:22 -05:00
Jordan Rose
8fa2f4a73f JNI: Rethrow callback exceptions instead of wrapping them 2021-01-12 11:54:19 -08:00
Jordan Rose
049300d9d4 JNI: Report callback exceptions as the "cause" of a callback failing 2021-01-12 11:54:19 -08:00
Jack Lloyd
ba91fe441e Merge pull request #135 from signalapp/jack/fix-decrypt-logic
Fix handling when attempting to decrypt with a session that isn't found
2021-01-07 16:47:51 -05:00
Jack Lloyd
0184984db5 Add a test that decryption works after you archive a session state 2021-01-07 15:24:44 -05:00
Jack Lloyd
564a1b7d54 Resolve difference in behavior between Java and Rust SessionRecord
In libsignal-protocol-java, SessionRecord holds a SesssionState struct which is
the "active" session plus a list of old states. If the record is freshly
created, there is still a SessionState, but it is an uninitialized/new protobuf
structure which causes all fields to be empty/zero/false.

So in the original Java logic you can call for example hasSenderChain, and on
an empty/fresh record it will return false. However in Rust, in this case the
Option is empty and we return an error instead.

For hasSenderChain, it seems reasonable to return false if there is no active
session, since if there is no session there is certainly no chain.

Android also expects the session version to be == 0 on such sessions, but this
makes less sense, so have this logic only in the Java binding and not in the
Rust library proper.
2021-01-07 13:15:25 -05:00
Jack Lloyd
4131f8075c Merge pull request #105 from signalapp/jack/no-more-java-protobuf
Remove protobuf from Java binding
2020-12-10 10:24:14 -05:00
Jack Lloyd
4b4b7e3df6 Make some changes on the road to removing SessionState from Java 2020-12-09 13:48:14 -05:00
Jack Lloyd
612ef9f44c Remove protobuf from Java 2020-12-09 13:01:31 -05:00
Jack Lloyd
a32efa2d24 Remove some Java API surface no longer needed
Some cruft still remains for the tests which is hard to avoid, eg getAliceBaseKey
2020-12-08 18:13:06 -05:00
Jack Lloyd
9f11b256a8 Expose AES-GCM-SIV to Java and Swift 2020-12-04 18:13:16 -05:00
Jordan Rose
d1df148cc8 Java: Escape some non-ASCII characters in a test case 2020-12-01 16:54:35 -08:00
Jack Lloyd
643a637b34 Merge pull request #77 from signalapp/jack/sealed-sender
Sealed Sender
2020-12-01 17:43:30 -05:00
Jordan Rose
e64fa771e5 JNI: Handle InvalidKeyIdException in (Signed)PreKeyStore
And test that the exception is handled and not propagated.
2020-11-23 13:20:23 -08:00