summaryrefslogtreecommitdiff
path: root/lisp/gnus/mml-sec.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/gnus/mml-sec.el')
-rw-r--r--lisp/gnus/mml-sec.el534
1 files changed, 3 insertions, 531 deletions
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el
index 0a5f472079d..dbd31629f97 100644
--- a/lisp/gnus/mml-sec.el
+++ b/lisp/gnus/mml-sec.el
@@ -25,9 +25,7 @@
(eval-when-compile (require 'cl))
-(require 'gnus-util)
-(require 'epg)
-
+(autoload 'gnus-subsetp "gnus-util")
(autoload 'mail-strip-quoted-names "mail-utils")
(autoload 'mml2015-sign "mml2015")
(autoload 'mml2015-encrypt "mml2015")
@@ -42,7 +40,6 @@
(autoload 'mml-smime-encrypt-query "mml-smime")
(autoload 'mml-smime-verify "mml-smime")
(autoload 'mml-smime-verify-test "mml-smime")
-(autoload 'epa--select-keys "epa")
(defvar mml-sign-alist
'(("smime" mml-smime-sign-buffer mml-smime-sign-query)
@@ -94,7 +91,7 @@ signs and encrypt the message in one step.
Note that the output generated by using a `combined' mode is NOT
understood by all PGP implementations, in particular PGP version
-2 does not support it! See Info node `(message) Security' for
+2 does not support it! See Info node `(message)Security' for
details."
:version "22.1"
:group 'message
@@ -114,9 +111,7 @@ details."
(if (boundp 'password-cache)
password-cache
t)
- "If t, cache OpenPGP or S/MIME passphrases inside Emacs.
-Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead.
-See Info node `(message) Security'."
+ "If t, cache passphrase."
:group 'message
:type 'boolean)
@@ -430,529 +425,6 @@ If called with a prefix argument, only encrypt (do NOT sign)."
(interactive "P")
(mml-secure-message "pgpauto" (if dontsign 'encrypt 'signencrypt)))
-;;; Common functionality for mml1991.el, mml2015.el, mml-smime.el
-
-(define-obsolete-variable-alias 'mml1991-signers 'mml-secure-openpgp-signers)
-(define-obsolete-variable-alias 'mml2015-signers 'mml-secure-openpgp-signers)
-(defcustom mml-secure-openpgp-signers nil
- "A list of your own key ID(s) which will be used to sign OpenPGP messages.
-If set, it is added to the setting of `mml-secure-openpgp-sign-with-sender'."
- :group 'mime-security
- :type '(repeat (string :tag "Key ID")))
-
-(define-obsolete-variable-alias 'mml-smime-signers 'mml-secure-smime-signers)
-(defcustom mml-secure-smime-signers nil
- "A list of your own key ID(s) which will be used to sign S/MIME messages.
-If set, it is added to the setting of `mml-secure-smime-sign-with-sender'."
- :group 'mime-security
- :type '(repeat (string :tag "Key ID")))
-
-(define-obsolete-variable-alias
- 'mml1991-encrypt-to-self 'mml-secure-openpgp-encrypt-to-self)
-(define-obsolete-variable-alias
- 'mml2015-encrypt-to-self 'mml-secure-openpgp-encrypt-to-self)
-(defcustom mml-secure-openpgp-encrypt-to-self nil
- "List of own key ID(s) or t; determines additional recipients with OpenPGP.
-If t, also encrypt to key for message sender; if list, encrypt to those keys.
-With this variable, you can ensure that you can decrypt your own messages.
-Alternatives to this variable include Bcc'ing the message to yourself or
-using the encrypt-to or hidden-encrypt-to option in gpg.conf (see man gpg(1)).
-Note that this variable and the encrypt-to option give away your identity
-for *every* encryption without warning, which is not what you want if you are
-using, e.g., remailers.
-Also, use of Bcc gives away your identity for *every* encryption without
-warning, which is a bug, see:
-https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18718"
- :group 'mime-security
- :type '(choice (const :tag "None" nil)
- (const :tag "From address" t)
- (repeat (string :tag "Key ID"))))
-
-(define-obsolete-variable-alias
- 'mml-smime-encrypt-to-self 'mml-secure-smime-encrypt-to-self)
-(defcustom mml-secure-smime-encrypt-to-self nil
- "List of own key ID(s) or t; determines additional recipients with S/MIME.
-If t, also encrypt to key for message sender; if list, encrypt to those keys.
-With this variable, you can ensure that you can decrypt your own messages.
-Alternatives to this variable include Bcc'ing the message to yourself or
-using the encrypt-to option in gpgsm.conf (see man gpgsm(1)).
-Note that this variable and the encrypt-to option give away your identity
-for *every* encryption without warning, which is not what you want if you are
-using, e.g., remailers.
-Also, use of Bcc gives away your identity for *every* encryption without
-warning, which is a bug, see:
-https://debbugs.gnu.org/cgi/bugreport.cgi?bug=18718"
- :group 'mime-security
- :type '(choice (const :tag "None" nil)
- (const :tag "From address" t)
- (repeat (string :tag "Key ID"))))
-
-(define-obsolete-variable-alias
- 'mml2015-sign-with-sender 'mml-secure-openpgp-sign-with-sender)
-;mml1991-sign-with-sender did never exist.
-(defcustom mml-secure-openpgp-sign-with-sender nil
- "If t, use message sender to find an OpenPGP key to sign with."
- :group 'mime-security
- :type 'boolean)
-
-(define-obsolete-variable-alias
- 'mml-smime-sign-with-sender 'mml-secure-smime-sign-with-sender)
-(defcustom mml-secure-smime-sign-with-sender nil
- "If t, use message sender to find an S/MIME key to sign with."
- :group 'mime-security
- :type 'boolean)
-
-(define-obsolete-variable-alias
- 'mml2015-always-trust 'mml-secure-openpgp-always-trust)
-;mml1991-always-trust did never exist.
-(defcustom mml-secure-openpgp-always-trust t
- "If t, skip key validation of GnuPG on encryption."
- :group 'mime-security
- :type 'boolean)
-
-(defcustom mml-secure-fail-when-key-problem nil
- "If t, raise an error if some key is missing or several keys exist.
-Otherwise, ask the user."
- :group 'mime-security
- :type 'boolean)
-
-(defcustom mml-secure-key-preferences
- '((OpenPGP (sign) (encrypt)) (CMS (sign) (encrypt)))
- "Protocol- and usage-specific fingerprints of preferred keys.
-This variable is only relevant if a recipient owns multiple key pairs (for
-encryption) or you own multiple key pairs (for signing). In such cases,
-you will be asked which key(s) should be used, and your choice can be
-customized in this variable."
- :group 'mime-security
- :type '(alist :key-type (symbol :tag "Protocol") :value-type
- (alist :key-type (symbol :tag "Usage") :value-type
- (alist :key-type (string :tag "Name") :value-type
- (repeat (string :tag "Fingerprint"))))))
-
-(defun mml-secure-cust-usage-lookup (context usage)
- "Return preferences for CONTEXT and USAGE."
- (let* ((protocol (epg-context-protocol context))
- (protocol-prefs (cdr (assoc protocol mml-secure-key-preferences))))
- (assoc usage protocol-prefs)))
-
-(defun mml-secure-cust-fpr-lookup (context usage name)
- "Return fingerprints of preferred keys for CONTEXT, USAGE, and NAME."
- (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage))
- (fprs (assoc name (cdr usage-prefs))))
- (when fprs
- (cdr fprs))))
-
-(defun mml-secure-cust-record-keys (context usage name keys &optional save)
- "For CONTEXT, USAGE, and NAME record fingerprint(s) of KEYS.
-If optional SAVE is not nil, save customized fingerprints.
-Return keys."
- (assert keys)
- (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage))
- (curr-fprs (cdr (assoc name (cdr usage-prefs))))
- (key-fprs (mapcar 'mml-secure-fingerprint keys))
- (new-fprs (gnus-union curr-fprs key-fprs :test 'equal)))
- (if curr-fprs
- (setcdr (assoc name (cdr usage-prefs)) new-fprs)
- (setcdr usage-prefs (cons (cons name new-fprs) (cdr usage-prefs))))
- (when save
- (customize-save-variable
- 'mml-secure-key-preferences mml-secure-key-preferences))
- keys))
-
-(defun mml-secure-cust-remove-keys (context usage name)
- "Remove keys for CONTEXT, USAGE, and NAME.
-Return t if a customization for NAME was present (and has been removed)."
- (let* ((usage-prefs (mml-secure-cust-usage-lookup context usage))
- (current (assoc name usage-prefs)))
- (when current
- (setcdr usage-prefs (remove current (cdr usage-prefs)))
- t)))
-
-(defvar mml-secure-secret-key-id-list nil)
-
-(defun mml-secure-add-secret-key-id (key-id)
- "Record KEY-ID in list of secret keys."
- (add-to-list 'mml-secure-secret-key-id-list key-id))
-
-(defun mml-secure-clear-secret-key-id-list ()
- "Remove passwords from cache and clear list of secret keys."
- ;; Loosely based on code inside mml2015-epg-encrypt,
- ;; mml2015-epg-clear-decrypt, and mml2015-epg-decrypt
- (dolist (key-id mml-secure-secret-key-id-list nil)
- (password-cache-remove key-id))
- (setq mml-secure-secret-key-id-list nil))
-
-(defvar mml1991-cache-passphrase)
-(defvar mml1991-passphrase-cache-expiry)
-
-(defun mml-secure-cache-passphrase-p (protocol)
- "Return t if OpenPGP or S/MIME passphrases should be cached for PROTOCOL.
-Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead."
- (or (and (eq 'OpenPGP protocol)
- (or mml-secure-cache-passphrase
- (and (boundp 'mml2015-cache-passphrase)
- mml2015-cache-passphrase)
- (and (boundp 'mml1991-cache-passphrase)
- mml1991-cache-passphrase)))
- (and (eq 'CMS protocol)
- (or mml-secure-cache-passphrase
- (and (boundp 'mml-smime-cache-passphrase)
- mml-smime-cache-passphrase)))))
-
-(defun mml-secure-cache-expiry-interval (protocol)
- "Return time in seconds to cache passphrases for PROTOCOL.
-Passphrase caching in Emacs is NOT recommended. Use gpg-agent instead."
- (or (and (eq 'OpenPGP protocol)
- (or (and (boundp 'mml2015-passphrase-cache-expiry)
- mml2015-passphrase-cache-expiry)
- (and (boundp 'mml1991-passphrase-cache-expiry)
- mml1991-passphrase-cache-expiry)
- mml-secure-passphrase-cache-expiry))
- (and (eq 'CMS protocol)
- (or (and (boundp 'mml-smime-passphrase-cache-expiry)
- mml-smime-passphrase-cache-expiry)
- mml-secure-passphrase-cache-expiry))))
-
-(defun mml-secure-passphrase-callback (context key-id standard)
- "Ask for passphrase in CONTEXT for KEY-ID for STANDARD.
-The passphrase is read and cached."
- ;; Based on mml2015-epg-passphrase-callback.
- (if (eq key-id 'SYM)
- (epg-passphrase-callback-function context key-id nil)
- (let* ((password-cache-key-id
- (if (eq key-id 'PIN)
- "PIN"
- key-id))
- (entry (assoc key-id epg-user-id-alist))
- (passphrase
- (password-read
- (if (eq key-id 'PIN)
- "Passphrase for PIN: "
- (if entry
- (format "Passphrase for %s %s: " key-id (cdr entry))
- (format "Passphrase for %s: " key-id)))
- ;; TODO: With mml-smime.el, password-cache-key-id is not passed
- ;; as argument to password-read.
- ;; Is that on purpose? If so, the following needs to be placed
- ;; inside an if statement.
- password-cache-key-id)))
- (when passphrase
- (let ((password-cache-expiry (mml-secure-cache-expiry-interval
- (epg-context-protocol context))))
- (password-cache-add password-cache-key-id passphrase))
- (mml-secure-add-secret-key-id password-cache-key-id)
- (copy-sequence passphrase)))))
-
-(defun mml-secure-check-user-id (key recipient)
- "Check whether KEY has a non-revoked, non-expired UID for RECIPIENT."
- ;; Based on mml2015-epg-check-user-id.
- (let ((uids (epg-key-user-id-list key)))
- (catch 'break
- (dolist (uid uids nil)
- (if (and (stringp (epg-user-id-string uid))
- (equal (car (mail-header-parse-address
- (epg-user-id-string uid)))
- (car (mail-header-parse-address
- recipient)))
- (not (memq (epg-user-id-validity uid)
- '(revoked expired))))
- (throw 'break t))))))
-
-(defun mml-secure-secret-key-exists-p (context subkey)
- "Return t if keyring for CONTEXT contains secret key for public SUBKEY."
- (let* ((fpr (epg-sub-key-fingerprint subkey))
- (candidates (epg-list-keys context fpr 'secret))
- (candno (length candidates)))
- ;; If two or more subkeys with the same fingerprint exist, something is
- ;; terribly wrong.
- (when (>= candno 2)
- (error "Found %d secret keys with same fingerprint %s" candno fpr))
- (= 1 candno)))
-
-(defun mml-secure-check-sub-key (context key usage &optional fingerprint)
- "Check whether in CONTEXT the public KEY has a usable subkey for USAGE.
-This is the case if KEY is not disabled, and there is a subkey for
-USAGE that is neither revoked nor expired. Additionally, if optional
-FINGERPRINT is present and if it is not the primary key's fingerprint, then
-the returned subkey must have that FINGERPRINT. FINGERPRINT must consist of
-hexadecimal digits only (no leading \"0x\" allowed).
-If USAGE is not `encrypt', then additionally an appropriate secret key must
-be present in the keyring."
- ;; Based on mml2015-epg-check-sub-key, extended by
- ;; - check for secret keys if usage is not 'encrypt and
- ;; - check for new argument FINGERPRINT.
- (let* ((subkeys (epg-key-sub-key-list key))
- (primary (car subkeys))
- (fpr (epg-sub-key-fingerprint primary)))
- ;; The primary key will be marked as disabled, when the entire
- ;; key is disabled (see 12 Field, Format of colon listings, in
- ;; gnupg/doc/DETAILS)
- (unless (memq 'disabled (epg-sub-key-capability primary))
- (catch 'break
- (dolist (subkey subkeys nil)
- (if (and (memq usage (epg-sub-key-capability subkey))
- (not (memq (epg-sub-key-validity subkey)
- '(revoked expired)))
- (or (eq 'encrypt usage) ; Encryption works with public key.
- ;; In contrast, signing requires secret key.
- (mml-secure-secret-key-exists-p context subkey))
- (or (not fingerprint)
- (gnus-string-match-p (concat fingerprint "$") fpr)
- (gnus-string-match-p (concat fingerprint "$")
- (epg-sub-key-fingerprint subkey))))
- (throw 'break t)))))))
-
-(defun mml-secure-find-usable-keys (context name usage &optional justone)
- "In CONTEXT return a list of keys for NAME and USAGE.
-If USAGE is `encrypt' public keys are returned, otherwise secret ones.
-Only non-revoked and non-expired keys are returned whose primary key is
-not disabled.
-NAME can be an e-mail address or a key ID.
-If NAME just consists of hexadecimal digits (possibly prefixed by \"0x\"), it
-is treated as key ID for which at most one key must exist in the keyring.
-Otherwise, NAME is treated as user ID, for which no keys are returned if it
-is expired or revoked.
-If optional JUSTONE is not nil, return the first key instead of a list."
- (let* ((keys (epg-list-keys context name))
- (iskeyid (string-match "\\(0x\\)?\\([0-9a-fA-F]\\{8,\\}\\)" name))
- (fingerprint (match-string 2 name))
- result)
- (when (and iskeyid (>= (length keys) 2))
- (error
- "Name %s (for %s) looks like a key ID but multiple keys found"
- name usage))
- (catch 'break
- (dolist (key keys result)
- (if (and (or iskeyid
- (mml-secure-check-user-id key name))
- (mml-secure-check-sub-key context key usage fingerprint))
- (if justone
- (throw 'break key)
- (push key result)))))))
-
-(defun mml-secure-select-preferred-keys (context names usage)
- "Return list of preferred keys in CONTEXT for NAMES and USAGE.
-This inspects the keyrings to find keys for each name in NAMES. If several
-keys are found for a name, `mml-secure-select-keys' is used to look for
-customized preferences or have the user select preferable ones.
-When `mml-secure-fail-when-key-problem' is t, fail with an error in
-case of missing, outdated, or multiple keys."
- ;; Loosely based on code appearing inside mml2015-epg-sign and
- ;; mml2015-epg-encrypt.
- (apply
- #'nconc
- (mapcar
- (lambda (name)
- (let* ((keys (mml-secure-find-usable-keys context name usage))
- (keyno (length keys)))
- (cond ((= 0 keyno)
- (when (or mml-secure-fail-when-key-problem
- (not (y-or-n-p
- (format "No %s key for %s; skip it? "
- usage name))))
- (error "No %s key for %s" usage name)))
- ((= 1 keyno) keys)
- (t (mml-secure-select-keys context name keys usage)))))
- names)))
-
-(defun mml-secure-fingerprint (key)
- "Return fingerprint for public KEY."
- (epg-sub-key-fingerprint (car (epg-key-sub-key-list key))))
-
-(defun mml-secure-filter-keys (keys fprs)
- "Filter KEYS to subset with fingerprints in FPRS."
- (when keys
- (if (member (mml-secure-fingerprint (car keys)) fprs)
- (cons (car keys) (mml-secure-filter-keys (cdr keys) fprs))
- (mml-secure-filter-keys (cdr keys) fprs))))
-
-(defun mml-secure-normalize-cust-name (name)
- "Normalize NAME to be used for customization.
-Currently, remove ankle brackets."
- (if (string-match "^<\\(.*\\)>$" name)
- (match-string 1 name)
- name))
-
-(defun mml-secure-select-keys (context name keys usage)
- "In CONTEXT for NAME select among KEYS for USAGE.
-KEYS should be a list with multiple entries.
-NAME is normalized first as customized keys are inspected.
-When `mml-secure-fail-when-key-problem' is t, fail with an error in case of
-outdated or multiple keys."
- (let* ((nname (mml-secure-normalize-cust-name name))
- (fprs (mml-secure-cust-fpr-lookup context usage nname))
- (usable-fprs (mapcar 'mml-secure-fingerprint keys)))
- (if fprs
- (if (gnus-subsetp fprs usable-fprs)
- (mml-secure-filter-keys keys fprs)
- (mml-secure-cust-remove-keys context usage nname)
- (let ((diff (gnus-setdiff fprs usable-fprs)))
- (if mml-secure-fail-when-key-problem
- (error "Customization of %s keys for %s outdated" usage nname)
- (mml-secure-select-keys-1
- context nname keys usage (format "\
-Customized keys
- (%s)
-for %s not available any more.
-Select anew. "
- diff nname)))))
- (if mml-secure-fail-when-key-problem
- (error "Multiple %s keys for %s" usage nname)
- (mml-secure-select-keys-1
- context nname keys usage (format "\
-Multiple %s keys for:
- %s
-Select preferred one(s). "
- usage nname))))))
-
-(defun mml-secure-select-keys-1 (context name keys usage message)
- "In CONTEXT for NAME let user select among KEYS for USAGE, showing MESSAGE.
-Return selected keys."
- (let* ((selected (epa--select-keys message keys))
- (selno (length selected))
- ;; TODO: y-or-n-p does not always resize the echo area but may
- ;; truncate the message. Why? The following does not help.
- ;; yes-or-no-p shows full message, though.
- (message-truncate-lines nil))
- (if selected
- (if (y-or-n-p
- (format "%d %s key(s) selected. Store for %s? "
- selno usage name))
- (mml-secure-cust-record-keys context usage name selected 'save)
- selected)
- (unless (y-or-n-p
- (format "No %s key for %s; skip it? " usage name))
- (error "No %s key for %s" usage name)))))
-
-(defun mml-secure-signer-names (protocol sender)
- "Determine signer names for PROTOCOL and message from SENDER.
-Returned names may be e-mail addresses or key IDs and are determined based
-on `mml-secure-openpgp-signers' and `mml-secure-openpgp-sign-with-sender' with
-OpenPGP or `mml-secure-smime-signers' and `mml-secure-smime-sign-with-sender'
-with S/MIME."
- (if (eq 'OpenPGP protocol)
- (append mml-secure-openpgp-signers
- (if (and mml-secure-openpgp-sign-with-sender sender)
- (list (concat "<" sender ">"))))
- (append mml-secure-smime-signers
- (if (and mml-secure-smime-sign-with-sender sender)
- (list (concat "<" sender ">"))))))
-
-(defun mml-secure-signers (context signer-names)
- "Determine signing keys in CONTEXT from SIGNER-NAMES.
-If `mm-sign-option' is `guided', the user is asked to choose.
-Otherwise, `mml-secure-select-preferred-keys' is used."
- ;; Based on code appearing inside mml2015-epg-sign and
- ;; mml2015-epg-encrypt.
- (if (eq mm-sign-option 'guided)
- (epa-select-keys context "\
-Select keys for signing.
-If no one is selected, default secret key is used. "
- signer-names t)
- (mml-secure-select-preferred-keys context signer-names 'sign)))
-
-(defun mml-secure-self-recipients (protocol sender)
- "Determine additional recipients based on encrypt-to-self variables.
-PROTOCOL specifies OpenPGP or S/MIME for a message from SENDER."
- (let ((encrypt-to-self
- (if (eq 'OpenPGP protocol)
- mml-secure-openpgp-encrypt-to-self
- mml-secure-smime-encrypt-to-self)))
- (when encrypt-to-self
- (if (listp encrypt-to-self)
- encrypt-to-self
- (list sender)))))
-
-(defun mml-secure-recipients (protocol context config sender)
- "Determine encryption recipients.
-PROTOCOL specifies OpenPGP or S/MIME with matching CONTEXT and CONFIG
-for a message from SENDER."
- ;; Based on code appearing inside mml2015-epg-encrypt.
- (let ((recipients
- (apply #'nconc
- (mapcar
- (lambda (recipient)
- (or (epg-expand-group config recipient)
- (list (concat "<" recipient ">"))))
- (split-string
- (or (message-options-get 'message-recipients)
- (message-options-set 'message-recipients
- (read-string "Recipients: ")))
- "[ \f\t\n\r\v,]+")))))
- (nconc recipients (mml-secure-self-recipients protocol sender))
- (if (eq mm-encrypt-option 'guided)
- (setq recipients
- (epa-select-keys context "\
-Select recipients for encryption.
-If no one is selected, symmetric encryption will be performed. "
- recipients))
- (setq recipients
- (mml-secure-select-preferred-keys context recipients 'encrypt))
- (unless recipients
- (error "No recipient specified")))
- recipients))
-
-(defun mml-secure-epg-encrypt (protocol cont &optional sign)
- ;; Based on code appearing inside mml2015-epg-encrypt.
- (let* ((context (epg-make-context protocol))
- (config (epg-configuration))
- (sender (message-options-get 'message-sender))
- (recipients (mml-secure-recipients protocol context config sender))
- (signer-names (mml-secure-signer-names protocol sender))
- cipher signers)
- (when sign
- (setq signers (mml-secure-signers context signer-names))
- (epg-context-set-signers context signers))
- (when (eq 'OpenPGP protocol)
- (epg-context-set-armor context t)
- (epg-context-set-textmode context t))
- (when (mml-secure-cache-passphrase-p protocol)
- (epg-context-set-passphrase-callback
- context
- (cons 'mml-secure-passphrase-callback protocol)))
- (condition-case error
- (setq cipher
- (if (eq 'OpenPGP protocol)
- (epg-encrypt-string context (buffer-string) recipients sign
- mml-secure-openpgp-always-trust)
- (epg-encrypt-string context (buffer-string) recipients))
- mml-secure-secret-key-id-list nil)
- (error
- (mml-secure-clear-secret-key-id-list)
- (signal (car error) (cdr error))))
- cipher))
-
-(defun mml-secure-epg-sign (protocol mode)
- ;; Based on code appearing inside mml2015-epg-sign.
- (let* ((context (epg-make-context protocol))
- (sender (message-options-get 'message-sender))
- (signer-names (mml-secure-signer-names protocol sender))
- (signers (mml-secure-signers context signer-names))
- signature micalg)
- (when (eq 'OpenPGP protocol)
- (epg-context-set-armor context t)
- (epg-context-set-textmode context t))
- (epg-context-set-signers context signers)
- (when (mml-secure-cache-passphrase-p protocol)
- (epg-context-set-passphrase-callback
- context
- (cons 'mml-secure-passphrase-callback protocol)))
- (condition-case error
- (setq signature
- (if (eq 'OpenPGP protocol)
- (epg-sign-string context (buffer-string) mode)
- (epg-sign-string context
- (mm-replace-in-string (buffer-string)
- "\n" "\r\n") t))
- mml-secure-secret-key-id-list nil)
- (error
- (mml-secure-clear-secret-key-id-list)
- (signal (car error) (cdr error))))
- (if (epg-context-result-for context 'sign)
- (setq micalg (epg-new-signature-digest-algorithm
- (car (epg-context-result-for context 'sign)))))
- (cons signature micalg)))
-
(provide 'mml-sec)
;;; mml-sec.el ends here