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

Gracefully handle unrecognized HPKE algorithms #412

Merged
merged 1 commit into from
Sep 15, 2023
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
101 changes: 67 additions & 34 deletions packages/dap/src/hpkeConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,35 @@ describe("DAP HpkeConfigList", () => {
});

it("selects the first config that it recognizes", () => {
const list = HpkeConfigList.parse(
Buffer.from(
"0022" + // Overall length prefix
// Unrecognized configuration first
"64" + // id
"0064" + // kem_id
"0064" + // kdf_id
"0064" + // aead_id
"0008" + // Length prefix for public key
"4141414141414141" + // public_key
// Valid configuration
"ff" + // id
"0010" + // kem_id, KemId.DhkemP256HkdfSha256
"0001" + // kdf_id, KdfId.HkdfSha256
"0001" + // aead_id, AeadId.Aes128Gcm
"0008" + // Length prefix for public_key
"4141414141414141", // public_key
"hex",
),
);

const validConfig = new HpkeConfig(
255,
KemId.DhkemP256HkdfSha256,
KdfId.HkdfSha256,
AeadId.Aes128Gcm,
Buffer.from("public key"),
Buffer.from("AAAAAAAA"),
);

const invalidConfig = new HpkeConfig(
100,
KemId.DhkemX25519HkdfSha256,
KdfId.HkdfSha512,
AeadId.Chacha20Poly1305,
Buffer.from("public key"),
);

// none of these are known ids, so we skip the invalid config
invalidConfig.aeadId = 100;
invalidConfig.kdfId = 100;
invalidConfig.kemId = 100;

const list = new HpkeConfigList([invalidConfig, validConfig]);

assert.deepEqual(list.selectConfig(), validConfig);
});
});
Expand Down Expand Up @@ -144,33 +150,60 @@ describe("DAP HpkeConfig", () => {
}, /id must be an integer in \[0, 255\]/);
});

it("cannot be built from an unrecognized kemId", () => {
it("cannot be built from an invalid kemId", () => {
for (const badKemId of [-1, 65536, 0.5, NaN]) {
assert.throws(() => {
new HpkeConfig(0, badKemId, 1, 1, Buffer.alloc(10));
}, /kemId must be an integer in \[0, 65535\]/);
}
});

it("cannot be buit from an invalid kdfId", () => {
for (const badKdfId of [-1, 65536, 0.5, NaN]) {
assert.throws(() => {
new HpkeConfig(0, 1, badKdfId, 1, Buffer.alloc(10));
}, /kdfId must be an integer in \[0, 65535\]/);
}
});

it("cannot be built from an invalid aeadId", () => {
for (const badAeadId of [-1, 65536, 0.5, NaN]) {
assert.throws(() => {
new HpkeConfig(0, 1, 1, badAeadId, Buffer.alloc(10));
}, /aeadId must be an integer in \[0, 65535\]/);
}
});

it("cannot be used if it contains an unrecognized kemId", () => {
const config = new HpkeConfig(10, 10, 1, 1, Buffer.alloc(10));
assert.throws(() => {
new HpkeConfig(10, 10, 1, 1, Buffer.alloc(10));
config.cipherSuite();
}, /kemId was 10 but must be one of the following:/);
});

it("cannot be built from an unrecognized kdfId", () => {
it("cannot be used if it contains an unrecognized kdfId", () => {
const config = new HpkeConfig(
100,
KemId.DhkemP256HkdfSha256,
50,
AeadId.Chacha20Poly1305,
Buffer.alloc(10),
);
assert.throws(() => {
new HpkeConfig(
100,
KemId.DhkemP256HkdfSha256,
50,
AeadId.Chacha20Poly1305,
Buffer.alloc(10),
);
config.cipherSuite();
}, /kdfId was 50 but must be one of the following:/);
});

it("cannot be built from an unrecognized aeadId", () => {
it("cannot be used if it contains an unrecognized aeadId", () => {
const config = new HpkeConfig(
100,
KemId.DhkemP256HkdfSha256,
KdfId.HkdfSha512,
5,
Buffer.alloc(10),
);
assert.throws(() => {
new HpkeConfig(
100,
KemId.DhkemP256HkdfSha256,
KdfId.HkdfSha512,
5,
Buffer.alloc(10),
);
config.cipherSuite();
}, /aeadId was 5 but must be one of the following:/);
});

Expand Down
20 changes: 16 additions & 4 deletions packages/dap/src/hpkeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,18 @@ export class HpkeConfig implements Encodable {
if (id !== Math.floor(id) || id < 0 || id > 255) {
throw new Error("id must be an integer in [0, 255]");
}

this.validate(KemId, "kemId");
this.validate(KdfId, "kdfId");
this.validate(AeadId, "aeadId");
if (kemId !== Math.floor(kemId) || kemId < 0 || kemId > 0xffff) {
jbr marked this conversation as resolved.
Show resolved Hide resolved
throw new Error("kemId must be an integer in [0, 65535]");
}
if (kdfId !== Math.floor(kdfId) || kdfId < 0 || kdfId > 0xffff) {
throw new Error("kdfId must be an integer in [0, 65535]");
}
if (aeadId !== Math.floor(aeadId) || aeadId < 0 || aeadId > 0xffff) {
throw new Error("aeadId must be an integer in [0, 65535]");
}
if (publicKey.length > 0xffff) {
throw new Error("publicKey must not be longer than 65535 bytes");
}
}

private validate(
Expand Down Expand Up @@ -92,6 +100,10 @@ export class HpkeConfig implements Encodable {

/** @internal */
cipherSuite(): CipherSuite {
this.validate(KemId, "kemId");
this.validate(KdfId, "kdfId");
this.validate(AeadId, "aeadId");

const aead: AeadId = this.aeadId as AeadId;
const kdf: KdfId = this.kdfId as KdfId;
const kem: KemId = this.kemId as KemId;
Expand Down