mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-27 18:17:22 +02:00
LibWeb: Handle raw-secret key formats in wrap_key
Refresh the imported wrapKey_unwrapKey WPT to the current upstream version and treat the raw-secret and other raw* formats like raw when wrap_key() and unwrap_key() serialize wrapped key bytes. The updated test covers ChaCha20-Poly1305 wrapping with the raw-secret format. Accepting the full set of byte-oriented raw formats lets those keys round-trip through wrapKey and unwrapKey.
This commit is contained in:
committed by
Andreas Kling
parent
3726df5a9e
commit
52c46483d1
Notes:
github-actions[bot]
2026-03-29 11:23:14 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/52c46483d1b Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8665
@@ -40,6 +40,11 @@
|
||||
name: "AES-KW",
|
||||
importParameters: {name: "AES-KW", length: 128},
|
||||
wrapParameters: {name: "AES-KW"}
|
||||
},
|
||||
{
|
||||
name: 'ChaCha20-Poly1305',
|
||||
importParameters: {name: "ChaCha20-Poly1305"},
|
||||
wrapParameters: {name: "ChaCha20-Poly1305", iv: new Uint8Array(12), additionalData: new Uint8Array(16)}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -57,7 +62,8 @@
|
||||
{algorithm: {name: "AES-CBC", length: 128}, usages: ["encrypt", "decrypt"]},
|
||||
{algorithm: {name: "AES-GCM", length: 128}, usages: ["encrypt", "decrypt"]},
|
||||
{algorithm: {name: "AES-KW", length: 128}, usages: ["wrapKey", "unwrapKey"]},
|
||||
{algorithm: {name: "HMAC", length: 128, hash: "SHA-256"}, usages: ["sign", "verify"]}
|
||||
{algorithm: {name: "HMAC", length: 128, hash: "SHA-256"}, usages: ["sign", "verify"]},
|
||||
{algorithm: {name: "ChaCha20-Poly1305"}, usages: ['encrypt', 'decrypt']}
|
||||
];
|
||||
|
||||
// Import all the keys needed, then iterate over all combinations
|
||||
@@ -69,7 +75,7 @@
|
||||
var wrapper = wrappers[wrapperParam.name];
|
||||
keysToWrapParameters.filter((param) => Object.keys(keys).includes(param.algorithm.name)).forEach(function(toWrapParam) {
|
||||
var keyData = keys[toWrapParam.algorithm.name];
|
||||
["raw", "spki", "pkcs8"].filter((fmt) => Object.keys(keyData).includes(fmt)).forEach(function(keyDataFormat) {
|
||||
["raw", "raw-secret", "spki", "pkcs8"].filter((fmt) => Object.keys(keyData).includes(fmt)).forEach(function(keyDataFormat) {
|
||||
var toWrap = keyData[keyDataFormat];
|
||||
[keyDataFormat, "jwk"].forEach(function(format) {
|
||||
if (wrappingIsPossible(toWrap.originalExport[format], wrapper.parameters.name)) {
|
||||
@@ -106,9 +112,15 @@
|
||||
.then(function(key) {
|
||||
wrappers["RSA-OAEP"].unwrappingKey = key;
|
||||
}));
|
||||
} else if (params.name === "ChaCha20-Poly1305") {
|
||||
var algorithm = {name: params.name};
|
||||
promises.push(subtle.importKey("raw-secret", wrappingKeyData["SYMMETRIC256"].raw, algorithm, true, ["wrapKey", "unwrapKey"])
|
||||
.then(function(key) {
|
||||
wrappers[params.name] = {wrappingKey: key, unwrappingKey: key, parameters: params};
|
||||
}));
|
||||
} else {
|
||||
var algorithm = {name: params.name};
|
||||
promises.push(subtle.importKey("raw", wrappingKeyData["SYMMETRIC"].raw, algorithm, true, ["wrapKey", "unwrapKey"])
|
||||
promises.push(subtle.importKey("raw", wrappingKeyData["SYMMETRIC128"].raw, algorithm, true, ["wrapKey", "unwrapKey"])
|
||||
.then(function(key) {
|
||||
wrappers[params.name] = {wrappingKey: key, unwrappingKey: key, parameters: params};
|
||||
}));
|
||||
@@ -151,9 +163,12 @@
|
||||
var keyData = toWrapKeyDataFromAlg(params.algorithm.name);
|
||||
promises.push(importAndExport("spki", keyData.spki, params.algorithm, params.publicUsages, "public key "));
|
||||
promises.push(importAndExport("pkcs8", keyData.pkcs8, params.algorithm, params.privateUsages, "private key "));
|
||||
} else if (params.algorithm.name === "ChaCha20-Poly1305") {
|
||||
keys[params.algorithm.name] = {};
|
||||
promises.push(importAndExport("raw-secret", toWrapKeyData["SYMMETRIC256"].raw, params.algorithm, params.usages, ""));
|
||||
} else {
|
||||
keys[params.algorithm.name] = {};
|
||||
promises.push(importAndExport("raw", toWrapKeyData["SYMMETRIC"].raw, params.algorithm, params.usages, ""));
|
||||
promises.push(importAndExport("raw", toWrapKeyData["SYMMETRIC128"].raw, params.algorithm, params.usages, ""));
|
||||
}
|
||||
});
|
||||
// Using allSettled to skip unsupported test cases.
|
||||
@@ -292,79 +307,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Are two array buffers the same?
|
||||
function equalBuffers(a, b) {
|
||||
if (a.byteLength !== b.byteLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var aBytes = new Uint8Array(a);
|
||||
var bBytes = new Uint8Array(b);
|
||||
|
||||
for (var i=0; i<a.byteLength; i++) {
|
||||
if (aBytes[i] !== bBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Are two Jwk objects "the same"? That is, does the object returned include
|
||||
// matching values for each property that was expected? It's okay if the
|
||||
// returned object has extra methods; they aren't checked.
|
||||
function equalJwk(expected, got) {
|
||||
var fields = Object.keys(expected);
|
||||
var fieldName;
|
||||
|
||||
for(var i=0; i<fields.length; i++) {
|
||||
fieldName = fields[i];
|
||||
if (!(fieldName in got)) {
|
||||
return false;
|
||||
}
|
||||
if (objectToString(expected[fieldName]) !== objectToString(got[fieldName])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Character representation of any object we may use as a parameter.
|
||||
function objectToString(obj) {
|
||||
var keyValuePairs = [];
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return "[" + obj.map(function(elem){return objectToString(elem);}).join(", ") + "]";
|
||||
} else if (typeof obj === "object") {
|
||||
Object.keys(obj).sort().forEach(function(keyName) {
|
||||
keyValuePairs.push(keyName + ": " + objectToString(obj[keyName]));
|
||||
});
|
||||
return "{" + keyValuePairs.join(", ") + "}";
|
||||
} else if (typeof obj === "undefined") {
|
||||
return "undefined";
|
||||
} else {
|
||||
return obj.toString();
|
||||
}
|
||||
|
||||
var keyValuePairs = [];
|
||||
|
||||
Object.keys(obj).sort().forEach(function(keyName) {
|
||||
var value = obj[keyName];
|
||||
if (typeof value === "object") {
|
||||
value = objectToString(value);
|
||||
} else if (typeof value === "array") {
|
||||
value = "[" + value.map(function(elem){return objectToString(elem);}).join(", ") + "]";
|
||||
} else {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
keyValuePairs.push(keyName + ": " + value);
|
||||
});
|
||||
|
||||
return "{" + keyValuePairs.join(", ") + "}";
|
||||
}
|
||||
|
||||
// Can we compare key values by using them
|
||||
function canCompareNonExtractableKeys(key){
|
||||
if (key.usages.indexOf("decrypt") !== -1) {
|
||||
@@ -432,6 +374,9 @@
|
||||
case "ECDH" :
|
||||
deriveParams = {name: "ECDH"};
|
||||
break;
|
||||
case "ChaCha20-Poly1305":
|
||||
cryptParams = {name: "ChaCha20-Poly1305", iv: new Uint8Array(12)};
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported algorithm for key comparison");
|
||||
}
|
||||
|
||||
@@ -14,8 +14,11 @@ let wrappingKeyData = {
|
||||
qi: "JHmVKb1zwW5iRR6RCeexYnh2fmY-3DrPSdM8Dxhr0F8dayi-tlRqEdnG0hvp45n8gLUskWWcB9EXlUJObZGKDfGuxgMa3g_xeLA2vmFQ12MxPsyH4iCNZvsgmGxx7TuOHrnDh5EBVnM4_de63crEJON2sYI8Ozi-xp2OEmAr2seWKq4sxkFni6exLhqb-NE4m9HMKlng1EtQh2rLBFG1VYD3SYYpMLc5fxzqGvSxn3Fa-Xgg-IZPY3ubrcm52KYgmLUGmnYStfVqGSWSdhDXHlNgI5pdAA0FzpyBk3ZX-JsxhwcnneKrYBBweq06kRMGWgvdbdAQ-7wSeGqqj5VPwA"
|
||||
},
|
||||
},
|
||||
"SYMMETRIC": {
|
||||
"SYMMETRIC128": {
|
||||
raw: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
},
|
||||
"SYMMETRIC256": {
|
||||
raw: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +89,11 @@ let toWrapKeyData = {
|
||||
kty: "OKP"
|
||||
}
|
||||
},
|
||||
"SYMMETRIC": {
|
||||
"SYMMETRIC128": {
|
||||
raw: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
},
|
||||
"SYMMETRIC256": {
|
||||
raw: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user