Merge pull request #1387 from Bilb/fix-pre-key-errors-bad-mac

fix restoring of session after restore from seed
pull/1381/head
Audric Ackermann 4 years ago committed by GitHub
commit cf401fb78e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -92,7 +92,7 @@ export interface ConversationModel
makeQuote: any;
unblock: any;
deleteContact: any;
endSession: any;
endSession: () => Promise<void>;
block: any;
copyPublicKey: any;
getAvatar: any;

@ -1547,14 +1547,6 @@
},
async onSessionResetReceived() {
await this.setSessionResetStatus(SessionResetEnum.request_received);
// send empty message, this will trigger the new session to propagate
// to the reset initiator.
const user = new libsession.Types.PubKey(this.id);
const sessionEstablished = new window.libsession.Messages.Outgoing.SessionEstablishedMessage(
{ timestamp: Date.now() }
);
await libsession.getMessageQueue().send(user, sessionEstablished);
},
isSessionResetReceived() {

@ -232,8 +232,7 @@
};
}
window.log.error('Failed to fetch prekey:', keyId);
return undefined;
throw new textsecure.PreKeyMissing();
},
async loadPreKeyForContact(contactPubKey) {
const key = await window.Signal.Data.getPreKeyByRecipient(contactPubKey);

@ -928,10 +928,6 @@
}
},
endSession() {
this.model.endSession();
},
setDisappearingMessages(seconds) {
if (seconds > 0) {
this.model.updateExpirationTimer(seconds);

@ -226,6 +226,18 @@
}
}
function PreKeyMissing() {
this.name = 'PreKeyMissing';
Error.call(this, this.name);
// Maintains proper stack trace, where our error was thrown (only available on V8)
// via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
if (Error.captureStackTrace) {
Error.captureStackTrace(this);
}
}
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
@ -243,4 +255,5 @@
window.textsecure.PublicChatError = PublicChatError;
window.textsecure.PublicTokenError = PublicTokenError;
window.textsecure.SenderKeyMissing = SenderKeyMissing;
window.textsecure.PreKeyMissing = PreKeyMissing;
})();

@ -21,5 +21,6 @@ export interface LibTextsecure {
PublicChatError: any;
PublicTokenError: any;
SenderKeyMissing: any;
PreKeyMissing: any;
createTaskWithTimeout(task: any, id: any, options?: any): Promise<any>;
}

@ -447,7 +447,7 @@ export class SessionConversation extends React.Component<Props, State> {
},
onDeleteContact: () => conversation.deleteContact(),
onResetSession: () => {
conversation.endSession();
void conversation.endSession();
},
onShowSafetyNumber: () => {

@ -6,7 +6,10 @@ import { removeFromCache, updateCache } from './cache';
import { SignalService } from '../protobuf';
import * as Lodash from 'lodash';
import * as libsession from '../session';
import { handleSessionRequestMessage } from './sessionHandling';
import {
handleEndSession,
handleSessionRequestMessage,
} from './sessionHandling';
import { handlePairingAuthorisationMessage } from './multidevice';
import { MediumGroupRequestKeysMessage } from '../session/messages/outgoing';
import { MultiDeviceProtocol, SessionProtocol } from '../session/protocols';
@ -169,16 +172,16 @@ async function decryptUnidentifiedSender(
window.log.info(
'Dropping blocked message with error after sealed sender decryption'
);
await removeFromCache(envelope);
return null;
}
// eslint-disable-next-line no-param-reassign
// eslint-disable no-param-reassign
envelope.source = source.getName();
// eslint-disable-next-line no-param-reassign
envelope.sourceDevice = source.getDeviceId();
// eslint-disable-next-line no-param-reassign
envelope.unidentifiedDeliveryReceived = !originalSource;
// eslint-enable no-param-reassign
await removeFromCache(envelope);
throw error;
}
@ -257,6 +260,7 @@ async function doDecrypt(
}
}
// tslint:disable-next-line: max-func-body-length
async function decrypt(
envelope: EnvelopePlus,
ciphertext: ArrayBuffer
@ -309,6 +313,17 @@ async function decrypt(
return;
}
} else if (error instanceof window.textsecure.PreKeyMissing) {
const convo = window.ConversationController.get(envelope.source);
if (!convo) {
window.console.warn(
'PreKeyMissing but convo is missing too. Dropping...'
);
return;
}
void convo.endSession();
return;
}
let errorToThrow = error;

@ -286,14 +286,16 @@ export async function handleDataMessage(
return;
}
// tslint:disable-next-line no-bitwise
// tslint:disable no-bitwise
if (
dataMessage.flags &&
dataMessage.flags & SignalService.DataMessage.Flags.END_SESSION
) {
await handleEndSession(envelope.source);
return;
return removeFromCache(envelope);
}
// tslint:enable no-bitwise
const message = await processDecrypted(envelope, dataMessage);
const ourPubKey = window.textsecure.storage.user.getNumber();
const senderPubKey = envelope.senderIdentity || envelope.source;
@ -302,7 +304,7 @@ export async function handleDataMessage(
const { UNPAIRING_REQUEST } = SignalService.DataMessage.Flags;
// eslint-disable-next-line no-bitwise
// tslint:disable-next-line: no-bitwise
const isUnpairingRequest = Boolean(message.flags & UNPAIRING_REQUEST);
if (isUnpairingRequest) {

@ -14,6 +14,8 @@ export async function handleEndSession(number: string): Promise<void> {
try {
const conversation = ConversationController.get(number);
if (conversation) {
// this just marks the conversation as being waiting for a new session
// it does trigger a message to be sent. (the message is sent from handleSessionRequestMessage())
await conversation.onSessionResetReceived();
} else {
throw new Error();
@ -27,7 +29,7 @@ export async function handleSessionRequestMessage(
envelope: EnvelopePlus,
preKeyBundleMessage: SignalService.IPreKeyBundleMessage
) {
const { libsignal, libloki, StringView, textsecure, dcodeIO, log } = window;
const { libsignal, StringView, textsecure, dcodeIO, log } = window;
window.console.log(
`Received SESSION_REQUEST from source: ${envelope.source}`

@ -2,6 +2,7 @@ import { ContentMessage } from './ContentMessage';
import { SignalService } from '../../../../protobuf';
import { MessageParams } from '../Message';
import { Constants } from '../../..';
import * as crypto from 'crypto';
export interface PreKeyBundleType {
identityKey: Uint8Array;
@ -19,10 +20,19 @@ interface SessionRequestParams extends MessageParams {
export class SessionRequestMessage extends ContentMessage {
private readonly preKeyBundle: PreKeyBundleType;
private readonly padding: Buffer;
constructor(params: SessionRequestParams) {
super({ timestamp: params.timestamp, identifier: params.identifier });
this.preKeyBundle = params.preKeyBundle;
// Generate a random int from 1 and 512
const buffer = crypto.randomBytes(1);
// tslint:disable-next-line: no-bitwise
const paddingLength = (new Uint8Array(buffer)[0] & 0x1ff) + 1;
// Generate a random padding buffer of the chosen size
this.padding = crypto.randomBytes(paddingLength);
}
public ttl(): number {
@ -36,7 +46,7 @@ export class SessionRequestMessage extends ContentMessage {
protected contentProto(): SignalService.Content {
const nullMessage = new SignalService.NullMessage({});
const preKeyBundleMessage = this.getPreKeyBundleMessage();
nullMessage.padding = this.padding;
return new SignalService.Content({
nullMessage,
preKeyBundleMessage,

Loading…
Cancel
Save