diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /security/manager/ssl/tests/unit/test_oskeystore.js | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/manager/ssl/tests/unit/test_oskeystore.js')
-rw-r--r-- | security/manager/ssl/tests/unit/test_oskeystore.js | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/security/manager/ssl/tests/unit/test_oskeystore.js b/security/manager/ssl/tests/unit/test_oskeystore.js new file mode 100644 index 0000000000..fcc9de6c59 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_oskeystore.js @@ -0,0 +1,272 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ +"use strict"; + +// Tests the methods and attributes for interfacing with nsIOSKeyStore. + +// Ensure that the appropriate initialization has happened. +do_get_profile(); + +const LABELS = ["mylabel1", "mylabel2", "mylabel3"]; + +async function delete_all_secrets() { + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + for (let label of LABELS) { + if (await keystore.asyncSecretAvailable(label)) { + await keystore.asyncDeleteSecret(label); + ok( + !(await keystore.asyncSecretAvailable(label)), + label + " should be deleted now." + ); + } + } +} + +async function encrypt_decrypt_test() { + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + ok( + !(await keystore.asyncSecretAvailable(LABELS[0])), + "The secret should not be available yet." + ); + + let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok(recoveryPhrase, "A recovery phrase should've been created."); + let recoveryPhrase2 = await keystore.asyncGenerateSecret(LABELS[1]); + ok(recoveryPhrase2, "A recovery phrase should've been created."); + + let text = new Uint8Array([0x01, 0x00, 0x01]); + let ciphertext = ""; + try { + ciphertext = await keystore.asyncEncryptBytes(LABELS[0], text); + ok(ciphertext, "We should have a ciphertext now."); + } catch (e) { + ok(false, "Error encrypting " + e); + } + + // Decrypting should give us the plaintext bytes again. + try { + let plaintext = await keystore.asyncDecryptBytes(LABELS[0], ciphertext); + ok( + plaintext.toString() == text.toString(), + "Decrypted plaintext should be the same as text." + ); + } catch (e) { + ok(false, "Error decrypting ciphertext " + e); + } + + // Decrypting with a wrong key should throw an error. + try { + await keystore.asyncDecryptBytes(LABELS[1], ciphertext); + ok(false, "Decrypting with the wrong key should fail."); + } catch (e) { + ok(true, "Decrypting with the wrong key should fail " + e); + } +} + +add_task(async function () { + await delete_all_secrets(); + await encrypt_decrypt_test(); + await delete_all_secrets(); +}); + +// Test that using a recovery phrase works. +add_task(async function () { + await delete_all_secrets(); + + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + + let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok(recoveryPhrase, "A recovery phrase should've been created."); + + let text = new Uint8Array([0x01, 0x00, 0x01]); + let ciphertext = await keystore.asyncEncryptBytes(LABELS[0], text); + ok(ciphertext, "We should have a ciphertext now."); + + await keystore.asyncDeleteSecret(LABELS[0]); + // Decrypting should fail after deleting the secret. + await keystore + .asyncDecryptBytes(LABELS[0], ciphertext) + .then(() => + ok(false, "decrypting didn't throw as expected after deleting the secret") + ) + .catch(() => + ok(true, "decrypting threw as expected after deleting the secret") + ); + + await keystore.asyncRecoverSecret(LABELS[0], recoveryPhrase); + let plaintext = await keystore.asyncDecryptBytes(LABELS[0], ciphertext); + ok( + plaintext.toString() == text.toString(), + "Decrypted plaintext should be the same as text." + ); + + await delete_all_secrets(); +}); + +// Test that trying to use a non-base64 recovery phrase fails. +add_task(async function () { + await delete_all_secrets(); + + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + await keystore + .asyncRecoverSecret(LABELS[0], "@##$^&*()#$^&*(@#%&*_") + .then(() => + ok(false, "base64-decoding non-base64 should have failed but didn't") + ) + .catch(() => ok(true, "base64-decoding non-base64 failed as expected")); + + ok( + !(await keystore.asyncSecretAvailable(LABELS[0])), + "we didn't recover a secret, so the secret shouldn't be available" + ); + let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok( + recoveryPhrase && !!recoveryPhrase.length, + "we should be able to re-use that label to generate a new secret" + ); + await delete_all_secrets(); +}); + +// Test that re-using a label overwrites any previously-stored secret. +add_task(async function () { + await delete_all_secrets(); + + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + + let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok(recoveryPhrase, "A recovery phrase should've been created."); + + let text = new Uint8Array([0x66, 0x6f, 0x6f, 0x66]); + let ciphertext = await keystore.asyncEncryptBytes(LABELS[0], text); + ok(ciphertext, "We should have a ciphertext now."); + + let newRecoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok(newRecoveryPhrase, "A new recovery phrase should've been created."); + + // The new secret replaced the old one so we shouldn't be able to decrypt the ciphertext now. + await keystore + .asyncDecryptBytes(LABELS[0], ciphertext) + .then(() => + ok(false, "decrypting without the original key should have failed") + ) + .catch(() => + ok(true, "decrypting without the original key failed as expected") + ); + + await keystore.asyncRecoverSecret(LABELS[0], recoveryPhrase); + let plaintext = await keystore.asyncDecryptBytes(LABELS[0], ciphertext); + ok( + plaintext.toString() == text.toString(), + "Decrypted plaintext should be the same as text (once we have the original key again)." + ); + + await delete_all_secrets(); +}); + +// Test that re-using a label (this time using a recovery phrase) overwrites any previously-stored +// secret. +add_task(async function () { + await delete_all_secrets(); + + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + + let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok(recoveryPhrase, "A recovery phrase should've been created."); + + let newRecoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok(newRecoveryPhrase, "A new recovery phrase should've been created."); + + let text = new Uint8Array([0x66, 0x6f, 0x6f, 0x66]); + let ciphertext = await keystore.asyncEncryptBytes(LABELS[0], text); + ok(ciphertext, "We should have a ciphertext now."); + + await keystore.asyncRecoverSecret(LABELS[0], recoveryPhrase); + + // We recovered the old secret, so decrypting ciphertext that had been encrypted with the newer + // key should fail. + await keystore + .asyncDecryptBytes(LABELS[0], ciphertext) + .then(() => ok(false, "decrypting without the new key should have failed")) + .catch(() => ok(true, "decrypting without the new key failed as expected")); + + await keystore.asyncRecoverSecret(LABELS[0], newRecoveryPhrase); + let plaintext = await keystore.asyncDecryptBytes(LABELS[0], ciphertext); + ok( + plaintext.toString() == text.toString(), + "Decrypted plaintext should be the same as text (once we have the new key again)." + ); + + await delete_all_secrets(); +}); + +// Test that trying to use recovery phrases that are the wrong size fails. +add_task(async function () { + await delete_all_secrets(); + + let keystore = Cc["@mozilla.org/security/oskeystore;1"].getService( + Ci.nsIOSKeyStore + ); + + await keystore + .asyncRecoverSecret(LABELS[0], "") + .then(() => ok(false, "'recovering' with an empty key should have failed")) + .catch(() => ok(true, "'recovering' with an empty key failed as expected")); + ok( + !(await keystore.asyncSecretAvailable(LABELS[0])), + "we didn't recover a secret, so the secret shouldn't be available" + ); + + await keystore + .asyncRecoverSecret(LABELS[0], "AAAAAA") + .then(() => + ok(false, "recovering with a key that is too short should have failed") + ) + .catch(() => + ok(true, "recovering with a key that is too short failed as expected") + ); + ok( + !(await keystore.asyncSecretAvailable(LABELS[0])), + "we didn't recover a secret, so the secret shouldn't be available" + ); + + await keystore + .asyncRecoverSecret( + LABELS[0], + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + ) + .then(() => + ok(false, "recovering with a key that is too long should have failed") + ) + .catch(() => + ok(true, "recovering with a key that is too long failed as expected") + ); + ok( + !(await keystore.asyncSecretAvailable(LABELS[0])), + "we didn't recover a secret, so the secret shouldn't be available" + ); + + let recoveryPhrase = await keystore.asyncGenerateSecret(LABELS[0]); + ok( + recoveryPhrase && !!recoveryPhrase.length, + "we should be able to use that label to generate a new secret" + ); + ok( + await keystore.asyncSecretAvailable(LABELS[0]), + "the generated secret should now be available" + ); + + await delete_all_secrets(); +}); |