diff options
Diffstat (limited to 'comm/mail/extensions/openpgp/content/modules/RNPLib.jsm')
-rw-r--r-- | comm/mail/extensions/openpgp/content/modules/RNPLib.jsm | 2109 |
1 files changed, 2109 insertions, 0 deletions
diff --git a/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm b/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm new file mode 100644 index 0000000000..58bcb383b5 --- /dev/null +++ b/comm/mail/extensions/openpgp/content/modules/RNPLib.jsm @@ -0,0 +1,2109 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const EXPORTED_SYMBOLS = ["RNPLibLoader"]; + +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +const lazy = {}; + +const { ctypes } = ChromeUtils.importESModule( + "resource://gre/modules/ctypes.sys.mjs" +); + +ChromeUtils.defineESModuleGetters(lazy, { + setTimeout: "resource://gre/modules/Timer.sys.mjs", +}); + +XPCOMUtils.defineLazyModuleGetters(lazy, { + OpenPGPMasterpass: "chrome://openpgp/content/modules/masterpass.jsm", +}); + +const MIN_RNP_VERSION = [0, 17, 0]; + +var systemOS = Services.appinfo.OS.toLowerCase(); +var abi = ctypes.default_abi; + +// Open librnp. Determine the path to the chrome directory and look for it +// there first. If not, fallback to searching the standard locations. +var librnp, librnpPath; + +function tryLoadRNP(name, suffix) { + let filename = ctypes.libraryName(name) + suffix; + let binPath = Services.dirsvc.get("XpcomLib", Ci.nsIFile).path; + let binDir = PathUtils.parent(binPath); + librnpPath = PathUtils.join(binDir, filename); + + try { + librnp = ctypes.open(librnpPath); + } catch (e) {} + + if (!librnp) { + try { + // look in standard locations + librnpPath = filename; + librnp = ctypes.open(librnpPath); + } catch (e) {} + } +} + +function loadExternalRNPLib() { + if (!librnp) { + // Try loading librnp.so, librnp.dylib, or rnp.dll first + tryLoadRNP("rnp", ""); + } + + if (!librnp && (systemOS === "winnt" || systemOS === "darwin")) { + // rnp.0.dll or rnp.0.dylib + tryLoadRNP("rnp.0", ""); + } + + if (!librnp) { + tryLoadRNP("rnp-0", ""); + } + + if (!librnp && systemOS === "winnt") { + // librnp-0.dll + tryLoadRNP("librnp-0", ""); + } + + if (!librnp && !(systemOS === "winnt") && !(systemOS === "darwin")) { + // librnp.so.0 + tryLoadRNP("rnp", ".0"); + } +} + +var RNPLibLoader = { + init() { + const required_version_str = `${MIN_RNP_VERSION[0]}.${MIN_RNP_VERSION[1]}.${MIN_RNP_VERSION[2]}`; + + let dummyRNPLib = { + loaded: false, + loadedOfficial: false, + loadStatus: "libs-rnp-status-load-failed", + loadErrorReason: "RNP/OpenPGP library failed to load", + path: "", + + getRNPLibStatus() { + return { + min_version: required_version_str, + loaded_version: "-", + status: this.loadStatus, + error: this.loadErrorReason, + path: this.path, + }; + }, + }; + + loadExternalRNPLib(); + if (!librnp) { + return dummyRNPLib; + } + + try { + enableRNPLibJS(); + } catch (e) { + console.log(e); + return dummyRNPLib; + } + + const rnp_version_str = + RNPLib.rnp_version_string_full().readStringReplaceMalformed(); + RNPLib.loadedVersion = rnp_version_str; + RNPLib.expectedVersion = required_version_str; + + let hasRequiredVersion = RNPLib.check_required_version(); + + if (!hasRequiredVersion) { + RNPLib.loadErrorReason = `RNP version ${rnp_version_str} does not meet minimum required ${required_version_str}.`; + RNPLib.loadStatus = "libs-rnp-status-incompatible"; + return RNPLib; + } + + RNPLib.loaded = true; + + let hasOfficialVersion = + rnp_version_str.includes(".MZLA") || + rnp_version_str.match("^[0-9]+.[0-9]+.[0-9]+(.[0-9]+)?$"); + if (!hasOfficialVersion) { + RNPLib.loadErrorReason = `RNP reports unexpected version information, it's considered an unofficial version with unknown capabilities.`; + RNPLib.loadStatus = "libs-rnp-status-unofficial"; + } else { + RNPLib.loadedOfficial = true; + } + + return RNPLib; + }, +}; + +const rnp_result_t = ctypes.uint32_t; +const rnp_ffi_t = ctypes.void_t.ptr; +const rnp_input_t = ctypes.void_t.ptr; +const rnp_output_t = ctypes.void_t.ptr; +const rnp_key_handle_t = ctypes.void_t.ptr; +const rnp_uid_handle_t = ctypes.void_t.ptr; +const rnp_identifier_iterator_t = ctypes.void_t.ptr; +const rnp_op_generate_t = ctypes.void_t.ptr; +const rnp_op_encrypt_t = ctypes.void_t.ptr; +const rnp_op_sign_t = ctypes.void_t.ptr; +const rnp_op_sign_signature_t = ctypes.void_t.ptr; +const rnp_op_verify_t = ctypes.void_t.ptr; +const rnp_op_verify_signature_t = ctypes.void_t.ptr; +const rnp_signature_handle_t = ctypes.void_t.ptr; +const rnp_recipient_handle_t = ctypes.void_t.ptr; +const rnp_symenc_handle_t = ctypes.void_t.ptr; + +const rnp_password_cb_t = ctypes.FunctionType(abi, ctypes.bool, [ + rnp_ffi_t, + ctypes.void_t.ptr, + rnp_key_handle_t, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.size_t, +]).ptr; + +const rnp_key_signatures_cb = ctypes.FunctionType(abi, ctypes.void_t, [ + rnp_ffi_t, + ctypes.void_t.ptr, + rnp_signature_handle_t, + ctypes.uint32_t.ptr, +]).ptr; + +var RNPLib; + +function enableRNPLibJS() { + // this must be delayed until after "librnp" is initialized + + RNPLib = { + loaded: false, + loadedOfficial: false, + loadStatus: "", + loadErrorReason: "", + expectedVersion: "", + loadedVersion: "", + + getRNPLibStatus() { + return { + min_version: this.expectedVersion, + loaded_version: this.loadedVersion, + status: + this.loaded && this.loadedOfficial + ? "libs-rnp-status-ok" + : this.loadStatus, + error: this.loadErrorReason, + path: this.path, + }; + }, + + path: librnpPath, + + // Handle to the RNP library and primary key data store. + // Kept at null if init fails. + ffi: null, + + // returns rnp_input_t, destroy using rnp_input_destroy + async createInputFromPath(path) { + // IOUtils.read always returns an array. + let u8 = await IOUtils.read(path); + if (!u8.length) { + return null; + } + + let input_from_memory = new this.rnp_input_t(); + try { + this.rnp_input_from_memory( + input_from_memory.address(), + u8, + u8.length, + false + ); + } catch (ex) { + throw new Error("rnp_input_from_memory for file " + path + " failed"); + } + return input_from_memory; + }, + + getFilenames() { + let secFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + secFile.append("secring.gpg"); + let pubFile = Services.dirsvc.get("ProfD", Ci.nsIFile); + pubFile.append("pubring.gpg"); + + let secRingPath = secFile.path; + let pubRingPath = pubFile.path; + + return { pubRingPath, secRingPath }; + }, + + /** + * Load a keyring file into the global ffi context. + * + * @param {string} filename - The file to load + * @param keyringFlag - either RNP_LOAD_SAVE_PUBLIC_KEYS + * or RNP_LOAD_SAVE_SECRET_KEYS + */ + async loadFile(filename, keyringFlag) { + let in_file = await this.createInputFromPath(filename); + if (in_file) { + this.rnp_load_keys(this.ffi, "GPG", in_file, keyringFlag); + this.rnp_input_destroy(in_file); + } + }, + + /** + * Load a keyring file into the global ffi context. + * If the file couldn't be opened, fall back to a backup file, + * by appending ".old" to filename. + * + * @param {string} filename - The file to load + * @param keyringFlag - either RNP_LOAD_SAVE_PUBLIC_KEYS + * or RNP_LOAD_SAVE_SECRET_KEYS + */ + async loadWithFallback(filename, keyringFlag) { + let loadBackup = false; + try { + await this.loadFile(filename, keyringFlag); + } catch (ex) { + if (DOMException.isInstance(ex)) { + loadBackup = true; + } + } + if (loadBackup) { + filename += ".old"; + try { + await this.loadFile(filename, keyringFlag); + } catch (ex) {} + } + }, + + async _fixUnprotectedKeys() { + // Bug 1710290, protect all unprotected keys. + // To do so, we require that the user has already unlocked + // by entering the global primary password, if it is set. + // Ensure that other repairing is done first, if necessary, + // as handled by masterpass.jsm (OpenPGP automatic password). + + // Note we have two failure scenarios, either a failure, or + // retrieveOpenPGPPassword() returning null (that function + // might fail because of inconsistencies or corruption). + let canRepair = false; + try { + console.log("Trying to automatically protect the unprotected keys."); + let mp = await lazy.OpenPGPMasterpass.retrieveOpenPGPPassword(); + if (mp) { + await RNPLib.protectUnprotectedKeys(); + await RNPLib.saveKeys(); + canRepair = true; + console.log("Successfully protected the unprotected keys."); + let [prot, unprot] = RNPLib.getProtectedKeysCount(); + console.debug( + `Found (${prot} protected and ${unprot} unprotected secret keys.` + ); + } + } catch (ex) { + console.log(ex); + } + + if (!canRepair) { + console.log("Cannot protect the unprotected keys at this time."); + } + }, + + check_required_version() { + const min_version = this.rnp_version_for(...MIN_RNP_VERSION); + const this_version = this.rnp_version(); + return Boolean(this_version >= min_version); + }, + + /** + * Prepare an RNP library handle, and in addition set all the + * application's preferences for library behavior. + * + * Other application code should NOT call rnp_ffi_create directly, + * but obtain an RNP library handle from this function. + */ + prepare_ffi() { + let ffi = new rnp_ffi_t(); + if (this._rnp_ffi_create(ffi.address(), "GPG", "GPG")) { + return null; + } + + // Treat MD5 as insecure. + if ( + this.rnp_add_security_rule( + ffi, + this.RNP_FEATURE_HASH_ALG, + this.RNP_ALGNAME_MD5, + this.RNP_SECURITY_OVERRIDE, + 0, + this.RNP_SECURITY_INSECURE + ) + ) { + return null; + } + + // Use RNP's default rule for SHA1 used with data signatures, + // and use our override to allow it for key signatures. + if ( + this.rnp_add_security_rule( + ffi, + this.RNP_FEATURE_HASH_ALG, + this.RNP_ALGNAME_SHA1, + this.RNP_SECURITY_VERIFY_KEY | this.RNP_SECURITY_OVERRIDE, + 0, + this.RNP_SECURITY_DEFAULT + ) + ) { + return null; + } + + /* + // Security rules API does not yet support PK and SYMM algs. + // + // If a hash algorithm is already disabled at build time, + // and an attempt is made to set a security rule for that + // algorithm, then RNP returns a failure. + // + // Ideally, RNP should allow these calls (regardless of build time + // settings) to define an application security rule, that is + // independent of the configuration used for building the + // RNP library. + + if ( + this.rnp_add_security_rule( + ffi, + this.RNP_FEATURE_HASH_ALG, + this.RNP_ALGNAME_SM3, + this.RNP_SECURITY_OVERRIDE, + 0, + this.RNP_SECURITY_PROHIBITED + ) + ) { + return null; + } + + if ( + this.rnp_add_security_rule( + ffi, + this.RNP_FEATURE_PK_ALG, + this.RNP_ALGNAME_SM2, + this.RNP_SECURITY_OVERRIDE, + 0, + this.RNP_SECURITY_PROHIBITED + ) + ) { + return null; + } + + if ( + this.rnp_add_security_rule( + ffi, + this.RNP_FEATURE_SYMM_ALG, + this.RNP_ALGNAME_SM4, + this.RNP_SECURITY_OVERRIDE, + 0, + this.RNP_SECURITY_PROHIBITED + ) + ) { + return null; + } + */ + + return ffi; + }, + + /** + * Test the correctness of security rules, in particular, test + * if the given hash algorithm is allowed at the given time. + * + * This is an application consistency test. If the behavior isn't + * according to the expectation, the function throws an error. + * + * @param {string} hashAlg - Test this hash algorithm + * @param {time_t} time - Test status at this timestamp + * @param {boolean} keySigAllowed - Test if using the hash algorithm + * is allowed for signatures found inside OpenPGP keys. + * @param {boolean} dataSigAllowed - Test if using the hash algorithm + * is allowed for signatures on data. + */ + _confirmSecurityRule(hashAlg, time, keySigAllowed, dataSigAllowed) { + let level = new ctypes.uint32_t(); + let flag = new ctypes.uint32_t(); + + flag.value = this.RNP_SECURITY_VERIFY_DATA; + let testDataSuccess = false; + if ( + !RNPLib.rnp_get_security_rule( + this.ffi, + this.RNP_FEATURE_HASH_ALG, + hashAlg, + time, + flag.address(), + null, + level.address() + ) + ) { + if (dataSigAllowed) { + testDataSuccess = level.value == RNPLib.RNP_SECURITY_DEFAULT; + } else { + testDataSuccess = level.value < RNPLib.RNP_SECURITY_DEFAULT; + } + } + + if (!testDataSuccess) { + throw new Error("security configuration for data signatures failed"); + } + + flag.value = this.RNP_SECURITY_VERIFY_KEY; + let testKeySuccess = false; + if ( + !RNPLib.rnp_get_security_rule( + this.ffi, + this.RNP_FEATURE_HASH_ALG, + hashAlg, + time, + flag.address(), + null, + level.address() + ) + ) { + if (keySigAllowed) { + testKeySuccess = level.value == RNPLib.RNP_SECURITY_DEFAULT; + } else { + testKeySuccess = level.value < RNPLib.RNP_SECURITY_DEFAULT; + } + } + + if (!testKeySuccess) { + throw new Error("security configuration for key signatures failed"); + } + }, + + /** + * Perform tests that the RNP library behaves according to the + * defined security rules. + * If a problem is found, the function throws an error. + */ + _sanityCheckSecurityRules() { + let time_t_now = Math.round(Date.now() / 1000); + let ten_years_in_seconds = 10 * 365 * 24 * 60 * 60; + let ten_years_future = time_t_now + ten_years_in_seconds; + + this._confirmSecurityRule(this.RNP_ALGNAME_MD5, time_t_now, false, false); + this._confirmSecurityRule( + this.RNP_ALGNAME_MD5, + ten_years_future, + false, + false + ); + + this._confirmSecurityRule(this.RNP_ALGNAME_SHA1, time_t_now, true, false); + this._confirmSecurityRule( + this.RNP_ALGNAME_SHA1, + ten_years_future, + true, + false + ); + }, + + async init() { + this.ffi = this.prepare_ffi(); + if (!this.ffi) { + throw new Error("Couldn't initialize librnp."); + } + + this.rnp_ffi_set_log_fd(this.ffi, 2); // stderr + + this.keep_password_cb_alive = rnp_password_cb_t( + this.password_cb, + this, // this value used while executing callback + false // callback return value if exception is thrown + ); + this.rnp_ffi_set_pass_provider( + this.ffi, + this.keep_password_cb_alive, + null + ); + + let { pubRingPath, secRingPath } = this.getFilenames(); + + try { + this._sanityCheckSecurityRules(); + } catch (e) { + // Disable all RNP operation + this.ffi = null; + throw e; + } + + await this.loadWithFallback(pubRingPath, this.RNP_LOAD_SAVE_PUBLIC_KEYS); + await this.loadWithFallback(secRingPath, this.RNP_LOAD_SAVE_SECRET_KEYS); + + let pubnum = new ctypes.size_t(); + this.rnp_get_public_key_count(this.ffi, pubnum.address()); + + let secnum = new ctypes.size_t(); + this.rnp_get_secret_key_count(this.ffi, secnum.address()); + + let [prot, unprot] = this.getProtectedKeysCount(); + console.debug( + `Found ${pubnum.value} public keys and ${secnum.value} secret keys (${prot} protected, ${unprot} unprotected)` + ); + + if (unprot) { + // We need automatic repair, which can involve a primary password + // prompt. Let's use a short timer, so we keep it out of the + // early startup code. + console.log( + "Will attempt to automatically protect the unprotected keys in 30 seconds" + ); + lazy.setTimeout(RNPLib._fixUnprotectedKeys, 30000); + } + return true; + }, + + /** + * Returns two numbers, the number of protected and unprotected keys. + * Because we use an automatic password for all secret keys + * (regardless of a primary password being used), + * the number of unprotected keys should be zero. + */ + getProtectedKeysCount() { + let prot = 0; + let unprot = 0; + + let iter = new RNPLib.rnp_identifier_iterator_t(); + let grip = new ctypes.char.ptr(); + + if ( + RNPLib.rnp_identifier_iterator_create( + RNPLib.ffi, + iter.address(), + "grip" + ) + ) { + throw new Error("rnp_identifier_iterator_create failed"); + } + + while ( + !RNPLib.rnp_identifier_iterator_next(iter, grip.address()) && + !grip.isNull() + ) { + let handle = new RNPLib.rnp_key_handle_t(); + if (RNPLib.rnp_locate_key(RNPLib.ffi, "grip", grip, handle.address())) { + throw new Error("rnp_locate_key failed"); + } + + if (this.getSecretAvailableFromHandle(handle)) { + let is_protected = new ctypes.bool(); + if (RNPLib.rnp_key_is_protected(handle, is_protected.address())) { + throw new Error("rnp_key_is_protected failed"); + } + if (is_protected.value) { + prot++; + } else { + unprot++; + } + } + + RNPLib.rnp_key_handle_destroy(handle); + } + + RNPLib.rnp_identifier_iterator_destroy(iter); + return [prot, unprot]; + }, + + getSecretAvailableFromHandle(handle) { + let have_secret = new ctypes.bool(); + if (RNPLib.rnp_key_have_secret(handle, have_secret.address())) { + throw new Error("rnp_key_have_secret failed"); + } + return have_secret.value; + }, + + /** + * If the given secret key is a pseudo secret key, which doesn't + * contain the underlying key material, then return false. + * + * Only call this function if getSecretAvailableFromHandle returns + * true for the given handle (which means it claims to contain a + * secret key). + * + * @param {rnp_key_handle_t} handle - handle of the key to query + * @returns {boolean} - true if secret key material is available + * + */ + isSecretKeyMaterialAvailable(handle) { + let protection_type = new ctypes.char.ptr(); + if ( + RNPLib.rnp_key_get_protection_type(handle, protection_type.address()) + ) { + throw new Error("rnp_key_get_protection_type failed"); + } + let result; + switch (protection_type.readString()) { + case "GPG-None": + case "GPG-Smartcard": + case "Unknown": + result = false; + break; + default: + result = true; + break; + } + RNPLib.rnp_buffer_destroy(protection_type); + return result; + }, + + async protectUnprotectedKeys() { + let iter = new RNPLib.rnp_identifier_iterator_t(); + let grip = new ctypes.char.ptr(); + + let newPass = await lazy.OpenPGPMasterpass.retrieveOpenPGPPassword(); + + if ( + RNPLib.rnp_identifier_iterator_create( + RNPLib.ffi, + iter.address(), + "grip" + ) + ) { + throw new Error("rnp_identifier_iterator_create failed"); + } + + while ( + !RNPLib.rnp_identifier_iterator_next(iter, grip.address()) && + !grip.isNull() + ) { + let handle = new RNPLib.rnp_key_handle_t(); + if (RNPLib.rnp_locate_key(RNPLib.ffi, "grip", grip, handle.address())) { + throw new Error("rnp_locate_key failed"); + } + + if (RNPLib.getSecretAvailableFromHandle(handle)) { + let is_protected = new ctypes.bool(); + if (RNPLib.rnp_key_is_protected(handle, is_protected.address())) { + throw new Error("rnp_key_is_protected failed"); + } + if (!is_protected.value) { + RNPLib.protectKeyWithSubKeys(handle, newPass); + } + } + + RNPLib.rnp_key_handle_destroy(handle); + } + + RNPLib.rnp_identifier_iterator_destroy(iter); + }, + + protectKeyWithSubKeys(handle, newPass) { + if (RNPLib.isSecretKeyMaterialAvailable(handle)) { + if (RNPLib.rnp_key_protect(handle, newPass, null, null, null, 0)) { + throw new Error("rnp_key_protect failed"); + } + } + + let sub_count = new ctypes.size_t(); + if (RNPLib.rnp_key_get_subkey_count(handle, sub_count.address())) { + throw new Error("rnp_key_get_subkey_count failed"); + } + + for (let i = 0; i < sub_count.value; i++) { + let sub_handle = new RNPLib.rnp_key_handle_t(); + if (RNPLib.rnp_key_get_subkey_at(handle, i, sub_handle.address())) { + throw new Error("rnp_key_get_subkey_at failed"); + } + if ( + RNPLib.getSecretAvailableFromHandle(sub_handle) && + RNPLib.isSecretKeyMaterialAvailable(sub_handle) + ) { + if ( + RNPLib.rnp_key_protect(sub_handle, newPass, null, null, null, 0) + ) { + throw new Error("rnp_key_protect failed"); + } + } + RNPLib.rnp_key_handle_destroy(sub_handle); + } + }, + + /** + * Save keyring file to the given path. + * + * @param {string} path - The file path to save to. + * @param {number} keyRingFlag - RNP_LOAD_SAVE_PUBLIC_KEYS or + * RNP_LOAD_SAVE_SECRET_KEYS. + */ + async saveKeyRing(path, keyRingFlag) { + if (!this.ffi) { + return; + } + + let oldPath = path + ".old"; + + // Ignore failure, oldPath might not exist yet. + await IOUtils.copy(path, oldPath).catch(() => {}); + + let u8 = null; + let keyCount = new ctypes.size_t(); + + if (keyRingFlag == this.RNP_LOAD_SAVE_SECRET_KEYS) { + this.rnp_get_secret_key_count(this.ffi, keyCount.address()); + } else { + this.rnp_get_public_key_count(this.ffi, keyCount.address()); + } + + let keyCountNum = parseInt(keyCount.value.toString()); + if (keyCountNum) { + let rnp_out = new this.rnp_output_t(); + if (this.rnp_output_to_memory(rnp_out.address(), 0)) { + throw new Error("rnp_output_to_memory failed"); + } + if (this.rnp_save_keys(this.ffi, "GPG", rnp_out, keyRingFlag)) { + throw new Error("rnp_save_keys failed"); + } + + let result_buf = new ctypes.uint8_t.ptr(); + let result_len = new ctypes.size_t(); + + // Parameter false means "don't copy rnp_out to result_buf", + // rather a reference to the memory is used. Be careful to + // destroy rnp_out after we're done with the data. + if ( + this.rnp_output_memory_get_buf( + rnp_out, + result_buf.address(), + result_len.address(), + false + ) + ) { + throw new Error("rnp_output_memory_get_buf failed"); + } else { + let uint8_array = ctypes.cast( + result_buf, + ctypes.uint8_t.array(result_len.value).ptr + ).contents; + // This call creates a copy of the data, it should be + // safe to destroy rnp_out afterwards. + u8 = uint8_array.readTypedArray(); + } + this.rnp_output_destroy(rnp_out); + } + + u8 = u8 || new Uint8Array(); + + await IOUtils.write(path, u8, { + tmpPath: path + ".tmp-new", + }); + }, + + async saveKeys() { + if (!this.ffi) { + return; + } + let { pubRingPath, secRingPath } = this.getFilenames(); + + let saveThem = async () => { + await this.saveKeyRing(pubRingPath, this.RNP_LOAD_SAVE_PUBLIC_KEYS); + await this.saveKeyRing(secRingPath, this.RNP_LOAD_SAVE_SECRET_KEYS); + }; + let saveBlocker = saveThem(); + IOUtils.profileBeforeChange.addBlocker( + "OpenPGP: writing out keyring", + saveBlocker + ); + await saveBlocker; + IOUtils.profileBeforeChange.removeBlocker(saveBlocker); + }, + + keep_password_cb_alive: null, + + cached_pw: null, + + /** + * Past versions of Thunderbird used this callback to provide + * the automatically managed passphrase to RNP, which was used + * for all OpenPGP. Nowadays, Thunderbird supports the definition + * of used-defined passphrase. To better control the unlocking of + * keys, Thunderbird no longer uses this callback. + * The application is designed to unlock secret keys as needed, + * prior to calling the respective RNP APIs. + * If this callback is reached anyway, it's an internal error, + * it means that some Thunderbird code hasn't properly unlocked + * the required key yet. + * + * This is a C callback from an external library, so we cannot + * rely on the usual JS throw mechanism to abort this operation. + */ + password_cb(ffi, app_ctx, key, pgp_context, buf, buf_len) { + let fingerprint = new ctypes.char.ptr(); + let fpStr; + if (!RNPLib.rnp_key_get_fprint(key, fingerprint.address())) { + fpStr = "Fingerprint: " + fingerprint.readString(); + } + RNPLib.rnp_buffer_destroy(fingerprint); + + console.debug( + `Internal error, RNP password callback called unexpectedly. ${fpStr}.` + ); + return false; + }, + + // For comparing version numbers + rnp_version_for: librnp.declare( + "rnp_version_for", + abi, + ctypes.uint32_t, + ctypes.uint32_t, // major + ctypes.uint32_t, // minor + ctypes.uint32_t // patch + ), + + // Get the library version. + rnp_version: librnp.declare("rnp_version", abi, ctypes.uint32_t), + + rnp_version_string_full: librnp.declare( + "rnp_version_string_full", + abi, + ctypes.char.ptr + ), + + // Get a RNP library handle. + // Mark with leading underscore, to clarify that this function + // shouldn't be called directly - you should call prepare_ffi(). + _rnp_ffi_create: librnp.declare( + "rnp_ffi_create", + abi, + rnp_result_t, + rnp_ffi_t.ptr, + ctypes.char.ptr, + ctypes.char.ptr + ), + + rnp_ffi_destroy: librnp.declare( + "rnp_ffi_destroy", + abi, + rnp_result_t, + rnp_ffi_t + ), + + rnp_ffi_set_log_fd: librnp.declare( + "rnp_ffi_set_log_fd", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.int + ), + + rnp_get_public_key_count: librnp.declare( + "rnp_get_public_key_count", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.size_t.ptr + ), + + rnp_get_secret_key_count: librnp.declare( + "rnp_get_secret_key_count", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.size_t.ptr + ), + + rnp_input_from_path: librnp.declare( + "rnp_input_from_path", + abi, + rnp_result_t, + rnp_input_t.ptr, + ctypes.char.ptr + ), + + rnp_input_from_memory: librnp.declare( + "rnp_input_from_memory", + abi, + rnp_result_t, + rnp_input_t.ptr, + ctypes.uint8_t.ptr, + ctypes.size_t, + ctypes.bool + ), + + rnp_output_to_memory: librnp.declare( + "rnp_output_to_memory", + abi, + rnp_result_t, + rnp_output_t.ptr, + ctypes.size_t + ), + + rnp_output_to_path: librnp.declare( + "rnp_output_to_path", + abi, + rnp_result_t, + rnp_output_t.ptr, + ctypes.char.ptr + ), + + rnp_decrypt: librnp.declare( + "rnp_decrypt", + abi, + rnp_result_t, + rnp_ffi_t, + rnp_input_t, + rnp_output_t + ), + + rnp_output_memory_get_buf: librnp.declare( + "rnp_output_memory_get_buf", + abi, + rnp_result_t, + rnp_output_t, + ctypes.uint8_t.ptr.ptr, + ctypes.size_t.ptr, + ctypes.bool + ), + + rnp_input_destroy: librnp.declare( + "rnp_input_destroy", + abi, + rnp_result_t, + rnp_input_t + ), + + rnp_output_destroy: librnp.declare( + "rnp_output_destroy", + abi, + rnp_result_t, + rnp_output_t + ), + + rnp_load_keys: librnp.declare( + "rnp_load_keys", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.char.ptr, + rnp_input_t, + ctypes.uint32_t + ), + + rnp_save_keys: librnp.declare( + "rnp_save_keys", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.char.ptr, + rnp_output_t, + ctypes.uint32_t + ), + + rnp_ffi_set_pass_provider: librnp.declare( + "rnp_ffi_set_pass_provider", + abi, + rnp_result_t, + rnp_ffi_t, + rnp_password_cb_t, + ctypes.void_t.ptr + ), + + rnp_identifier_iterator_create: librnp.declare( + "rnp_identifier_iterator_create", + abi, + rnp_result_t, + rnp_ffi_t, + rnp_identifier_iterator_t.ptr, + ctypes.char.ptr + ), + + rnp_identifier_iterator_next: librnp.declare( + "rnp_identifier_iterator_next", + abi, + rnp_result_t, + rnp_identifier_iterator_t, + ctypes.char.ptr.ptr + ), + + rnp_identifier_iterator_destroy: librnp.declare( + "rnp_identifier_iterator_destroy", + abi, + rnp_result_t, + rnp_identifier_iterator_t + ), + + rnp_locate_key: librnp.declare( + "rnp_locate_key", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.char.ptr, + ctypes.char.ptr, + rnp_key_handle_t.ptr + ), + + rnp_key_handle_destroy: librnp.declare( + "rnp_key_handle_destroy", + abi, + rnp_result_t, + rnp_key_handle_t + ), + + rnp_key_allows_usage: librnp.declare( + "rnp_key_allows_usage", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr, + ctypes.bool.ptr + ), + + rnp_key_is_sub: librnp.declare( + "rnp_key_is_sub", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_is_primary: librnp.declare( + "rnp_key_is_primary", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_have_secret: librnp.declare( + "rnp_key_have_secret", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_have_public: librnp.declare( + "rnp_key_have_public", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_get_fprint: librnp.declare( + "rnp_key_get_fprint", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_key_get_keyid: librnp.declare( + "rnp_key_get_keyid", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_key_get_alg: librnp.declare( + "rnp_key_get_alg", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_key_get_grip: librnp.declare( + "rnp_key_get_grip", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_key_get_primary_grip: librnp.declare( + "rnp_key_get_primary_grip", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_key_is_revoked: librnp.declare( + "rnp_key_is_revoked", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_buffer_destroy: librnp.declare( + "rnp_buffer_destroy", + abi, + ctypes.void_t, + ctypes.void_t.ptr + ), + + rnp_key_get_subkey_count: librnp.declare( + "rnp_key_get_subkey_count", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.size_t.ptr + ), + + rnp_key_get_subkey_at: librnp.declare( + "rnp_key_get_subkey_at", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.size_t, + rnp_key_handle_t.ptr + ), + + rnp_key_get_creation: librnp.declare( + "rnp_key_get_creation", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t.ptr + ), + + rnp_key_get_expiration: librnp.declare( + "rnp_key_get_expiration", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t.ptr + ), + + rnp_key_get_bits: librnp.declare( + "rnp_key_get_bits", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t.ptr + ), + + rnp_key_get_uid_count: librnp.declare( + "rnp_key_get_uid_count", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.size_t.ptr + ), + + rnp_key_get_primary_uid: librnp.declare( + "rnp_key_get_primary_uid", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_key_get_uid_at: librnp.declare( + "rnp_key_get_uid_at", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.size_t, + ctypes.char.ptr.ptr + ), + + rnp_key_get_uid_handle_at: librnp.declare( + "rnp_key_get_uid_handle_at", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.size_t, + rnp_uid_handle_t.ptr + ), + + rnp_uid_handle_destroy: librnp.declare( + "rnp_uid_handle_destroy", + abi, + rnp_result_t, + rnp_uid_handle_t + ), + + rnp_uid_is_revoked: librnp.declare( + "rnp_uid_is_revoked", + abi, + rnp_result_t, + rnp_uid_handle_t, + ctypes.bool.ptr + ), + + rnp_key_unlock: librnp.declare( + "rnp_key_unlock", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr + ), + + rnp_key_lock: librnp.declare( + "rnp_key_lock", + abi, + rnp_result_t, + rnp_key_handle_t + ), + + rnp_key_unprotect: librnp.declare( + "rnp_key_unprotect", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr + ), + + rnp_key_protect: librnp.declare( + "rnp_key_protect", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.size_t + ), + + rnp_key_is_protected: librnp.declare( + "rnp_key_is_protected", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_is_locked: librnp.declare( + "rnp_key_is_locked", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_op_generate_create: librnp.declare( + "rnp_op_generate_create", + abi, + rnp_result_t, + rnp_op_generate_t.ptr, + rnp_ffi_t, + ctypes.char.ptr + ), + + rnp_op_generate_subkey_create: librnp.declare( + "rnp_op_generate_subkey_create", + abi, + rnp_result_t, + rnp_op_generate_t.ptr, + rnp_ffi_t, + rnp_key_handle_t, + ctypes.char.ptr + ), + + rnp_op_generate_set_bits: librnp.declare( + "rnp_op_generate_set_bits", + abi, + rnp_result_t, + rnp_op_generate_t, + ctypes.uint32_t + ), + + rnp_op_generate_set_curve: librnp.declare( + "rnp_op_generate_set_curve", + abi, + rnp_result_t, + rnp_op_generate_t, + ctypes.char.ptr + ), + + rnp_op_generate_set_protection_password: librnp.declare( + "rnp_op_generate_set_protection_password", + abi, + rnp_result_t, + rnp_op_generate_t, + ctypes.char.ptr + ), + + rnp_op_generate_set_userid: librnp.declare( + "rnp_op_generate_set_userid", + abi, + rnp_result_t, + rnp_op_generate_t, + ctypes.char.ptr + ), + + rnp_op_generate_set_expiration: librnp.declare( + "rnp_op_generate_set_expiration", + abi, + rnp_result_t, + rnp_op_generate_t, + ctypes.uint32_t + ), + + rnp_op_generate_execute: librnp.declare( + "rnp_op_generate_execute", + abi, + rnp_result_t, + rnp_op_generate_t + ), + + rnp_op_generate_get_key: librnp.declare( + "rnp_op_generate_get_key", + abi, + rnp_result_t, + rnp_op_generate_t, + rnp_key_handle_t.ptr + ), + + rnp_op_generate_destroy: librnp.declare( + "rnp_op_generate_destroy", + abi, + rnp_result_t, + rnp_op_generate_t + ), + + rnp_guess_contents: librnp.declare( + "rnp_guess_contents", + abi, + rnp_result_t, + rnp_input_t, + ctypes.char.ptr.ptr + ), + + rnp_import_signatures: librnp.declare( + "rnp_import_signatures", + abi, + rnp_result_t, + rnp_ffi_t, + rnp_input_t, + ctypes.uint32_t, + ctypes.char.ptr.ptr + ), + + rnp_import_keys: librnp.declare( + "rnp_import_keys", + abi, + rnp_result_t, + rnp_ffi_t, + rnp_input_t, + ctypes.uint32_t, + ctypes.char.ptr.ptr + ), + + rnp_key_remove: librnp.declare( + "rnp_key_remove", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t + ), + + rnp_uid_remove: librnp.declare( + "rnp_uid_remove", + abi, + rnp_result_t, + rnp_key_handle_t, + rnp_uid_handle_t + ), + + rnp_key_remove_signatures: librnp.declare( + "rnp_key_remove_signatures", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t, + rnp_key_signatures_cb, + ctypes.void_t.ptr + ), + + rnp_op_encrypt_create: librnp.declare( + "rnp_op_encrypt_create", + abi, + rnp_result_t, + rnp_op_encrypt_t.ptr, + rnp_ffi_t, + rnp_input_t, + rnp_output_t + ), + + rnp_op_sign_cleartext_create: librnp.declare( + "rnp_op_sign_cleartext_create", + abi, + rnp_result_t, + rnp_op_sign_t.ptr, + rnp_ffi_t, + rnp_input_t, + rnp_output_t + ), + + rnp_op_sign_detached_create: librnp.declare( + "rnp_op_sign_detached_create", + abi, + rnp_result_t, + rnp_op_sign_t.ptr, + rnp_ffi_t, + rnp_input_t, + rnp_output_t + ), + + rnp_op_encrypt_add_recipient: librnp.declare( + "rnp_op_encrypt_add_recipient", + abi, + rnp_result_t, + rnp_op_encrypt_t, + rnp_key_handle_t + ), + + rnp_op_encrypt_add_signature: librnp.declare( + "rnp_op_encrypt_add_signature", + abi, + rnp_result_t, + rnp_op_encrypt_t, + rnp_key_handle_t, + rnp_op_sign_signature_t.ptr + ), + + rnp_op_sign_add_signature: librnp.declare( + "rnp_op_sign_add_signature", + abi, + rnp_result_t, + rnp_op_sign_t, + rnp_key_handle_t, + rnp_op_sign_signature_t.ptr + ), + + rnp_op_encrypt_set_armor: librnp.declare( + "rnp_op_encrypt_set_armor", + abi, + rnp_result_t, + rnp_op_encrypt_t, + ctypes.bool + ), + + rnp_op_sign_set_armor: librnp.declare( + "rnp_op_sign_set_armor", + abi, + rnp_result_t, + rnp_op_sign_t, + ctypes.bool + ), + + rnp_op_encrypt_set_hash: librnp.declare( + "rnp_op_encrypt_set_hash", + abi, + rnp_result_t, + rnp_op_encrypt_t, + ctypes.char.ptr + ), + + rnp_op_sign_set_hash: librnp.declare( + "rnp_op_sign_set_hash", + abi, + rnp_result_t, + rnp_op_sign_t, + ctypes.char.ptr + ), + + rnp_op_encrypt_set_cipher: librnp.declare( + "rnp_op_encrypt_set_cipher", + abi, + rnp_result_t, + rnp_op_encrypt_t, + ctypes.char.ptr + ), + + rnp_op_sign_execute: librnp.declare( + "rnp_op_sign_execute", + abi, + rnp_result_t, + rnp_op_sign_t + ), + + rnp_op_sign_destroy: librnp.declare( + "rnp_op_sign_destroy", + abi, + rnp_result_t, + rnp_op_sign_t + ), + + rnp_op_encrypt_execute: librnp.declare( + "rnp_op_encrypt_execute", + abi, + rnp_result_t, + rnp_op_encrypt_t + ), + + rnp_op_encrypt_destroy: librnp.declare( + "rnp_op_encrypt_destroy", + abi, + rnp_result_t, + rnp_op_encrypt_t + ), + + rnp_key_export: librnp.declare( + "rnp_key_export", + abi, + rnp_result_t, + rnp_key_handle_t, + rnp_output_t, + ctypes.uint32_t + ), + + rnp_key_export_revocation: librnp.declare( + "rnp_key_export_revocation", + abi, + rnp_result_t, + rnp_key_handle_t, + rnp_output_t, + ctypes.uint32_t, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.char.ptr + ), + + rnp_output_to_armor: librnp.declare( + "rnp_output_to_armor", + abi, + rnp_result_t, + rnp_output_t, + rnp_output_t.ptr, + ctypes.char.ptr + ), + + rnp_output_finish: librnp.declare( + "rnp_output_finish", + abi, + rnp_result_t, + rnp_output_t + ), + + rnp_op_verify_create: librnp.declare( + "rnp_op_verify_create", + abi, + rnp_result_t, + rnp_op_verify_t.ptr, + rnp_ffi_t, + rnp_input_t, + rnp_output_t + ), + + rnp_op_verify_detached_create: librnp.declare( + "rnp_op_verify_detached_create", + abi, + rnp_result_t, + rnp_op_verify_t.ptr, + rnp_ffi_t, + rnp_input_t, + rnp_input_t + ), + + rnp_op_verify_execute: librnp.declare( + "rnp_op_verify_execute", + abi, + rnp_result_t, + rnp_op_verify_t + ), + + rnp_op_verify_destroy: librnp.declare( + "rnp_op_verify_destroy", + abi, + rnp_result_t, + rnp_op_verify_t + ), + + rnp_op_verify_get_signature_count: librnp.declare( + "rnp_op_verify_get_signature_count", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.size_t.ptr + ), + + rnp_op_verify_get_signature_at: librnp.declare( + "rnp_op_verify_get_signature_at", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.size_t, + rnp_op_verify_signature_t.ptr + ), + + rnp_op_verify_signature_get_handle: librnp.declare( + "rnp_op_verify_signature_get_handle", + abi, + rnp_result_t, + rnp_op_verify_signature_t, + rnp_signature_handle_t.ptr + ), + + rnp_op_verify_signature_get_status: librnp.declare( + "rnp_op_verify_signature_get_status", + abi, + rnp_result_t, + rnp_op_verify_signature_t + ), + + rnp_op_verify_signature_get_key: librnp.declare( + "rnp_op_verify_signature_get_key", + abi, + rnp_result_t, + rnp_op_verify_signature_t, + rnp_key_handle_t.ptr + ), + + rnp_op_verify_signature_get_times: librnp.declare( + "rnp_op_verify_signature_get_times", + abi, + rnp_result_t, + rnp_op_verify_signature_t, + ctypes.uint32_t.ptr, + ctypes.uint32_t.ptr + ), + + rnp_uid_get_signature_count: librnp.declare( + "rnp_uid_get_signature_count", + abi, + rnp_result_t, + rnp_uid_handle_t, + ctypes.size_t.ptr + ), + + rnp_uid_get_signature_at: librnp.declare( + "rnp_uid_get_signature_at", + abi, + rnp_result_t, + rnp_uid_handle_t, + ctypes.size_t, + rnp_signature_handle_t.ptr + ), + + rnp_key_get_signature_count: librnp.declare( + "rnp_key_get_signature_count", + abi, + rnp_result_t, + rnp_uid_handle_t, + ctypes.size_t.ptr + ), + + rnp_key_get_signature_at: librnp.declare( + "rnp_key_get_signature_at", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.size_t, + rnp_signature_handle_t.ptr + ), + + rnp_signature_get_hash_alg: librnp.declare( + "rnp_signature_get_hash_alg", + abi, + rnp_result_t, + rnp_signature_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_signature_get_creation: librnp.declare( + "rnp_signature_get_creation", + abi, + rnp_result_t, + rnp_signature_handle_t, + ctypes.uint32_t.ptr + ), + + rnp_signature_get_keyid: librnp.declare( + "rnp_signature_get_keyid", + abi, + rnp_result_t, + rnp_signature_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_signature_get_signer: librnp.declare( + "rnp_signature_get_signer", + abi, + rnp_result_t, + rnp_signature_handle_t, + rnp_key_handle_t.ptr + ), + + rnp_signature_handle_destroy: librnp.declare( + "rnp_signature_handle_destroy", + abi, + rnp_result_t, + rnp_signature_handle_t + ), + + rnp_enarmor: librnp.declare( + "rnp_enarmor", + abi, + rnp_result_t, + rnp_input_t, + rnp_output_t, + ctypes.char.ptr + ), + + rnp_op_verify_get_protection_info: librnp.declare( + "rnp_op_verify_get_protection_info", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.char.ptr.ptr, + ctypes.char.ptr.ptr, + ctypes.bool.ptr + ), + + rnp_op_verify_get_recipient_count: librnp.declare( + "rnp_op_verify_get_recipient_count", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.size_t.ptr + ), + + rnp_op_verify_get_used_recipient: librnp.declare( + "rnp_op_verify_get_used_recipient", + abi, + rnp_result_t, + rnp_op_verify_t, + rnp_recipient_handle_t.ptr + ), + + rnp_op_verify_get_recipient_at: librnp.declare( + "rnp_op_verify_get_recipient_at", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.size_t, + rnp_recipient_handle_t.ptr + ), + + rnp_recipient_get_keyid: librnp.declare( + "rnp_recipient_get_keyid", + abi, + rnp_result_t, + rnp_recipient_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_recipient_get_alg: librnp.declare( + "rnp_recipient_get_alg", + abi, + rnp_result_t, + rnp_recipient_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_op_verify_get_symenc_count: librnp.declare( + "rnp_op_verify_get_symenc_count", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.size_t.ptr + ), + + rnp_op_verify_get_used_symenc: librnp.declare( + "rnp_op_verify_get_used_symenc", + abi, + rnp_result_t, + rnp_op_verify_t, + rnp_symenc_handle_t.ptr + ), + + rnp_op_verify_get_symenc_at: librnp.declare( + "rnp_op_verify_get_symenc_at", + abi, + rnp_result_t, + rnp_op_verify_t, + ctypes.size_t, + rnp_symenc_handle_t.ptr + ), + + rnp_symenc_get_cipher: librnp.declare( + "rnp_symenc_get_cipher", + abi, + rnp_result_t, + rnp_symenc_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_symenc_get_aead_alg: librnp.declare( + "rnp_symenc_get_aead_alg", + abi, + rnp_result_t, + rnp_symenc_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_symenc_get_hash_alg: librnp.declare( + "rnp_symenc_get_hash_alg", + abi, + rnp_result_t, + rnp_symenc_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_symenc_get_s2k_type: librnp.declare( + "rnp_symenc_get_s2k_type", + abi, + rnp_result_t, + rnp_symenc_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_symenc_get_s2k_iterations: librnp.declare( + "rnp_symenc_get_s2k_iterations", + abi, + rnp_result_t, + rnp_symenc_handle_t, + ctypes.uint32_t.ptr + ), + + rnp_key_set_expiration: librnp.declare( + "rnp_key_set_expiration", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t + ), + + rnp_key_revoke: librnp.declare( + "rnp_key_revoke", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.char.ptr + ), + + rnp_key_export_autocrypt: librnp.declare( + "rnp_key_export_autocrypt", + abi, + rnp_result_t, + rnp_key_handle_t, + rnp_key_handle_t, + ctypes.char.ptr, + rnp_output_t, + ctypes.uint32_t + ), + + rnp_key_valid_till: librnp.declare( + "rnp_key_valid_till", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint32_t.ptr + ), + + rnp_key_valid_till64: librnp.declare( + "rnp_key_valid_till64", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.uint64_t.ptr + ), + + rnp_uid_is_valid: librnp.declare( + "rnp_uid_is_valid", + abi, + rnp_result_t, + rnp_uid_handle_t, + ctypes.bool.ptr + ), + + rnp_uid_is_primary: librnp.declare( + "rnp_uid_is_primary", + abi, + rnp_result_t, + rnp_uid_handle_t, + ctypes.bool.ptr + ), + + rnp_signature_is_valid: librnp.declare( + "rnp_signature_is_valid", + abi, + rnp_result_t, + rnp_signature_handle_t, + ctypes.uint32_t + ), + + rnp_key_get_protection_type: librnp.declare( + "rnp_key_get_protection_type", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_output_armor_set_line_length: librnp.declare( + "rnp_output_armor_set_line_length", + abi, + rnp_result_t, + rnp_output_t, + ctypes.size_t + ), + + rnp_key_25519_bits_tweaked: librnp.declare( + "rnp_key_25519_bits_tweaked", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.bool.ptr + ), + + rnp_key_25519_bits_tweak: librnp.declare( + "rnp_key_25519_bits_tweak", + abi, + rnp_result_t, + rnp_key_handle_t + ), + + rnp_key_get_curve: librnp.declare( + "rnp_key_get_curve", + abi, + rnp_result_t, + rnp_key_handle_t, + ctypes.char.ptr.ptr + ), + + rnp_get_security_rule: librnp.declare( + "rnp_get_security_rule", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.uint64_t, + ctypes.uint32_t.ptr, + ctypes.uint64_t.ptr, + ctypes.uint32_t.ptr + ), + + rnp_add_security_rule: librnp.declare( + "rnp_add_security_rule", + abi, + rnp_result_t, + rnp_ffi_t, + ctypes.char.ptr, + ctypes.char.ptr, + ctypes.uint32_t, + ctypes.uint64_t, + ctypes.uint32_t + ), + + rnp_op_encrypt_set_aead: librnp.declare( + "rnp_op_encrypt_set_aead", + abi, + rnp_result_t, + rnp_op_encrypt_t, + ctypes.char.ptr + ), + + rnp_op_encrypt_set_flags: librnp.declare( + "rnp_op_encrypt_set_flags", + abi, + rnp_result_t, + rnp_op_encrypt_t, + ctypes.uint32_t + ), + + rnp_result_t, + rnp_ffi_t, + rnp_password_cb_t, + rnp_input_t, + rnp_output_t, + rnp_key_handle_t, + rnp_uid_handle_t, + rnp_identifier_iterator_t, + rnp_op_generate_t, + rnp_op_encrypt_t, + rnp_op_sign_t, + rnp_op_sign_signature_t, + rnp_op_verify_t, + rnp_op_verify_signature_t, + rnp_signature_handle_t, + rnp_recipient_handle_t, + rnp_symenc_handle_t, + + RNP_LOAD_SAVE_PUBLIC_KEYS: 1, + RNP_LOAD_SAVE_SECRET_KEYS: 2, + RNP_LOAD_SAVE_PERMISSIVE: 256, + + RNP_KEY_REMOVE_PUBLIC: 1, + RNP_KEY_REMOVE_SECRET: 2, + RNP_KEY_REMOVE_SUBKEYS: 4, + + RNP_KEY_EXPORT_ARMORED: 1, + RNP_KEY_EXPORT_PUBLIC: 2, + RNP_KEY_EXPORT_SECRET: 4, + RNP_KEY_EXPORT_SUBKEYS: 8, + + RNP_KEY_SIGNATURE_NON_SELF_SIG: 4, + + RNP_SUCCESS: 0x00000000, + + RNP_FEATURE_SYMM_ALG: "symmetric algorithm", + RNP_FEATURE_HASH_ALG: "hash algorithm", + RNP_FEATURE_PK_ALG: "public key algorithm", + RNP_ALGNAME_MD5: "MD5", + RNP_ALGNAME_SHA1: "SHA1", + RNP_ALGNAME_SM2: "SM2", + RNP_ALGNAME_SM3: "SM3", + RNP_ALGNAME_SM4: "SM4", + + RNP_SECURITY_OVERRIDE: 1, + RNP_SECURITY_VERIFY_KEY: 2, + RNP_SECURITY_VERIFY_DATA: 4, + RNP_SECURITY_REMOVE_ALL: 65536, + + RNP_SECURITY_PROHIBITED: 0, + RNP_SECURITY_INSECURE: 1, + RNP_SECURITY_DEFAULT: 2, + + RNP_ENCRYPT_NOWRAP: 1, + + /* Common error codes */ + RNP_ERROR_GENERIC: 0x10000000, // 268435456 + RNP_ERROR_BAD_FORMAT: 0x10000001, // 268435457 + RNP_ERROR_BAD_PARAMETERS: 0x10000002, // 268435458 + RNP_ERROR_NOT_IMPLEMENTED: 0x10000003, // 268435459 + RNP_ERROR_NOT_SUPPORTED: 0x10000004, // 268435460 + RNP_ERROR_OUT_OF_MEMORY: 0x10000005, // 268435461 + RNP_ERROR_SHORT_BUFFER: 0x10000006, // 268435462 + RNP_ERROR_NULL_POINTER: 0x10000007, // 268435463 + + /* Storage */ + RNP_ERROR_ACCESS: 0x11000000, // 285212672 + RNP_ERROR_READ: 0x11000001, // 285212673 + RNP_ERROR_WRITE: 0x11000002, // 285212674 + + /* Crypto */ + RNP_ERROR_BAD_STATE: 0x12000000, // 301989888 + RNP_ERROR_MAC_INVALID: 0x12000001, // 301989889 + RNP_ERROR_SIGNATURE_INVALID: 0x12000002, // 301989890 + RNP_ERROR_KEY_GENERATION: 0x12000003, // 301989891 + RNP_ERROR_BAD_PASSWORD: 0x12000004, // 301989892 + RNP_ERROR_KEY_NOT_FOUND: 0x12000005, // 301989893 + RNP_ERROR_NO_SUITABLE_KEY: 0x12000006, // 301989894 + RNP_ERROR_DECRYPT_FAILED: 0x12000007, // 301989895 + RNP_ERROR_RNG: 0x12000008, // 301989896 + RNP_ERROR_SIGNING_FAILED: 0x12000009, // 301989897 + RNP_ERROR_NO_SIGNATURES_FOUND: 0x1200000a, // 301989898 + + RNP_ERROR_SIGNATURE_EXPIRED: 0x1200000b, // 301989899 + + /* Parsing */ + RNP_ERROR_NOT_ENOUGH_DATA: 0x13000000, // 318767104 + RNP_ERROR_UNKNOWN_TAG: 0x13000001, // 318767105 + RNP_ERROR_PACKET_NOT_CONSUMED: 0x13000002, // 318767106 + RNP_ERROR_NO_USERID: 0x13000003, // 318767107 + RNP_ERROR_EOF: 0x13000004, // 318767108 + }; +} |