Add IK -> XX fallback tests and fix things

This commit is contained in:
Belma Gutlic
2020-01-17 23:40:51 +01:00
parent 34bec6e1f4
commit 47e295add5
6 changed files with 59 additions and 24 deletions

View File

@ -14,6 +14,8 @@ export const uint16BEDecode = data => {
};
uint16BEDecode.bytes = 2;
// Note: IK and XX encoder usage is opposite (XX uses in stages encode0 where IK uses encode1)
export function encode0(message: MessageBuffer): bytes {
return Buffer.concat([message.ne, message.ciphertext]);
}

View File

@ -8,6 +8,7 @@ import {Buffer} from "buffer";
import {decode0, decode1, encode0, encode1} from "./encoder";
import {verifySignedPayload} from "./utils";
import {FailedIKError} from "./errors";
import {logger} from "./logger";
export class IKHandshake implements IHandshake {
public isInitiator: boolean;
@ -44,15 +45,16 @@ export class IKHandshake implements IHandshake {
public async stage0(): Promise<void> {
if (this.isInitiator) {
const messageBuffer = this.ik.sendMessage(this.session, this.payload);
this.connection.writeLP(encode0(messageBuffer));
this.connection.writeLP(encode1(messageBuffer));
} else {
const receivedMsg = await this.connection.readLP();
const receivedMessageBuffer = decode0(receivedMsg);
const receivedMsg = (await this.connection.readLP()).slice();
const receivedMessageBuffer = decode1(Buffer.from(receivedMsg));
const plaintext = this.ik.recvMessage(this.session, receivedMessageBuffer);
try {
await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id);
} catch (e) {
logger("Responder breaking up with IK handshake in stage 0.");
throw new FailedIKError(receivedMsg, `Error occurred while verifying initiator's signed payload: ${e.message}`);
}
}
@ -60,18 +62,19 @@ export class IKHandshake implements IHandshake {
public async stage1(): Promise<void> {
if (this.isInitiator) {
const receivedMsg = await this.connection.readLP();
const receivedMessageBuffer = decode1(receivedMsg);
const receivedMsg = (await this.connection.readLP()).slice();
const receivedMessageBuffer = decode0(Buffer.from(receivedMsg));
const plaintext = this.ik.recvMessage(this.session, receivedMessageBuffer);
try {
await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id);
} catch (e) {
logger("Initiator breaking up with IK handshake in stage 1.");
throw new FailedIKError(receivedMsg, `Error occurred while verifying responder's signed payload: ${e.message}`);
}
} else {
const messageBuffer = this.ik.sendMessage(this.session, this.payload);
this.connection.writeLP(encode1(messageBuffer));
this.connection.writeLP(encode0(messageBuffer));
}
}

View File

@ -39,37 +39,34 @@ export class XXFallbackHandshake extends XXHandshake {
this.xx.sendMessage(this.session, Buffer.alloc(0), this.ephemeralKeys);
logger("XX Fallback Stage 0 - Initialized state as the first message was sent by initiator.");
} else {
logger("XX Fallback Stage 0 - Responder waiting to receive first message...");
const receivedMessageBuffer = decode0(this.initialMsg);
this.xx.recvMessage(this.session, {
ne: receivedMessageBuffer.ne,
ns: Buffer.alloc(0),
ciphertext: Buffer.alloc(0),
});
logger("XX Fallback Stage 0 - Responder received first message.");
logger("XX Fallback Stage 0 - Responder used received message from IK.");
}
}
// stage 1
public async exchange(): Promise<void> {
if (this.isInitiator) {
logger('XX Fallback Stage 1 - Initiator waiting to receive first message from responder...');
const receivedMessageBuffer = decode1(this.initialMsg);
const plaintext = this.xx.recvMessage(this.session, receivedMessageBuffer);
logger('XX Fallback Stage 1 - Initiator received the message. Got remote\'s static key.');
logger('XX Fallback Stage 1 - Initiator used received message from IK.');
logger("Initiator going to check remote's signature...");
try {
await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id);
} catch (e) {
throw new Error(`Error occurred while verifying signed payload: ${e.message}`);
throw new Error(`Error occurred while verifying signed payload from responder: ${e.message}`);
}
logger("All good with the signature!");
} else {
logger('XX Fallback Stage 1 - Responder sending out first message with signed payload and static key.');
const messageBuffer = this.xx.sendMessage(this.session, this.payload);
this.connection.writeLP(encode1(messageBuffer));
logger('XX Fallback Stage 1 - Responder sent the second handshake message with signed payload.')
logger("XX Fallback Stage 1 - Responder start");
super.exchange();
logger("XX Fallback Stage 1 - Responder end");
}
}
}

View File

@ -63,7 +63,7 @@ export class XXHandshake implements IHandshake {
public async exchange(): Promise<void> {
if (this.isInitiator) {
logger('Stage 1 - Initiator waiting to receive first message from responder...');
const receivedMessageBuffer = decode1((await this.connection.readLP()).slice());
const receivedMessageBuffer = decode1(await this.connection.readLP());
const plaintext = this.xx.recvMessage(this.session, receivedMessageBuffer);
logger('Stage 1 - Initiator received the message. Got remote\'s static key.');

View File

@ -124,7 +124,7 @@ export class Noise implements INoiseConnection {
throw new Error("Remote static key should be initialized.");
}
const IKhandshake = new IKHandshake(isInitiator, payload, this.prologue, this.staticKeys, connection, remotePeer, foundRemoteStaticKey);
const IKhandshake = new IKHandshake(isInitiator, Buffer.from(payload), this.prologue, this.staticKeys, connection, remotePeer, foundRemoteStaticKey);
try {
return await this.performIKHandshake(IKhandshake);
} catch (e) {
@ -189,13 +189,8 @@ export class Noise implements INoiseConnection {
handshake: IKHandshake,
): Promise<IKHandshake> {
try {
await handshake.stage0();
await handshake.stage1();
} catch (e) {
console.error("Error in IK handshake: ", e);
throw e;
}
await handshake.stage0();
await handshake.stage1();
return handshake;
}