diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js --- a/native/profile/secondary-device-qr-code-scanner.react.js +++ b/native/profile/secondary-device-qr-code-scanner.react.js @@ -33,6 +33,7 @@ import { composeTunnelbrokerQRAuthMessage, parseTunnelbrokerQRAuthMessage, + signDeviceListUpdate, } from '../qr-code/qr-code-utils.js'; import { useStyles } from '../themes/colors.js'; import Alert from '../utils/alert.js'; @@ -121,9 +122,8 @@ devices: [...devices, newDeviceID], timestamp: Date.now(), }; - await updateDeviceList({ - rawDeviceList: JSON.stringify(newDeviceList), - }); + const signedDeviceList = await signDeviceListUpdate(newDeviceList); + await updateDeviceList(signedDeviceList); }, [identityContext], ); diff --git a/native/qr-code/qr-code-utils.js b/native/qr-code/qr-code-utils.js --- a/native/qr-code/qr-code-utils.js +++ b/native/qr-code/qr-code-utils.js @@ -1,6 +1,10 @@ // @flow import { hexToUintArray } from 'lib/media/data-utils.js'; +import type { + RawDeviceList, + SignedDeviceList, +} from 'lib/types/identity-service-types.js'; import { peerToPeerMessageTypes, type QRCodeAuthMessage, @@ -9,12 +13,13 @@ qrCodeAuthMessagePayloadValidator, type QRCodeAuthMessagePayload, } from 'lib/types/tunnelbroker/qr-code-auth-message-types.js'; +import { getContentSigningKey } from 'lib/utils/crypto-utils.js'; import { convertBytesToObj, convertObjToBytes, } from '../backup/conversion-utils.js'; -import { commUtilsModule } from '../native-modules.js'; +import { commCoreModule, commUtilsModule } from '../native-modules.js'; import * as AES from '../utils/aes-crypto-module.js'; function composeTunnelbrokerQRAuthMessage( @@ -52,4 +57,28 @@ return Promise.resolve(payload); } -export { composeTunnelbrokerQRAuthMessage, parseTunnelbrokerQRAuthMessage }; +async function signDeviceListUpdate( + deviceListPayload: RawDeviceList, +): Promise { + const deviceID = await getContentSigningKey(); + const rawDeviceList = JSON.stringify(deviceListPayload); + + // don't sign device list if current device is not a primary one + if (deviceListPayload.devices[0] !== deviceID) { + return { + rawDeviceList, + }; + } + + const curPrimarySignature = await commCoreModule.signMessage(rawDeviceList); + return { + rawDeviceList, + curPrimarySignature, + }; +} + +export { + composeTunnelbrokerQRAuthMessage, + parseTunnelbrokerQRAuthMessage, + signDeviceListUpdate, +};