Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions lib/components/peer-olm-session-creator-provider.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function PeerOlmSessionCreatorProvider(props: Props): React.Node {

const deadDevices = useSelector(getPeersDeadDeviceIDs);
const refetchDeviceList = useGetAndUpdateDeviceListsForUsers();
const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos);

const createOlmSessionsWithUserCallback = React.useCallback(
async (
Expand All @@ -56,11 +57,20 @@ function PeerOlmSessionCreatorProvider(props: Props): React.Node {
runningPromises.current[userID] = {};
}

const filteredDevices = devices.filter(
request =>
!runningPromises.current[userID][request.deviceID] &&
!deadDevices.has(request.deviceID),
);
const filteredDevices = devices
.filter(
request =>
!runningPromises.current[userID][request.deviceID] &&
!deadDevices.has(request.deviceID),
)
.map(request => ({
...request,
// `devicesPlatformDetails` is defined because otherwise, this device
// is going to be included in dead devices and filtered out, see
// `getPeersDeadDeviceIDs`.
platformDetails:
auxUserInfos[userID]?.devicesPlatformDetails?.[request.deviceID],
}));

const promise = (async () => {
const authMetadata = await getAuthMetadata();
Expand Down Expand Up @@ -105,10 +115,11 @@ function PeerOlmSessionCreatorProvider(props: Props): React.Node {
},
[
deadDevices,
auxUserInfos,
getAuthMetadata,
identityClient,
olmDebugLog,
sendMessageToDevice,
olmDebugLog,
refetchDeviceList,
],
);
Expand Down
8 changes: 8 additions & 0 deletions lib/keyserver-conn/keyserver-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,18 @@ function useRawKeyserverAuth(keyserverID: string): RawKeyserverAuthFunc {
keyserverKeys.identityKeysBlob.notificationIdentityPublicKeys,
keyserverKeys.notifInitializationInfo,
keyserverID,
// Assuming the keyserver is always running on the newest
// version, Olm compatibility is not required unlike for other
// clients that might not be updated yet.
false,
),
olmAPI.contentOutboundSessionCreator(
keyserverKeys.identityKeysBlob.primaryIdentityPublicKeys,
keyserverKeys.contentInitializationInfo,
// Assuming the keyserver is always running on the newest
// version, Olm compatibility is not required unlike for other
// clients that might not be updated yet.
false,
),
getAuthMetadata(),
]);
Expand Down
4 changes: 4 additions & 0 deletions lib/shared/crypto-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ function useInitialNotificationsEncryptedMessage(
notificationIdentityPublicKeys,
notifInitializationInfo,
keyserverID,
// Assuming the keyserver is always running on the newest
// version, Olm compatibility is not required unlike for other
// clients that might not be updated yet.
false,
);
},
[
Expand Down
3 changes: 3 additions & 0 deletions lib/types/crypto-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,21 @@ export type OlmAPI = {
+contentOutboundSessionCreator: (
contentIdentityKeys: OLMIdentityKeys,
contentInitializationInfo: OlmSessionInitializationInfo,
olmCompatibilityMode: boolean,
) => Promise<OutboundSessionCreationResult>,
+isContentSessionInitialized: (deviceID: string) => Promise<boolean>,
+keyserverNotificationsSessionCreator: (
cookie: ?string,
notificationsIdentityKeys: OLMIdentityKeys,
notificationsInitializationInfo: OlmSessionInitializationInfo,
keyserverID: string,
olmCompatibilityMode: boolean,
) => Promise<string>,
+notificationsOutboundSessionCreator: (
deviceID: string,
notificationsIdentityKeys: OLMIdentityKeys,
notificationsInitializationInfo: OlmSessionInitializationInfo,
olmCompatibilityMode: boolean,
) => Promise<EncryptedData>,
+isDeviceNotificationsSessionInitialized: (
deviceID: string,
Expand Down
24 changes: 21 additions & 3 deletions lib/utils/crypto-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { type TInterface } from 'tcomb';

import { getConfig } from './config.js';
import { getMessageForException } from './errors.js';
import { olmSupportRequired } from './olm-support-required.js';
import { primaryIdentityPublicKeyRegex } from './siwe-utils.js';
import { tRegex, tShape } from './validation-utils.js';
import type { OlmDebugLog } from '../components/debug-logs-context.js';
Expand All @@ -16,7 +17,10 @@ import type {
OutboundSessionCreationResult,
SignedIdentityKeysBlob,
} from '../types/crypto-types.js';
import type { IdentityServiceClient } from '../types/identity-service-types';
import type {
IdentityPlatformDetails,
IdentityServiceClient,
} from '../types/identity-service-types';
import {
type OutboundSessionCreation,
peerToPeerMessageTypes,
Expand Down Expand Up @@ -77,10 +81,13 @@ async function createOlmSessionsWithOwnDevices(
const recipientDeviceID = primaryIdentityPublicKeys.ed25519;

try {
// This function is used for testing purposes only, available to staff
// users, so Olm support is hardcoded to false.
const { sessionVersion, encryptedData } =
await olmAPI.contentOutboundSessionCreator(
primaryIdentityPublicKeys,
keys.contentInitializationInfo,
false,
);

const sessionCreationMessage: OutboundSessionCreation = {
Expand Down Expand Up @@ -117,6 +124,10 @@ export type DeviceSessionCreationRequest = {
+deviceID: string,
+sessionCreationOptions?: SessionCreationOptions,
};
type DeviceSessionCreationRequestWithPlatformDetails = {
...DeviceSessionCreationRequest,
platformDetails: ?IdentityPlatformDetails,
};
export type SessionCreationResult = {
+deviceKeysMissing: boolean,
};
Expand All @@ -125,7 +136,7 @@ async function createOlmSessionsWithUser(
identityClient: IdentityServiceClient,
sendMessage: (message: TunnelbrokerClientMessageToDevice) => Promise<void>,
userID: string,
devices: $ReadOnlyArray<DeviceSessionCreationRequest>,
devices: $ReadOnlyArray<DeviceSessionCreationRequestWithPlatformDetails>,
source: 'session_reset' | 'session_not_exists',
olmDebugLog: (olmLog: OlmDebugLog) => mixed,
): Promise<SessionCreationResult> {
Expand All @@ -147,6 +158,7 @@ async function createOlmSessionsWithUser(
+deviceID: string,
+hasContentSession: boolean,
+hasNotifsSession: boolean,
+olmSupport: boolean,
}> = await Promise.all(
devices.map(request =>
(async () => {
Expand All @@ -170,6 +182,7 @@ async function createOlmSessionsWithUser(
deviceID: request.deviceID,
hasContentSession,
hasNotifsSession,
olmSupport: olmSupportRequired(request.platformDetails),
};
})(),
),
Expand All @@ -193,7 +206,8 @@ async function createOlmSessionsWithUser(
success = false,
sessionVersionResult = -1;
try {
const { deviceID, hasContentSession, hasNotifsSession } = sessionRequest;
const { deviceID, hasContentSession, hasNotifsSession, olmSupport } =
sessionRequest;
const deviceKeysResponse = keysResponse.find(
keys => keys.deviceID === deviceID,
);
Expand All @@ -215,6 +229,7 @@ async function createOlmSessionsWithUser(
recipientDeviceID,
notificationIdentityPublicKeys,
keys.notifInitializationInfo,
olmSupport,
);
success = true;
return;
Expand All @@ -227,18 +242,21 @@ async function createOlmSessionsWithUser(
await olmAPI.contentOutboundSessionCreator(
primaryIdentityPublicKeys,
keys.contentInitializationInfo,
olmSupport,
);
} else {
resultDescription = 'creating content and notif session';
[outboundSessionCreationResult] = await Promise.all([
await olmAPI.contentOutboundSessionCreator(
primaryIdentityPublicKeys,
keys.contentInitializationInfo,
olmSupport,
),
olmAPI.notificationsOutboundSessionCreator(
recipientDeviceID,
notificationIdentityPublicKeys,
keys.notifInitializationInfo,
olmSupport,
),
]);
}
Expand Down
38 changes: 38 additions & 0 deletions lib/utils/olm-support-required.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @flow

import {
hasMinCodeVersion,
NEXT_CODE_VERSION,
} from '../shared/version-utils.js';
import type { IdentityPlatformDetails } from '../types/identity-service-types.js';
import {
identityDeviceTypes,
identityDeviceTypeToPlatform,
} from '../types/identity-service-types.js';

function olmSupportRequired(
platformDetails: ?IdentityPlatformDetails,
): boolean {
if (!platformDetails) {
return true;
}
// Assuming the keyserver is always running on the newest
// version, Olm compatibility is not required unlike for other
// clients that might not be updated yet.
if (platformDetails.deviceType === identityDeviceTypes.KEYSERVER) {
return false;
}
const { deviceType, ...rest } = platformDetails;

return !hasMinCodeVersion(
{
...rest,
platform: identityDeviceTypeToPlatform[deviceType],
},
{
native: NEXT_CODE_VERSION,
web: NEXT_CODE_VERSION,
},
);
}
export { olmSupportRequired };
5 changes: 3 additions & 2 deletions native/cpp/CommonCpp/CryptoTools/CryptoModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ int CryptoModule::initializeOutboundForSendingSession(
const std::string &idKeys,
const std::string &preKeys,
const std::string &preKeySignature,
const std::optional<std::string> &oneTimeKey) {
const std::optional<std::string> &oneTimeKey,
bool olmCompatibilityMode) {
int newSessionVersion = 1;
if (this->hasSessionFor(targetDeviceId)) {
std::shared_ptr<Session> existingSession =
Expand All @@ -256,7 +257,7 @@ int CryptoModule::initializeOutboundForSendingSession(
preKeys,
preKeySignature,
oneTimeKey,
true); // olmCompatibilityMode = true
olmCompatibilityMode);

newSession->setVersion(newSessionVersion);
this->sessions.insert(make_pair(targetDeviceId, std::move(newSession)));
Expand Down
3 changes: 2 additions & 1 deletion native/cpp/CommonCpp/CryptoTools/CryptoModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class CryptoModule {
const std::string &idKeys,
const std::string &preKeys,
const std::string &preKeySignature,
const std::optional<std::string> &oneTimeKey);
const std::optional<std::string> &oneTimeKey,
bool olmCompatibilityMode);
bool hasSessionFor(const std::string &targetDeviceId);
std::shared_ptr<Session> getSessionByDeviceId(const std::string &deviceId);
void removeSessionByDeviceId(const std::string &deviceId);
Expand Down
18 changes: 12 additions & 6 deletions native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,7 +1152,8 @@ jsi::Value CommCoreModule::initializeNotificationsSession(
jsi::String prekey,
jsi::String prekeySignature,
std::optional<jsi::String> oneTimeKey,
jsi::String keyserverID) {
jsi::String keyserverID,
bool olmCompatibilityMode) {
auto identityKeysCpp{identityKeys.utf8(rt)};
auto prekeyCpp{prekey.utf8(rt)};
auto prekeySignatureCpp{prekeySignature.utf8(rt)};
Expand Down Expand Up @@ -1181,7 +1182,8 @@ jsi::Value CommCoreModule::initializeNotificationsSession(
identityKeysCpp,
prekeyCpp,
prekeySignatureCpp,
oneTimeKeyCpp);
oneTimeKeyCpp,
olmCompatibilityMode);

result = notifsCryptoModuleWithPicklingKey.value().first->encrypt(
keyserverIDCpp,
Expand Down Expand Up @@ -1526,7 +1528,8 @@ jsi::Value CommCoreModule::initializeContentOutboundSession(
jsi::String prekey,
jsi::String prekeySignature,
std::optional<jsi::String> oneTimeKey,
jsi::String deviceID) {
jsi::String deviceID,
bool olmCompatibilityMode) {
auto identityKeysCpp{identityKeys.utf8(rt)};
auto prekeyCpp{prekey.utf8(rt)};
auto prekeySignatureCpp{prekeySignature.utf8(rt)};
Expand All @@ -1550,7 +1553,8 @@ jsi::Value CommCoreModule::initializeContentOutboundSession(
identityKeysCpp,
prekeyCpp,
prekeySignatureCpp,
oneTimeKeyCpp);
oneTimeKeyCpp,
olmCompatibilityMode);

const std::string initMessage = "{\"type\": \"init\"}";
initialEncryptedData =
Expand Down Expand Up @@ -1667,7 +1671,8 @@ jsi::Value CommCoreModule::initializeNotificationsOutboundSession(
jsi::String prekey,
jsi::String prekeySignature,
std::optional<jsi::String> oneTimeKey,
jsi::String deviceID) {
jsi::String deviceID,
bool olmCompatibilityMode) {
auto identityKeysCpp{identityKeys.utf8(rt)};
auto prekeyCpp{prekey.utf8(rt)};
auto prekeySignatureCpp{prekeySignature.utf8(rt)};
Expand Down Expand Up @@ -1695,7 +1700,8 @@ jsi::Value CommCoreModule::initializeNotificationsOutboundSession(
identityKeysCpp,
prekeyCpp,
prekeySignatureCpp,
oneTimeKeyCpp);
oneTimeKeyCpp,
olmCompatibilityMode);

result = notifsCryptoModuleWithPicklingKey.value().first->encrypt(
deviceIDCpp,
Expand Down
9 changes: 6 additions & 3 deletions native/cpp/CommonCpp/NativeModules/CommCoreModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI {
jsi::String prekey,
jsi::String prekeySignature,
std::optional<jsi::String> oneTimeKey,
jsi::String keyserverID) override;
jsi::String keyserverID,
bool olmCompatibilityMode) override;
virtual jsi::Value
isNotificationsSessionInitialized(jsi::Runtime &rt) override;
virtual jsi::Value isDeviceNotificationsSessionInitialized(
Expand All @@ -133,7 +134,8 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI {
jsi::String prekey,
jsi::String prekeySignature,
std::optional<jsi::String> oneTimeKey,
jsi::String deviceID) override;
jsi::String deviceID,
bool olmCompatibilityMode) override;
virtual jsi::Value initializeContentInboundSession(
jsi::Runtime &rt,
jsi::String identityKeys,
Expand All @@ -149,7 +151,8 @@ class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI {
jsi::String prekey,
jsi::String prekeySignature,
std::optional<jsi::String> oneTimeKey,
jsi::String deviceID) override;
jsi::String deviceID,
bool olmCompatibilityMode) override;
virtual jsi::Value
encrypt(jsi::Runtime &rt, jsi::String message, jsi::String deviceID) override;
virtual jsi::Value encryptNotification(
Expand Down
Loading
Loading