The JNI tests have also been conditionalized in case we want to take
this out for Android as well. (Node still unconditionally depends on
it being present.) I've given it a separate feature flag from just
ffi/jni/node so that we can preserve the tests Jessa wrote for each
platform.
This MP4 format "sanitizer" currently only transforms (when necessary) outgoing media on iOS, Android, or Desktop to
make it suitable for streaming playback by the recepient. In the future, it will validate and be able to either repair
or reject outbound AND inbound media, to prevent malformed media from being fed to third party or OS media players.
An generic io module was added to the libsignal rust bridge containing the InputStream trait, modeled loosely after
Java's InputStream, which calls back into the client language to perform reads or skips. This infrastructure could
potentially also be for any other future large data inputs to libsignal functions.
This is very similar to the AuthCredential used by the group server,
but using CallLinkParams to encrypt the user ID rather than
GroupParams (and using GenericServerParams to issue the credential
rather than the group server's ServerParams).
This will allow a user to request to create a call link from the chat
server without revealing anything about the room, and then later
actually create it by giving the room ID to the calling server without
identifying themself.
This involves a new, stripped-down GenericServer{Secret,Public}Params,
which currently only contains a generic "zkcredential" key. Apart from
the calling server not needing to handle all the credentials that the
group storage server supports, the structure of zkcredential means it
is safe to use the same key for multiple kinds of credentials.
Similarly, CallLink{Secret,Public}Params plays the same role as
Group{Secret,Public}Params for encrypting user IDs when talking to the
calling server.
Following from that, the APIs for CreateCallLinkCredentials are
located on the individual types (RequestContext, Request, Response,
Credential, Presentation) rather than all being on the Server*Params
types; adding a new credential type won't change the API of the
Server*Params types at all.
The main Server*Params may make use of zkcredential in the future as
well, but for now it's only for new Signal servers that want to use
zero-knowledge credentials.
- We weren't loading the native library as "signal_jni.dll"
- The Gradle build commands, though still requiring a shell environment,
shouldn't rely on Unix-style #! lines to execute shell scripts
This was previously in the Java layer because it only really affects
the server, but it's more consistent to have all verification in the
Rust layer. We do lose the separate exception type for it, though.
Adds a java method for libsignal-server that enables extracting
attestation metrics from serialized evidence and endorsements.
Certificate and endorsement validity periods are exposed, so servers
can track if any attestation material is overly stale.
Implements (a subset of) Intel's DCAP attestation,
making heavy use of 'boring' for X509 and ECDSA.
Cds2Client is now ready for use!
Co-authored-by: Jordan Rose <jrose@signal.org>
Co-authored-by: Ravi Khadiwala <ravi@signal.org>
This is a variant of AuthCredential that carries two UUIDs, intended
to be a user's ACI and PNI. Why? Because when you've been invited to a
group, you may have been invited by your ACI or by your PNI, or by
both, and it's easier for clients to treat all those states the same
by having a credential that covers both identities. The downside is
that it's larger (both the data, obviously, but also the zkgroup proof
of validity, unsurprisingly).
AnyAuthCredentialPresentation gains a 'get_pni_ciphertext' method,
which will return `None` for the existing presentations and
`Some(encrypted_pni)` for the new credential. Having a separate
credential type but a common presentation type makes it easier for the
server to handle all possible credentials uniformly.
Like ProfileKeyCredential, but with an expiration timestamp embedded
in it. This has its own credential type and response type, but uses
the same request type as a "classic" ProfileKeyCredential, and
generates presentations usable with AnyProfileKeyCredential-
Presentation, so that existing server code accepting presentations
will automatically do the right thing.
Adoption for servers:
- Update secret params
- When presentations are saved in group state, use
ProfileKeyCredentialPresentation.getStructurallyValidV1PresentationBytes()
to maintain backwards compatibility with existing clients.
- Add an endpoint to issue ExpiringProfileKeyCredentials
- (future) Remove the endpoint that issues regular ProfileKeyCredentials
Adoption for clients, after the server has updated:
- Update public params
- Start fetching and using ExpiringProfileKeyCredentials instead of
regular ProfileKeyCredentials (the old endpoint will eventually
go away)
- Node: To bring types into harmony, a receipt's expiration time has
been changed to a `number` instead of a `bigint`
Optimize presentation of credentials (AuthCredentialPresentationV2, ProfileKeyCredentialPresentationV2, PniCredentialPresentationV2). Server will accept V1 or V2 presentations. Clients will produce V2.
Various improvements to FFI to support this, and some minor optimizations (in particular "lazy statics" to avoid redundant loading of SystemParams).
In Java these are subclasses of IllegalStateException, a
RuntimeException, so that every session operation isn't annotated as
throwing InvalidSessionException. Swift and TypeScript don't have
typed errors, so they're just additional specific cases that can be
caught.
...not a generic RuntimeException. Now that it's only used for
SignalMessage MAC keys, the only way it could be wrong is if it's
provided incorrectly by the user.
Reorganize the Gradle build with three targets:
- signal-client-java (client/)
- signal-client-android (android/)
- libsignal-server (server/)
plus an additional shared/ directory for sources shared between
client/ and server/.
This maintains the distinction between signal-client-java (the Java
parts, plus a Linux libsignal_jni.so for running tests outside of the
Android emulator) and signal-client-android (contains the Android JNI
libraries, plus any Android-specific code, which for now is just
AndroidSignalProtocolLogger, which the app doesn't even use).
The new libsignal-server is built very similarly to
signal-client-java, but only contains the Java sources relevant for
the server...plus the base org.whispersystems.libsignal classes from
the original libsignal-protocol-java, because some of them are
referenced directly in our generated Native.java. (We can improve on
this in the future.) The "testable" artifact that includes macOS and
Windows versions of libsignal_jni.so is now only built for
libsignal-server, not signal-client-java; our Android development
happens on Linux, but server development happens on multiple
platforms.
Tests were recently reorganized into a top-level tests/ directory, but
now there's been another reorganization:
- client/src/test/ - tests to run on any clients
- android/src/androidTest/ - tests to run only on Android devices /
emulators (currently none)
- server/src/test/ - tests to run specifically for the server
(currently none)
- shared/test/ - does not exist to avoid running the same tests twice
There are no tests to run "only not on Android devices", and it's
currently assumed that all server functionality is tested by the
client tests. The Android device tests run all the client tests as
well (by direct path reference). This may not be the "best" Gradle
layout, but it's at least straightforward to read the Gradle files.
For now there's still only one native library built for both
signal-client-java and libsignal-server, but that could change in the
future.