Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 samples #4997

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
79 changes: 60 additions & 19 deletions protection-samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,40 @@ require('buffer');
const assert = require('assert');
const crypto = require('crypto');

const INITIAL_SALT = Buffer.from('38762cf7f55934b34d179ae6a4c80cadccbb7f0a', 'hex');
const RETRY_KEY = Buffer.from('be0c690b9f66575a1d766b54e368c84e', 'hex');
const RETRY_NONCE = Buffer.from('461599d35d632bf2239825bb', 'hex');
const SHA256 = 'sha256';
const AES_GCM = 'aes-128-gcm';
const AES_ECB = 'aes-128-ecb';

const version = '00000001';
const V1 = '00000001';
const V2 = '6b3343cf';
const VERSION_INFO = {
'00000001': {
initial: 'c',
retry: 'f',
initial_salt: Buffer.from('38762cf7f55934b34d179ae6a4c80cadccbb7f0a', 'hex'),
retry_secret: Buffer.from('d9c9943e6101fd200021506bcc02814c73030f25c79d71ce876eca876e6fca8e', 'hex'),
retry_key: Buffer.from('be0c690b9f66575a1d766b54e368c84e', 'hex'),
retry_nonce: Buffer.from('461599d35d632bf2239825bb', 'hex'),
label_prefix: 'quic ',
},
'6b3343cf': {
initial: 'd',
retry: 'c',
initial_salt: Buffer.from('0dede3def700a6db819381be6e269dcbf9bd2ed9', 'hex'),
retry_secret: Buffer.from('c4dd2484d681aefa4ff4d69c2c20299984a765a5d3c31982f38fc74162155e9f', 'hex'),
retry_key: Buffer.from('8fb4b01b56ac48e260fbcbcead7ccc92', 'hex'),
retry_nonce: Buffer.from('d86969bc2d7c6d9990efb04a', 'hex'),
label_prefix: 'quicv2 ',
},
};
const VERSION_MAP = {
'1': V1,
'2': V2,
'v1': V1,
'v2': V2,
};

var version = V1;

function chunk(s, n) {
return (new Array(Math.ceil(s.length / n)))
Expand Down Expand Up @@ -100,15 +126,15 @@ function applyNonce(iv, counter) {

class InitialProtection {
constructor(label, cid) {
var qhkdf = QHKDF.extract(SHA256, INITIAL_SALT, cid);
var qhkdf = QHKDF.extract(SHA256, VERSION_INFO[version].initial_salt, cid);
log('initial_secret', qhkdf.prk);
qhkdf = new QHKDF(qhkdf.hmac, qhkdf.expand_label(label, 32));
log(label + ' secret', qhkdf.prk);
this.key = qhkdf.expand_label("quic key", 16);
this.key = qhkdf.expand_label(VERSION_INFO[version].label_prefix + 'key', 16);
log(label + ' key', this.key);
this.iv = qhkdf.expand_label("quic iv", 12);
this.iv = qhkdf.expand_label(VERSION_INFO[version].label_prefix + 'iv', 12);
log(label + ' iv', this.iv);
this.hp = qhkdf.expand_label("quic hp", 16);
this.hp = qhkdf.expand_label(VERSION_INFO[version].label_prefix + 'hp', 16);
log(label + ' hp', this.hp);
}

Expand Down Expand Up @@ -203,7 +229,9 @@ class InitialProtection {
var hdr_len = 1 + 4;
hdr_len += 1 + data[hdr_len]; // DCID
hdr_len += 1 + data[hdr_len]; // SCID
if ((data[0] & 0x30) === 0) { // Initial packet: token.
let initial0 = Buffer.from(VERSION_INFO[version].initial + '0', 'hex')[0];
if ((data[0] & 0x30) === (initial0 & 0x30)) {
// Initial packet: token.
if ((data[hdr_len] & 0xc0) !== 0) {
throw new Error('multi-byte token length unsupported');
}
Expand Down Expand Up @@ -251,7 +279,8 @@ function test(role, cid, hdr, pn, body) {
body = Buffer.from(body, 'hex');
log('body', hdr);

if (role === 'client' && (hdr[0] & 0x30) === 0) {
let initial0 = Buffer.from(VERSION_INFO[version].initial + '0', 'hex')[0];
if (role === 'client' && (hdr[0] & 0x30) === (initial0 & 0x30)) {
body = pad(hdr, body);
}

Expand All @@ -272,26 +301,27 @@ function hex_cid(cid) {

// Verify that the retry keys are correct.
function derive_retry() {
let secret = Buffer.from('d9c9943e6101fd200021506bcc02814c73030f25c79d71ce876eca876e6fca8e', 'hex');
let secret = VERSION_INFO[version].retry_secret;
let qhkdf = new QHKDF(new HMAC(SHA256), secret);
let key = qhkdf.expand_label("quic key", 16);
let key = qhkdf.expand_label(VERSION_INFO[version].label_prefix + 'key', 16);
log('retry key', key);
assert.deepStrictEqual(key, RETRY_KEY);
let nonce = qhkdf.expand_label("quic iv", 12);
assert.deepStrictEqual(key, VERSION_INFO[version].retry_key);
let nonce = qhkdf.expand_label(VERSION_INFO[version].label_prefix + 'iv', 12);
log('retry nonce', nonce);
assert.deepStrictEqual(nonce, RETRY_NONCE);
assert.deepStrictEqual(nonce, VERSION_INFO[version].retry_nonce);
}

function retry(dcid, scid, odcid) {
var pfx = Buffer.from(hex_cid(odcid), 'hex');
var encoded = Buffer.from('ff' + version + hex_cid(dcid) + hex_cid(scid), 'hex');
var encoded = Buffer.from(VERSION_INFO[version].retry + 'f' + version + hex_cid(dcid) + hex_cid(scid), 'hex');
var token = Buffer.from('token', 'ascii');
var header = Buffer.concat([encoded, token]);
log('retry header', header);
var aad = Buffer.concat([pfx, header]);
log('retry aad', aad);

var gcm = crypto.createCipheriv(AES_GCM, RETRY_KEY, RETRY_NONCE);
var gcm = crypto.createCipheriv(AES_GCM, VERSION_INFO[version].retry_key,
VERSION_INFO[version].retry_nonce);
gcm.setAAD(aad);
gcm.update('');
gcm.final();
Expand Down Expand Up @@ -331,9 +361,20 @@ function chacha20(pn, payload) {
log('protected packet', Buffer.concat([header, ct]));
}

if (process.argv.length > 2) {
if (VERSION_INFO[process.argv[2]]) {
version = process.argv[2];
} if (VERSION_MAP[process.argv[2]]) {
version = VERSION_MAP[process.argv[2]];
} else {
console.warn(`unknown version: ${process.argv[2]}`);
process.exit(2);
}
}

var cid = '8394c8f03e515708';

var ci_hdr = 'c3' + version + hex_cid(cid) + '0000';
var ci_hdr = VERSION_INFO[version].initial + '3' + version + hex_cid(cid) + '0000';
// This is a client Initial.
var crypto_frame = '060040f1' +
'010000ed0303ebf8fa56f12939b9584a3896472ec40bb863cfd3e86804fe3a47' +
Expand All @@ -355,7 +396,7 @@ var frames = '02000000000600405a' +
'690b84d08a60993c144eca684d1081287c834d5311' +
'bcf32bb9da1a002b00020304';
var scid = 'f067a5502a4262b5';
var si_hdr = 'c1' + version + '00' + hex_cid(scid) + '00';
var si_hdr = VERSION_INFO[version].initial + '1' + version + '00' + hex_cid(scid) + '00';
test('server', cid, si_hdr, 1, frames);

derive_retry();
Expand Down