Bug 1921728 - Handle binary OpenPGP keys ending with whitespace. r=kaie
Differential Revision: https://phabricator.services.mozilla.com/D224194 --HG-- extra : rebase_source : c5a854f16d7c79dd1a5d61656084112d0da1bebc extra : amend_source : c612acf7f3aabde2eae2fa6e1ca4b7a92df88156
This commit is contained in:
Родитель
ec22ce64ae
Коммит
4e514030f2
|
@ -1758,19 +1758,6 @@ export var RNP = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getCharCodeArray(pgpData) {
|
|
||||||
return pgpData.split("").map(e => e.charCodeAt());
|
|
||||||
},
|
|
||||||
|
|
||||||
is8Bit(charCodeArray) {
|
|
||||||
for (let i = 0; i < charCodeArray.length; i++) {
|
|
||||||
if (charCodeArray[i] > 255) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts/Decodes an OpenPGP message, verify signatures, and
|
* Decrypts/Decodes an OpenPGP message, verify signatures, and
|
||||||
* return associated meta data.
|
* return associated meta data.
|
||||||
|
@ -2046,7 +2033,7 @@ export var RNP = {
|
||||||
default:
|
default:
|
||||||
useDecodedData = false;
|
useDecodedData = false;
|
||||||
processSignature = false;
|
processSignature = false;
|
||||||
console.warn(
|
lazy.log.warn(
|
||||||
"rnp_op_verify_execute returned unexpected: " + result.exitCode
|
"rnp_op_verify_execute returned unexpected: " + result.exitCode
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -2467,7 +2454,7 @@ export var RNP = {
|
||||||
acceptanceResult
|
acceptanceResult
|
||||||
);
|
);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.warn("Get acceptance FAILED!", ex);
|
lazy.log.warn("Get acceptance FAILED!", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unverified key acceptance means, we consider the signature OK,
|
// unverified key acceptance means, we consider the signature OK,
|
||||||
|
@ -2728,13 +2715,6 @@ export var RNP = {
|
||||||
throw new Error("no keyBlockStr parameter in importToFFI");
|
throw new Error("no keyBlockStr parameter in importToFFI");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof keyBlockStr != "string") {
|
|
||||||
throw new Error(
|
|
||||||
"keyBlockStr of unepected type importToFFI: %o",
|
|
||||||
keyBlockStr
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input might be either plain text or binary data.
|
// Input might be either plain text or binary data.
|
||||||
// If the input is binary, do not modify it.
|
// If the input is binary, do not modify it.
|
||||||
// If the input contains characters with a multi-byte char code value,
|
// If the input contains characters with a multi-byte char code value,
|
||||||
|
@ -2744,10 +2724,13 @@ export var RNP = {
|
||||||
// filter out.
|
// filter out.
|
||||||
|
|
||||||
// Remove comment lines.
|
// Remove comment lines.
|
||||||
const trimmed = keyBlockStr.replace(/^Comment:.*(\r?\n|\r)/gm, "").trim();
|
const input = keyBlockStr.includes("-----BEGIN PGP ")
|
||||||
const arr = this.getCharCodeArray(trimmed);
|
? keyBlockStr.replace(/^Comment:.*(\r?\n|\r)/gm, "")
|
||||||
if (!this.is8Bit(arr)) {
|
: keyBlockStr;
|
||||||
throw new Error(`Non-ascii key block: ${keyBlockStr}`);
|
const arr = lazy.MailStringUtils.byteStringToUint8Array(input);
|
||||||
|
if (arr.some(c => c > 255)) {
|
||||||
|
// Not 8-bit data.
|
||||||
|
throw new Error(`Multi-byte string input: ${input}`);
|
||||||
}
|
}
|
||||||
const key_array = lazy.ctypes.uint8_t.array()(arr);
|
const key_array = lazy.ctypes.uint8_t.array()(arr);
|
||||||
|
|
||||||
|
@ -2783,7 +2766,7 @@ export var RNP = {
|
||||||
jsonInfo.address()
|
jsonInfo.address()
|
||||||
);
|
);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
console.warn(`rnp_import_keys FAILED; rv=${rv}`);
|
lazy.log.warn(`rnp_import_keys FAILED; rv=${rv}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: parse jsonInfo and return a list of keys,
|
// TODO: parse jsonInfo and return a list of keys,
|
||||||
|
@ -2922,7 +2905,7 @@ export var RNP = {
|
||||||
jsonInfo.address()
|
jsonInfo.address()
|
||||||
);
|
);
|
||||||
if (rv) {
|
if (rv) {
|
||||||
console.warn(`rnp_import_signatures FAILED; rv=${rv}`);
|
lazy.log.warn(`rnp_import_signatures FAILED; rv=${rv}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: parse jsonInfo
|
// TODO: parse jsonInfo
|
||||||
|
@ -3073,7 +3056,7 @@ export var RNP = {
|
||||||
for (const k of keys) {
|
for (const k of keys) {
|
||||||
if (k.fpr.length > 40) {
|
if (k.fpr.length > 40) {
|
||||||
RNPLib.rnp_ffi_destroy(tempFFI);
|
RNPLib.rnp_ffi_destroy(tempFFI);
|
||||||
console.warn(
|
lazy.log.warn(
|
||||||
`Cannot import OpenPGP key with fingerprint ${k.fpr} because it is based on an unsupported specification.`
|
`Cannot import OpenPGP key with fingerprint ${k.fpr} because it is based on an unsupported specification.`
|
||||||
);
|
);
|
||||||
result.errorMsg = `Found unsupported key: ${k.fpr}`;
|
result.errorMsg = `Found unsupported key: ${k.fpr}`;
|
||||||
|
@ -3667,7 +3650,7 @@ export var RNP = {
|
||||||
for (const ak of aliasKeys) {
|
for (const ak of aliasKeys) {
|
||||||
const key = this.getKeyHandleByKeyIdOrFingerprint(RNPLib.ffi, "0x" + ak);
|
const key = this.getKeyHandleByKeyIdOrFingerprint(RNPLib.ffi, "0x" + ak);
|
||||||
if (!key || key.isNull()) {
|
if (!key || key.isNull()) {
|
||||||
console.warn(`Couldn't find key used by alias rule ${ak}`);
|
lazy.log.warn(`Couldn't find key used by alias rule ${ak}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.addSuitableEncryptKey(key, op);
|
this.addSuitableEncryptKey(key, op);
|
||||||
|
@ -4118,6 +4101,14 @@ export var RNP = {
|
||||||
return this.isExpiredTime(expirationSeconds);
|
return this.isExpiredTime(expirationSeconds);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find key by email.
|
||||||
|
*
|
||||||
|
* @param {string} id - Email, surrounded by angle brackets.
|
||||||
|
* @param {boolean} [onlyIfAcceptableAsRecipientKey=false] - Require matching
|
||||||
|
* key to be acceptable as recipient key.
|
||||||
|
* @returns {Promise<ctypes.voidptr_t>} key handle of matching key.
|
||||||
|
*/
|
||||||
async findKeyByEmail(id, onlyIfAcceptableAsRecipientKey = false) {
|
async findKeyByEmail(id, onlyIfAcceptableAsRecipientKey = false) {
|
||||||
if (!id.startsWith("<") || !id.endsWith(">") || id.includes(" ")) {
|
if (!id.startsWith("<") || !id.endsWith(">") || id.includes(" ")) {
|
||||||
throw new Error(`Invalid argument; id=${id}`);
|
throw new Error(`Invalid argument; id=${id}`);
|
||||||
|
@ -4244,7 +4235,7 @@ export var RNP = {
|
||||||
acceptanceResult
|
acceptanceResult
|
||||||
);
|
);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.warn("Get acceptance FAILED!", ex);
|
lazy.log.warn("Get acceptance FAILED!", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!acceptanceResult.emailDecided) {
|
if (!acceptanceResult.emailDecided) {
|
||||||
|
@ -4276,7 +4267,7 @@ export var RNP = {
|
||||||
RNPLib.rnp_uid_handle_destroy(uid_handle);
|
RNPLib.rnp_uid_handle_destroy(uid_handle);
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.warn(`Finding key by email=${id} FAILED`, ex);
|
lazy.log.warn(`Finding key by email=${id} FAILED`, ex);
|
||||||
} finally {
|
} finally {
|
||||||
if (have_handle) {
|
if (have_handle) {
|
||||||
RNPLib.rnp_key_handle_destroy(handle);
|
RNPLib.rnp_key_handle_destroy(handle);
|
||||||
|
@ -5091,7 +5082,7 @@ export var RNP = {
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
console.warn("rnp_key_export_autocrypt FAILED");
|
lazy.log.warn("rnp_key_export_autocrypt FAILED");
|
||||||
} else {
|
} else {
|
||||||
const result_buf = new lazy.ctypes.uint8_t.ptr();
|
const result_buf = new lazy.ctypes.uint8_t.ptr();
|
||||||
const result_len = new lazy.ctypes.size_t();
|
const result_len = new lazy.ctypes.size_t();
|
||||||
|
|
|
@ -106,3 +106,35 @@ add_task(async function testImportApple() {
|
||||||
"should find correct encryption subkey"
|
"should find correct encryption subkey"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test importing binary key that ends with a whitespace.
|
||||||
|
*/
|
||||||
|
add_task(async function testImportBinaryPubSpace() {
|
||||||
|
// Note: This key artifact includes subpacket 39 (v6 preferred AEAD
|
||||||
|
// ciphersuites), which support is defined only in RFC 9580.
|
||||||
|
|
||||||
|
const ids = await OpenPGPTestUtils.importKey(
|
||||||
|
null,
|
||||||
|
do_get_file(
|
||||||
|
`${KEY_DIR}/DC1A523730F62AE8-pub-does_not_expire-ends_with_whitespace.pgp`
|
||||||
|
),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
Assert.equal(ids.length, 1, "should have imported the key");
|
||||||
|
Assert.equal(ids[0], "0xDC1A523730F62AE8", "should be the correct key");
|
||||||
|
await OpenPGPTestUtils.updateKeyIdAcceptance(
|
||||||
|
ids,
|
||||||
|
OpenPGPTestUtils.ACCEPTANCE_VERIFIED
|
||||||
|
);
|
||||||
|
|
||||||
|
const primaryKey = await RNP.findKeyByEmail("<test@example.com>", true);
|
||||||
|
Assert.ok(primaryKey, "should find primary key");
|
||||||
|
const encSubKey = RNP.getSuitableSubkey(primaryKey, "encrypt");
|
||||||
|
const keyId = RNP.getKeyIDFromHandle(encSubKey);
|
||||||
|
Assert.equal(
|
||||||
|
keyId,
|
||||||
|
"653B0BC4ADE0A239",
|
||||||
|
"should find correct encryption subkey"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
Двоичные данные
mail/test/browser/openpgp/data/keys/DC1A523730F62AE8-pub-does_not_expire-ends_with_whitespace.pgp
Normal file
Двоичные данные
mail/test/browser/openpgp/data/keys/DC1A523730F62AE8-pub-does_not_expire-ends_with_whitespace.pgp
Normal file
Двоичный файл не отображается.
Загрузка…
Ссылка в новой задаче