Fix bug#18964
[emacs.git] / lisp / epg.el
blobe4d8c1e1a024d134733c86d8c3ca252de4fca21a
1 ;;; epg.el --- the EasyPG Library -*- lexical-binding: t -*-
2 ;; Copyright (C) 1999-2000, 2002-2014 Free Software Foundation, Inc.
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
5 ;; Keywords: PGP, GnuPG
6 ;; Version: 1.0.0
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software: you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation, either version 3 of the License, or
13 ;; (at your option) any later version.
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23 ;;; Code:
25 (require 'epg-config)
26 (eval-when-compile (require 'cl-lib))
28 (defvar epg-user-id nil
29 "GnuPG ID of your default identity.")
31 (defvar epg-user-id-alist nil
32 "An alist mapping from key ID to user ID.")
34 (defvar epg-last-status nil)
35 (defvar epg-read-point nil)
36 (defvar epg-process-filter-running nil)
37 (defvar epg-pending-status-list nil)
38 (defvar epg-key-id nil)
39 (defvar epg-context nil)
40 (defvar epg-debug-buffer nil)
41 (defvar epg-agent-file nil)
42 (defvar epg-agent-mtime nil)
43 (defvar epg-error-output nil)
45 ;; from gnupg/include/cipher.h
46 (defconst epg-cipher-algorithm-alist
47 '((0 . "NONE")
48 (1 . "IDEA")
49 (2 . "3DES")
50 (3 . "CAST5")
51 (4 . "BLOWFISH")
52 (7 . "AES")
53 (8 . "AES192")
54 (9 . "AES256")
55 (10 . "TWOFISH")
56 (11 . "CAMELLIA128")
57 (12 . "CAMELLIA256")
58 (110 . "DUMMY")))
60 ;; from gnupg/include/cipher.h
61 (defconst epg-pubkey-algorithm-alist
62 '((1 . "RSA")
63 (2 . "RSA_E")
64 (3 . "RSA_S")
65 (16 . "ELGAMAL_E")
66 (17 . "DSA")
67 (20 . "ELGAMAL")))
69 ;; from gnupg/include/cipher.h
70 (defconst epg-digest-algorithm-alist
71 '((1 . "MD5")
72 (2 . "SHA1")
73 (3 . "RIPEMD160")
74 (8 . "SHA256")
75 (9 . "SHA384")
76 (10 . "SHA512")
77 (11 . "SHA224")))
79 ;; from gnupg/include/cipher.h
80 (defconst epg-compress-algorithm-alist
81 '((0 . "NONE")
82 (1 . "ZIP")
83 (2 . "ZLIB")
84 (3 . "BZIP2")))
86 (defconst epg-invalid-recipients-reason-alist
87 '((0 . "No specific reason given")
88 (1 . "Not Found")
89 (2 . "Ambiguous specification")
90 (3 . "Wrong key usage")
91 (4 . "Key revoked")
92 (5 . "Key expired")
93 (6 . "No CRL known")
94 (7 . "CRL too old")
95 (8 . "Policy mismatch")
96 (9 . "Not a secret key")
97 (10 . "Key not trusted")))
99 (defconst epg-delete-problem-reason-alist
100 '((1 . "No such key")
101 (2 . "Must delete secret key first")
102 (3 . "Ambiguous specification")))
104 (defconst epg-import-ok-reason-alist
105 '((0 . "Not actually changed")
106 (1 . "Entirely new key")
107 (2 . "New user IDs")
108 (4 . "New signatures")
109 (8 . "New subkeys")
110 (16 . "Contains private key")))
112 (defconst epg-import-problem-reason-alist
113 '((0 . "No specific reason given")
114 (1 . "Invalid Certificate")
115 (2 . "Issuer Certificate missing")
116 (3 . "Certificate Chain too long")
117 (4 . "Error storing certificate")))
119 (defconst epg-no-data-reason-alist
120 '((1 . "No armored data")
121 (2 . "Expected a packet but did not found one")
122 (3 . "Invalid packet found, this may indicate a non OpenPGP message")
123 (4 . "Signature expected but not found")))
125 (defconst epg-unexpected-reason-alist nil)
127 (defvar epg-key-validity-alist
128 '((?o . unknown)
129 (?i . invalid)
130 (?d . disabled)
131 (?r . revoked)
132 (?e . expired)
133 (?- . none)
134 (?q . undefined)
135 (?n . never)
136 (?m . marginal)
137 (?f . full)
138 (?u . ultimate)))
140 (defvar epg-key-capability-alist
141 '((?e . encrypt)
142 (?s . sign)
143 (?c . certify)
144 (?a . authentication)
145 (?D . disabled)))
147 (defvar epg-new-signature-type-alist
148 '((?D . detached)
149 (?C . clear)
150 (?S . normal)))
152 (defvar epg-dn-type-alist
153 '(("1.2.840.113549.1.9.1" . "EMail")
154 ("2.5.4.12" . "T")
155 ("2.5.4.42" . "GN")
156 ("2.5.4.4" . "SN")
157 ("0.2.262.1.10.7.20" . "NameDistinguisher")
158 ("2.5.4.16" . "ADDR")
159 ("2.5.4.15" . "BC")
160 ("2.5.4.13" . "D")
161 ("2.5.4.17" . "PostalCode")
162 ("2.5.4.65" . "Pseudo")
163 ("2.5.4.5" . "SerialNumber")))
165 (defvar epg-prompt-alist nil)
167 (define-error 'epg-error "GPG error")
169 (cl-defstruct (epg-data
170 (:constructor nil)
171 (:constructor epg-make-data-from-file (file))
172 (:constructor epg-make-data-from-string (string))
173 (:copier nil)
174 (:predicate nil))
175 (file nil :read-only t)
176 (string nil :read-only t))
178 (defmacro epg--gv-nreverse (place)
179 (gv-letplace (getter setter) place
180 (funcall setter `(nreverse ,getter))))
182 (cl-defstruct (epg-context
183 (:constructor nil)
184 (:constructor epg-context--make
185 (protocol &optional armor textmode include-certs
186 cipher-algorithm digest-algorithm
187 compress-algorithm
188 &aux
189 (program
190 (pcase protocol
191 (`OpenPGP epg-gpg-program)
192 (`CMS epg-gpgsm-program)
193 (_ (signal 'epg-error
194 (list "unknown protocol" protocol)))))))
195 (:copier nil)
196 (:predicate nil))
197 protocol
198 program
199 (home-directory epg-gpg-home-directory)
200 armor
201 textmode
202 include-certs
203 cipher-algorithm
204 digest-algorithm
205 compress-algorithm
206 (passphrase-callback (list #'epg-passphrase-callback-function))
207 progress-callback
208 signers
209 sig-notations
210 process
211 output-file
212 result
213 operation
214 pinentry-mode
215 (error-output ""))
217 ;; This is not an alias, just so we can mark it as autoloaded.
218 ;;;###autoload
219 (defun epg-make-context (&optional protocol armor textmode include-certs
220 cipher-algorithm digest-algorithm
221 compress-algorithm)
222 "Return a context object."
223 (epg-context--make (or protocol 'OpenPGP)
224 armor textmode include-certs
225 cipher-algorithm digest-algorithm
226 compress-algorithm))
228 (defun epg-context-set-armor (context armor)
229 "Specify if the output should be ASCII armored in CONTEXT."
230 (declare (obsolete setf "25.1"))
231 (setf (epg-context-armor context) armor))
233 (defun epg-context-set-textmode (context textmode)
234 "Specify if canonical text mode should be used in CONTEXT."
235 (declare (obsolete setf "25.1"))
236 (setf (epg-context-textmode context) textmode))
238 (defun epg-context-set-passphrase-callback (context
239 passphrase-callback)
240 "Set the function used to query passphrase.
242 PASSPHRASE-CALLBACK is either a function, or a cons-cell whose
243 car is a function and cdr is a callback data.
245 The function gets three arguments: the context, the key-id in
246 question, and the callback data (if any).
248 The callback may not be called if you use GnuPG 2.x, which relies
249 on the external program called `gpg-agent' for passphrase query.
250 If you really want to intercept passphrase query, consider
251 installing GnuPG 1.x _along with_ GnuPG 2.x, which does passphrase
252 query by itself and Emacs can intercept them."
253 ;; (declare (obsolete setf "25.1"))
254 (setf (epg-context-passphrase-callback context)
255 (if (consp passphrase-callback) ;FIXME: functions can also be consp!
256 passphrase-callback
257 (list passphrase-callback))))
259 (defun epg-context-set-progress-callback (context
260 progress-callback)
261 "Set the function which handles progress update.
263 PROGRESS-CALLBACK is either a function, or a cons-cell whose
264 car is a function and cdr is a callback data.
266 The function gets six arguments: the context, the operation
267 description, the character to display a progress unit, the
268 current amount done, the total amount to be done, and the
269 callback data (if any)."
270 (setf (epg-context-progress-callback context)
271 (if (consp progress-callback) ;FIXME: could be a function!
272 progress-callback
273 (list progress-callback))))
275 (defun epg-context-set-signers (context signers)
276 "Set the list of key-id for signing."
277 (declare (obsolete setf "25.1"))
278 (setf (epg-context-signers context) signers))
280 (cl-defstruct (epg-signature
281 (:constructor nil)
282 (:constructor epg-make-signature
283 (status &optional key-id))
284 (:copier nil)
285 (:predicate nil))
286 status
287 key-id
288 validity
289 fingerprint
290 creation-time
291 expiration-time
292 pubkey-algorithm
293 digest-algorithm
294 class
295 version
296 notations)
298 (cl-defstruct (epg-new-signature
299 (:constructor nil)
300 (:constructor epg-make-new-signature
301 (type pubkey-algorithm digest-algorithm
302 class creation-time fingerprint))
303 (:copier nil)
304 (:predicate nil))
305 (type nil :read-only t)
306 (pubkey-algorithm nil :read-only t)
307 (digest-algorithm nil :read-only t)
308 (class nil :read-only t)
309 (creation-time nil :read-only t)
310 (fingerprint nil :read-only t))
312 (cl-defstruct (epg-key
313 (:constructor nil)
314 (:constructor epg-make-key (owner-trust))
315 (:copier nil)
316 (:predicate nil))
317 (owner-trust nil :read-only t)
318 sub-key-list user-id-list)
320 (cl-defstruct (epg-sub-key
321 (:constructor nil)
322 (:constructor epg-make-sub-key
323 (validity capability secret-p algorithm length id
324 creation-time expiration-time))
325 (:copier nil)
326 (:predicate nil))
327 validity capability secret-p algorithm length id
328 creation-time expiration-time fingerprint)
330 (cl-defstruct (epg-user-id
331 (:constructor nil)
332 (:constructor epg-make-user-id (validity string))
333 (:copier nil)
334 (:predicate nil))
335 validity string signature-list)
337 (cl-defstruct (epg-key-signature
338 (:constructor nil)
339 (:constructor epg-make-key-signature
340 (validity pubkey-algorithm key-id creation-time
341 expiration-time user-id class
342 exportable-p))
343 (:copier nil)
344 (:predicate nil))
345 validity pubkey-algorithm key-id creation-time
346 expiration-time user-id class
347 exportable-p)
349 (cl-defstruct (epg-sig-notation
350 (:constructor nil)
351 (:constructor epg-make-sig-notation
352 (name value &optional human-readable critical))
353 (:copier nil)
354 (:predicate nil))
355 name value human-readable critical)
357 (cl-defstruct (epg-import-status
358 (:constructor nil)
359 (:constructor epg-make-import-status
360 (fingerprint
361 &optional reason new user-id signature sub-key secret))
362 (:copier nil)
363 (:predicate nil))
364 fingerprint reason new user-id signature sub-key secret)
366 (cl-defstruct (epg-import-result
367 (:constructor nil)
368 (:constructor epg-make-import-result
369 (considered no-user-id imported imported-rsa
370 unchanged new-user-ids new-sub-keys
371 new-signatures new-revocations
372 secret-read secret-imported
373 secret-unchanged not-imported
374 imports))
375 (:copier nil)
376 (:predicate nil))
377 considered no-user-id imported imported-rsa
378 unchanged new-user-ids new-sub-keys
379 new-signatures new-revocations
380 secret-read secret-imported
381 secret-unchanged not-imported
382 imports)
384 (defun epg-context-result-for (context name)
385 "Return the result of CONTEXT associated with NAME."
386 (cdr (assq name (epg-context-result context))))
388 (defun epg-context-set-result-for (context name value)
389 "Set the result of CONTEXT associated with NAME to VALUE."
390 (let* ((result (epg-context-result context))
391 (entry (assq name result)))
392 (if entry
393 (setcdr entry value)
394 (setf (epg-context-result context) (cons (cons name value) result)))))
396 (defun epg-signature-to-string (signature)
397 "Convert SIGNATURE to a human readable string."
398 (let* ((user-id (cdr (assoc (epg-signature-key-id signature)
399 epg-user-id-alist)))
400 (pubkey-algorithm (epg-signature-pubkey-algorithm signature))
401 (key-id (epg-signature-key-id signature)))
402 (concat
403 (cond ((eq (epg-signature-status signature) 'good)
404 "Good signature from ")
405 ((eq (epg-signature-status signature) 'bad)
406 "Bad signature from ")
407 ((eq (epg-signature-status signature) 'expired)
408 "Expired signature from ")
409 ((eq (epg-signature-status signature) 'expired-key)
410 "Signature made by expired key ")
411 ((eq (epg-signature-status signature) 'revoked-key)
412 "Signature made by revoked key ")
413 ((eq (epg-signature-status signature) 'no-pubkey)
414 "No public key for "))
415 key-id
416 (if user-id
417 (concat " "
418 (if (stringp user-id)
419 user-id
420 (epg-decode-dn user-id)))
422 (if (epg-signature-validity signature)
423 (format " (trust %s)" (epg-signature-validity signature))
425 (if (epg-signature-creation-time signature)
426 (format-time-string " created at %Y-%m-%dT%T%z"
427 (epg-signature-creation-time signature))
429 (if pubkey-algorithm
430 (concat " using "
431 (or (cdr (assq pubkey-algorithm epg-pubkey-algorithm-alist))
432 (format "(unknown algorithm %d)" pubkey-algorithm)))
433 ""))))
435 (defun epg-verify-result-to-string (verify-result)
436 "Convert VERIFY-RESULT to a human readable string."
437 (mapconcat #'epg-signature-to-string verify-result "\n"))
439 (defun epg-new-signature-to-string (new-signature)
440 "Convert NEW-SIGNATURE to a human readable string."
441 (concat
442 (cond ((eq (epg-new-signature-type new-signature) 'detached)
443 "Detached signature ")
444 ((eq (epg-new-signature-type new-signature) 'clear)
445 "Cleartext signature ")
447 "Signature "))
448 (cdr (assq (epg-new-signature-pubkey-algorithm new-signature)
449 epg-pubkey-algorithm-alist))
451 (cdr (assq (epg-new-signature-digest-algorithm new-signature)
452 epg-digest-algorithm-alist))
454 (format "%02X " (epg-new-signature-class new-signature))
455 (epg-new-signature-fingerprint new-signature)))
457 (defun epg-import-result-to-string (import-result)
458 "Convert IMPORT-RESULT to a human readable string."
459 (concat (format "Total number processed: %d\n"
460 (epg-import-result-considered import-result))
461 (if (> (epg-import-result-not-imported import-result) 0)
462 (format " skipped new keys: %d\n"
463 (epg-import-result-not-imported import-result)))
464 (if (> (epg-import-result-no-user-id import-result) 0)
465 (format " w/o user IDs: %d\n"
466 (epg-import-result-no-user-id import-result)))
467 (if (> (epg-import-result-imported import-result) 0)
468 (concat (format " imported: %d"
469 (epg-import-result-imported import-result))
470 (if (> (epg-import-result-imported-rsa import-result) 0)
471 (format " (RSA: %d)"
472 (epg-import-result-imported-rsa
473 import-result)))
474 "\n"))
475 (if (> (epg-import-result-unchanged import-result) 0)
476 (format " unchanged: %d\n"
477 (epg-import-result-unchanged import-result)))
478 (if (> (epg-import-result-new-user-ids import-result) 0)
479 (format " new user IDs: %d\n"
480 (epg-import-result-new-user-ids import-result)))
481 (if (> (epg-import-result-new-sub-keys import-result) 0)
482 (format " new subkeys: %d\n"
483 (epg-import-result-new-sub-keys import-result)))
484 (if (> (epg-import-result-new-signatures import-result) 0)
485 (format " new signatures: %d\n"
486 (epg-import-result-new-signatures import-result)))
487 (if (> (epg-import-result-new-revocations import-result) 0)
488 (format " new key revocations: %d\n"
489 (epg-import-result-new-revocations import-result)))
490 (if (> (epg-import-result-secret-read import-result) 0)
491 (format " secret keys read: %d\n"
492 (epg-import-result-secret-read import-result)))
493 (if (> (epg-import-result-secret-imported import-result) 0)
494 (format " secret keys imported: %d\n"
495 (epg-import-result-secret-imported import-result)))
496 (if (> (epg-import-result-secret-unchanged import-result) 0)
497 (format " secret keys unchanged: %d\n"
498 (epg-import-result-secret-unchanged import-result)))))
500 (defun epg-error-to-string (error)
501 (cond
502 ((eq (car error) 'exit)
503 "Exit")
504 ((eq (car error) 'quit)
505 "Canceled")
506 ((eq (car error) 'no-data)
507 (let ((entry (assq (cdr error) epg-no-data-reason-alist)))
508 (if entry
509 (format "No data (%s)" (downcase (cdr entry)))
510 "No data")))
511 ((eq (car error) 'unexpected)
512 (let ((entry (assq (cdr error) epg-unexpected-reason-alist)))
513 (if entry
514 (format "Unexpected (%s)" (downcase (cdr entry)))
515 "Unexpected")))
516 ((eq (car error) 'bad-armor)
517 "Bad armor")
518 ((memq (car error) '(invalid-recipient invalid-signer))
519 (concat
520 (if (eq (car error) 'invalid-recipient)
521 "Unusable public key"
522 "Unusable secret key")
523 (let ((entry (assq 'requested (cdr error))))
524 (if entry
525 (format ": %s" (cdr entry))
526 ": <unknown>"))
527 (let ((entry (assq 'reason (cdr error))))
528 (if (and entry
529 (> (cdr entry) 0) ;no specific reason given
530 (setq entry (assq (cdr entry)
531 epg-invalid-recipients-reason-alist)))
532 (format " (%s)" (downcase (cdr entry)))
533 ""))))
534 ((eq (car error) 'no-pubkey)
535 (format "No public key: %s" (cdr error)))
536 ((eq (car error) 'no-seckey)
537 (format "No secret key: %s" (cdr error)))
538 ((eq (car error) 'no-recipients)
539 "No recipients")
540 ((eq (car error) 'no-signers)
541 "No signers")
542 ((eq (car error) 'delete-problem)
543 (let ((entry (assq (cdr error) epg-delete-problem-reason-alist)))
544 (if entry
545 (format "Delete problem (%s)" (downcase (cdr entry)))
546 "Delete problem")))
547 ((eq (car error) 'key-not-created)
548 "Key not created")))
550 (defun epg-errors-to-string (errors)
551 (mapconcat #'epg-error-to-string errors "; "))
553 (defun epg--start (context args)
554 "Start `epg-gpg-program' in a subprocess with given ARGS."
555 (if (and (epg-context-process context)
556 (eq (process-status (epg-context-process context)) 'run))
557 (error "%s is already running in this context"
558 (epg-context-program context)))
559 (let* ((agent-info (getenv "GPG_AGENT_INFO"))
560 (args (append (list "--no-tty"
561 "--status-fd" "1"
562 "--yes")
563 (if (and (not (eq (epg-context-protocol context) 'CMS))
564 (string-match ":" (or agent-info "")))
565 '("--use-agent"))
566 (if (and (not (eq (epg-context-protocol context) 'CMS))
567 (epg-context-progress-callback context))
568 '("--enable-progress-filter"))
569 (if (epg-context-home-directory context)
570 (list "--homedir"
571 (epg-context-home-directory context)))
572 (unless (eq (epg-context-protocol context) 'CMS)
573 '("--command-fd" "0"))
574 (if (epg-context-armor context) '("--armor"))
575 (if (epg-context-textmode context) '("--textmode"))
576 (if (epg-context-output-file context)
577 (list "--output" (epg-context-output-file context)))
578 (if (epg-context-pinentry-mode context)
579 (list "--pinentry-mode"
580 (symbol-name (epg-context-pinentry-mode
581 context))))
582 args))
583 (coding-system-for-write 'binary)
584 (coding-system-for-read 'binary)
585 process-connection-type
586 (process-environment process-environment)
587 (buffer (generate-new-buffer " *epg*"))
588 process
589 terminal-name
590 agent-file
591 (agent-mtime '(0 0 0 0)))
592 ;; Set GPG_TTY and TERM for pinentry-curses. Note that we can't
593 ;; use `terminal-name' here to get the real pty name for the child
594 ;; process, though /dev/fd/0" is not portable.
595 (unless (memq system-type '(ms-dos windows-nt))
596 (with-temp-buffer
597 (condition-case nil
598 (when (= (call-process "tty" "/dev/fd/0" t) 0)
599 (delete-char -1)
600 (setq terminal-name (buffer-string)))
601 (file-error))))
602 (when terminal-name
603 (setq process-environment
604 (cons (concat "GPG_TTY=" terminal-name)
605 (cons "TERM=xterm" process-environment))))
606 ;; Record modified time of gpg-agent socket to restore the Emacs
607 ;; frame on text terminal in `epg-wait-for-completion'.
608 ;; See
609 ;; <http://lists.gnu.org/archive/html/emacs-devel/2007-02/msg00755.html>
610 ;; for more details.
611 (when (and agent-info (string-match "\\(.*\\):[0-9]+:[0-9]+" agent-info))
612 (setq agent-file (match-string 1 agent-info)
613 agent-mtime (or (nth 5 (file-attributes agent-file)) '(0 0 0 0))))
614 (if epg-debug
615 (save-excursion
616 (unless epg-debug-buffer
617 (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
618 (set-buffer epg-debug-buffer)
619 (goto-char (point-max))
620 (insert (if agent-info
621 (format "GPG_AGENT_INFO=%s\n" agent-info)
622 "GPG_AGENT_INFO is not set\n")
623 (format "%s %s\n"
624 (epg-context-program context)
625 (mapconcat #'identity args " ")))))
626 (with-current-buffer buffer
627 (if (fboundp 'set-buffer-multibyte)
628 (set-buffer-multibyte nil))
629 (make-local-variable 'epg-last-status)
630 (setq epg-last-status nil)
631 (make-local-variable 'epg-read-point)
632 (setq epg-read-point (point-min))
633 (make-local-variable 'epg-process-filter-running)
634 (setq epg-process-filter-running nil)
635 (make-local-variable 'epg-pending-status-list)
636 (setq epg-pending-status-list nil)
637 (make-local-variable 'epg-key-id)
638 (setq epg-key-id nil)
639 (make-local-variable 'epg-context)
640 (setq epg-context context)
641 (make-local-variable 'epg-agent-file)
642 (setq epg-agent-file agent-file)
643 (make-local-variable 'epg-agent-mtime)
644 (setq epg-agent-mtime agent-mtime)
645 (make-local-variable 'epg-error-output)
646 (setq epg-error-output nil))
647 (with-file-modes 448
648 (setq process (apply #'start-process "epg" buffer
649 (epg-context-program context) args)))
650 (set-process-filter process #'epg--process-filter)
651 (setf (epg-context-process context) process)))
653 (defun epg--process-filter (process input)
654 (if epg-debug
655 (with-current-buffer
656 (or epg-debug-buffer
657 (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
658 (goto-char (point-max))
659 (insert input)))
660 (if (buffer-live-p (process-buffer process))
661 (with-current-buffer (process-buffer process)
662 (save-excursion
663 (goto-char (point-max))
664 (insert input)
665 (unless epg-process-filter-running
666 (let ((epg-process-filter-running t))
667 (goto-char epg-read-point)
668 (beginning-of-line)
669 (while (looking-at ".*\n") ;the input line finished
670 (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
671 (let* ((status (match-string 1))
672 (string (match-string 2))
673 (symbol (intern-soft (concat "epg--status-"
674 status))))
675 (if (member status epg-pending-status-list)
676 (setq epg-pending-status-list nil))
677 (if (and symbol
678 (fboundp symbol))
679 (funcall symbol epg-context string))
680 (setq epg-last-status (cons status string)))
681 ;; Record other lines sent to stderr. This assumes
682 ;; that the process-filter receives output only from
683 ;; stderr and the FD specified with --status-fd.
684 (setq epg-error-output
685 (cons (buffer-substring (point)
686 (line-end-position))
687 epg-error-output)))
688 (forward-line)
689 (setq epg-read-point (point)))))))))
691 (defun epg-read-output (context)
692 "Read the output file CONTEXT and return the content as a string."
693 (with-temp-buffer
694 (if (fboundp 'set-buffer-multibyte)
695 (set-buffer-multibyte nil))
696 (if (file-exists-p (epg-context-output-file context))
697 (let ((coding-system-for-read 'binary))
698 (insert-file-contents (epg-context-output-file context))
699 (buffer-string)))))
701 (defun epg-wait-for-status (context status-list)
702 "Wait until one of elements in STATUS-LIST arrives."
703 (with-current-buffer (process-buffer (epg-context-process context))
704 (setq epg-pending-status-list status-list)
705 (while (and (eq (process-status (epg-context-process context)) 'run)
706 epg-pending-status-list)
707 (accept-process-output (epg-context-process context) 1))
708 (if epg-pending-status-list
709 (epg-context-set-result-for
710 context 'error
711 (cons '(exit)
712 (epg-context-result-for context 'error))))))
714 (defun epg-wait-for-completion (context)
715 "Wait until the `epg-gpg-program' process completes."
716 (while (eq (process-status (epg-context-process context)) 'run)
717 (accept-process-output (epg-context-process context) 1))
718 ;; This line is needed to run the process-filter right now.
719 (sleep-for 0.1)
720 ;; Restore Emacs frame on text terminal, when pinentry-curses has terminated.
721 (if (with-current-buffer (process-buffer (epg-context-process context))
722 (and epg-agent-file
723 (> (float-time (or (nth 5 (file-attributes epg-agent-file))
724 '(0 0 0 0)))
725 (float-time epg-agent-mtime))))
726 (redraw-frame))
727 (epg-context-set-result-for
728 context 'error
729 (nreverse (epg-context-result-for context 'error)))
730 (with-current-buffer (process-buffer (epg-context-process context))
731 (setf (epg-context-error-output context)
732 (mapconcat #'identity (nreverse epg-error-output) "\n"))))
734 (defun epg-reset (context)
735 "Reset the CONTEXT."
736 (if (and (epg-context-process context)
737 (buffer-live-p (process-buffer (epg-context-process context))))
738 (kill-buffer (process-buffer (epg-context-process context))))
739 (setf (epg-context-process context) nil))
741 (defun epg-delete-output-file (context)
742 "Delete the output file of CONTEXT."
743 (if (and (epg-context-output-file context)
744 (file-exists-p (epg-context-output-file context)))
745 (delete-file (epg-context-output-file context))))
747 (eval-and-compile
748 (if (fboundp 'decode-coding-string)
749 (defalias 'epg--decode-coding-string 'decode-coding-string)
750 (defalias 'epg--decode-coding-string 'identity)))
752 (defun epg--status-USERID_HINT (_context string)
753 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
754 (let* ((key-id (match-string 1 string))
755 (user-id (match-string 2 string))
756 (entry (assoc key-id epg-user-id-alist)))
757 (condition-case nil
758 (setq user-id (epg--decode-coding-string
759 (epg--decode-percent-escape user-id)
760 'utf-8))
761 (error))
762 (if entry
763 (setcdr entry user-id)
764 (setq epg-user-id-alist (cons (cons key-id user-id)
765 epg-user-id-alist))))))
767 (defun epg--status-NEED_PASSPHRASE (_context string)
768 (if (string-match "\\`\\([^ ]+\\)" string)
769 (setq epg-key-id (match-string 1 string))))
771 (defun epg--status-NEED_PASSPHRASE_SYM (_context _string)
772 (setq epg-key-id 'SYM))
774 (defun epg--status-NEED_PASSPHRASE_PIN (_context _string)
775 (setq epg-key-id 'PIN))
777 (eval-and-compile
778 (if (fboundp 'clear-string)
779 (defalias 'epg--clear-string 'clear-string)
780 (defun epg--clear-string (string)
781 (fillarray string 0))))
783 (eval-and-compile
784 (if (fboundp 'encode-coding-string)
785 (defalias 'epg--encode-coding-string 'encode-coding-string)
786 (defalias 'epg--encode-coding-string 'identity)))
788 (defun epg--status-GET_HIDDEN (context string)
789 (when (and epg-key-id
790 (string-match "\\`passphrase\\." string))
791 (unless (epg-context-passphrase-callback context)
792 (error "passphrase-callback not set"))
793 (let (inhibit-quit
794 passphrase
795 passphrase-with-new-line
796 encoded-passphrase-with-new-line)
797 (unwind-protect
798 (condition-case nil
799 (progn
800 (setq passphrase
801 (funcall
802 (car (epg-context-passphrase-callback context))
803 context
804 epg-key-id
805 (cdr (epg-context-passphrase-callback context))))
806 (when passphrase
807 (setq passphrase-with-new-line (concat passphrase "\n"))
808 (epg--clear-string passphrase)
809 (setq passphrase nil)
810 (if epg-passphrase-coding-system
811 (progn
812 (setq encoded-passphrase-with-new-line
813 (epg--encode-coding-string
814 passphrase-with-new-line
815 (coding-system-change-eol-conversion
816 epg-passphrase-coding-system 'unix)))
817 (epg--clear-string passphrase-with-new-line)
818 (setq passphrase-with-new-line nil))
819 (setq encoded-passphrase-with-new-line
820 passphrase-with-new-line
821 passphrase-with-new-line nil))
822 (process-send-string (epg-context-process context)
823 encoded-passphrase-with-new-line)))
824 (quit
825 (epg-context-set-result-for
826 context 'error
827 (cons '(quit)
828 (epg-context-result-for context 'error)))
829 (delete-process (epg-context-process context))))
830 (if passphrase
831 (epg--clear-string passphrase))
832 (if passphrase-with-new-line
833 (epg--clear-string passphrase-with-new-line))
834 (if encoded-passphrase-with-new-line
835 (epg--clear-string encoded-passphrase-with-new-line))))))
837 (defun epg--prompt-GET_BOOL (_context string)
838 (let ((entry (assoc string epg-prompt-alist)))
839 (y-or-n-p (if entry (cdr entry) (concat string "? ")))))
841 (defun epg--prompt-GET_BOOL-untrusted_key.override (_context _string)
842 (y-or-n-p (if (and (equal (car epg-last-status) "USERID_HINT")
843 (string-match "\\`\\([^ ]+\\) \\(.*\\)"
844 (cdr epg-last-status)))
845 (let* ((key-id (match-string 1 (cdr epg-last-status)))
846 (user-id (match-string 2 (cdr epg-last-status)))
847 (entry (assoc key-id epg-user-id-alist)))
848 (if entry
849 (setq user-id (cdr entry)))
850 (format "Untrusted key %s %s. Use anyway? " key-id user-id))
851 "Use untrusted key anyway? ")))
853 (defun epg--status-GET_BOOL (context string)
854 (let (inhibit-quit)
855 (condition-case nil
856 (if (funcall (or (intern-soft (concat "epg--prompt-GET_BOOL-" string))
857 #'epg--prompt-GET_BOOL)
858 context string)
859 (process-send-string (epg-context-process context) "y\n")
860 (process-send-string (epg-context-process context) "n\n"))
861 (quit
862 (epg-context-set-result-for
863 context 'error
864 (cons '(quit)
865 (epg-context-result-for context 'error)))
866 (delete-process (epg-context-process context))))))
868 (defun epg--status-GET_LINE (context string)
869 (let ((entry (assoc string epg-prompt-alist))
870 inhibit-quit)
871 (condition-case nil
872 (process-send-string (epg-context-process context)
873 (concat (read-string
874 (if entry
875 (cdr entry)
876 (concat string ": ")))
877 "\n"))
878 (quit
879 (epg-context-set-result-for
880 context 'error
881 (cons '(quit)
882 (epg-context-result-for context 'error)))
883 (delete-process (epg-context-process context))))))
885 (defun epg--status-*SIG (context status string)
886 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
887 (let* ((key-id (match-string 1 string))
888 (user-id (match-string 2 string))
889 (entry (assoc key-id epg-user-id-alist)))
890 (epg-context-set-result-for
891 context
892 'verify
893 (cons (epg-make-signature status key-id)
894 (epg-context-result-for context 'verify)))
895 (condition-case nil
896 (if (eq (epg-context-protocol context) 'CMS)
897 (setq user-id (epg-dn-from-string user-id))
898 (setq user-id (epg--decode-coding-string
899 (epg--decode-percent-escape user-id)
900 'utf-8)))
901 (error))
902 (if entry
903 (setcdr entry user-id)
904 (setq epg-user-id-alist
905 (cons (cons key-id user-id) epg-user-id-alist))))
906 (epg-context-set-result-for
907 context
908 'verify
909 (cons (epg-make-signature status)
910 (epg-context-result-for context 'verify)))))
912 (defun epg--status-GOODSIG (context string)
913 (epg--status-*SIG context 'good string))
915 (defun epg--status-EXPSIG (context string)
916 (epg--status-*SIG context 'expired string))
918 (defun epg--status-EXPKEYSIG (context string)
919 (epg--status-*SIG context 'expired-key string))
921 (defun epg--status-REVKEYSIG (context string)
922 (epg--status-*SIG context 'revoked-key string))
924 (defun epg--status-BADSIG (context string)
925 (epg--status-*SIG context 'bad string))
927 (defun epg--status-NO_PUBKEY (context string)
928 (if (eq (epg-context-operation context) 'verify)
929 (let ((signature (car (epg-context-result-for context 'verify))))
930 (if (and signature
931 (eq (epg-signature-status signature) 'error)
932 (equal (epg-signature-key-id signature) string))
933 (setf (epg-signature-status signature) 'no-pubkey)))
934 (epg-context-set-result-for
935 context 'error
936 (cons (cons 'no-pubkey string)
937 (epg-context-result-for context 'error)))))
939 (defun epg--status-NO_SECKEY (context string)
940 (epg-context-set-result-for
941 context 'error
942 (cons (cons 'no-seckey string)
943 (epg-context-result-for context 'error))))
945 (defun epg--time-from-seconds (seconds)
946 (let ((number-seconds (string-to-number (concat seconds ".0"))))
947 (cons (floor (/ number-seconds 65536))
948 (floor (mod number-seconds 65536)))))
950 (defun epg--status-ERRSIG (context string)
951 (if (string-match "\\`\\([^ ]+\\) \\([0-9]+\\) \\([0-9]+\\) \
952 \\([0-9A-Fa-f][0-9A-Fa-f]\\) \\([^ ]+\\) \\([0-9]+\\)"
953 string)
954 (let ((signature (epg-make-signature 'error)))
955 (epg-context-set-result-for
956 context
957 'verify
958 (cons signature
959 (epg-context-result-for context 'verify)))
960 (setf (epg-signature-key-id signature)
961 (match-string 1 string))
962 (setf (epg-signature-pubkey-algorithm signature)
963 (string-to-number (match-string 2 string)))
964 (setf (epg-signature-digest-algorithm signature)
965 (string-to-number (match-string 3 string)))
966 (setf (epg-signature-class signature)
967 (string-to-number (match-string 4 string) 16))
968 (setf (epg-signature-creation-time signature)
969 (epg--time-from-seconds (match-string 5 string))))))
971 (defun epg--status-VALIDSIG (context string)
972 (let ((signature (car (epg-context-result-for context 'verify))))
973 (when (and signature
974 (eq (epg-signature-status signature) 'good)
975 (string-match "\\`\\([^ ]+\\) [^ ]+ \\([^ ]+\\) \\([^ ]+\\) \
976 \\([0-9]+\\) [^ ]+ \\([0-9]+\\) \\([0-9]+\\) \\([0-9A-Fa-f][0-9A-Fa-f]\\) \
977 \\(.*\\)"
978 string))
979 (setf (epg-signature-fingerprint signature)
980 (match-string 1 string))
981 (setf (epg-signature-creation-time signature)
982 (epg--time-from-seconds (match-string 2 string)))
983 (unless (equal (match-string 3 string) "0")
984 (setf (epg-signature-expiration-time signature)
985 (epg--time-from-seconds (match-string 3 string))))
986 (setf (epg-signature-version signature)
987 (string-to-number (match-string 4 string)))
988 (setf (epg-signature-pubkey-algorithm signature)
989 (string-to-number (match-string 5 string)))
990 (setf (epg-signature-digest-algorithm signature)
991 (string-to-number (match-string 6 string)))
992 (setf (epg-signature-class signature)
993 (string-to-number (match-string 7 string) 16)))))
995 (defun epg--status-TRUST_UNDEFINED (context _string)
996 (let ((signature (car (epg-context-result-for context 'verify))))
997 (if (and signature
998 (eq (epg-signature-status signature) 'good))
999 (setf (epg-signature-validity signature) 'undefined))))
1001 (defun epg--status-TRUST_NEVER (context _string)
1002 (let ((signature (car (epg-context-result-for context 'verify))))
1003 (if (and signature
1004 (eq (epg-signature-status signature) 'good))
1005 (setf (epg-signature-validity signature) 'never))))
1007 (defun epg--status-TRUST_MARGINAL (context _string)
1008 (let ((signature (car (epg-context-result-for context 'verify))))
1009 (if (and signature
1010 (eq (epg-signature-status signature) 'marginal))
1011 (setf (epg-signature-validity signature) 'marginal))))
1013 (defun epg--status-TRUST_FULLY (context _string)
1014 (let ((signature (car (epg-context-result-for context 'verify))))
1015 (if (and signature
1016 (eq (epg-signature-status signature) 'good))
1017 (setf (epg-signature-validity signature) 'full))))
1019 (defun epg--status-TRUST_ULTIMATE (context _string)
1020 (let ((signature (car (epg-context-result-for context 'verify))))
1021 (if (and signature
1022 (eq (epg-signature-status signature) 'good))
1023 (setf (epg-signature-validity signature) 'ultimate))))
1025 (defun epg--status-NOTATION_NAME (context string)
1026 (let ((signature (car (epg-context-result-for context 'verify))))
1027 (if signature
1028 (push (epg-make-sig-notation string nil t nil)
1029 (epg-signature-notations signature)))))
1031 (defun epg--status-NOTATION_DATA (context string)
1032 (let ((signature (car (epg-context-result-for context 'verify)))
1033 notation)
1034 (if (and signature
1035 (setq notation (car (epg-signature-notations signature))))
1036 (setf (epg-sig-notation-value notation) string))))
1038 (defun epg--status-POLICY_URL (context string)
1039 (let ((signature (car (epg-context-result-for context 'verify))))
1040 (if signature
1041 (push (epg-make-sig-notation nil string t nil)
1042 (epg-signature-notations signature)))))
1044 (defun epg--status-PROGRESS (context string)
1045 (if (and (epg-context-progress-callback context)
1046 (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
1047 string))
1048 (funcall (car (epg-context-progress-callback context))
1049 context
1050 (match-string 1 string)
1051 (match-string 2 string)
1052 (string-to-number (match-string 3 string))
1053 (string-to-number (match-string 4 string))
1054 (cdr (epg-context-progress-callback context)))))
1056 (defun epg--status-ENC_TO (context string)
1057 (if (string-match "\\`\\([0-9A-Za-z]+\\) \\([0-9]+\\) \\([0-9]+\\)" string)
1058 (epg-context-set-result-for
1059 context 'encrypted-to
1060 (cons (list (match-string 1 string)
1061 (string-to-number (match-string 2 string))
1062 (string-to-number (match-string 3 string)))
1063 (epg-context-result-for context 'encrypted-to)))))
1065 (defun epg--status-DECRYPTION_FAILED (context _string)
1066 (epg-context-set-result-for context 'decryption-failed t))
1068 (defun epg--status-DECRYPTION_OKAY (context _string)
1069 (epg-context-set-result-for context 'decryption-okay t))
1071 (defun epg--status-NODATA (context string)
1072 (epg-context-set-result-for
1073 context 'error
1074 (cons (cons 'no-data (string-to-number string))
1075 (epg-context-result-for context 'error))))
1077 (defun epg--status-UNEXPECTED (context string)
1078 (epg-context-set-result-for
1079 context 'error
1080 (cons (cons 'unexpected (string-to-number string))
1081 (epg-context-result-for context 'error))))
1083 (defun epg--status-KEYEXPIRED (context string)
1084 (epg-context-set-result-for
1085 context 'key
1086 (cons (list 'key-expired (cons 'expiration-time
1087 (epg--time-from-seconds string)))
1088 (epg-context-result-for context 'key))))
1090 (defun epg--status-KEYREVOKED (context _string)
1091 (epg-context-set-result-for
1092 context 'key
1093 (cons '(key-revoked)
1094 (epg-context-result-for context 'key))))
1096 (defun epg--status-BADARMOR (context _string)
1097 (epg-context-set-result-for
1098 context 'error
1099 (cons '(bad-armor)
1100 (epg-context-result-for context 'error))))
1102 (defun epg--status-INV_RECP (context string)
1103 (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
1104 (epg-context-set-result-for
1105 context 'error
1106 (cons (list 'invalid-recipient
1107 (cons 'reason
1108 (string-to-number (match-string 1 string)))
1109 (cons 'requested
1110 (match-string 2 string)))
1111 (epg-context-result-for context 'error)))))
1113 (defun epg--status-INV_SGNR (context string)
1114 (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
1115 (epg-context-set-result-for
1116 context 'error
1117 (cons (list 'invalid-signer
1118 (cons 'reason
1119 (string-to-number (match-string 1 string)))
1120 (cons 'requested
1121 (match-string 2 string)))
1122 (epg-context-result-for context 'error)))))
1124 (defun epg--status-NO_RECP (context _string)
1125 (epg-context-set-result-for
1126 context 'error
1127 (cons '(no-recipients)
1128 (epg-context-result-for context 'error))))
1130 (defun epg--status-NO_SGNR (context _string)
1131 (epg-context-set-result-for
1132 context 'error
1133 (cons '(no-signers)
1134 (epg-context-result-for context 'error))))
1136 (defun epg--status-DELETE_PROBLEM (context string)
1137 (if (string-match "\\`\\([0-9]+\\)" string)
1138 (epg-context-set-result-for
1139 context 'error
1140 (cons (cons 'delete-problem
1141 (string-to-number (match-string 1 string)))
1142 (epg-context-result-for context 'error)))))
1144 (defun epg--status-SIG_CREATED (context string)
1145 (if (string-match "\\`\\([DCS]\\) \\([0-9]+\\) \\([0-9]+\\) \
1146 \\([0-9A-Fa-F][0-9A-Fa-F]\\) \\(.*\\) " string)
1147 (epg-context-set-result-for
1148 context 'sign
1149 (cons (epg-make-new-signature
1150 (cdr (assq (aref (match-string 1 string) 0)
1151 epg-new-signature-type-alist))
1152 (string-to-number (match-string 2 string))
1153 (string-to-number (match-string 3 string))
1154 (string-to-number (match-string 4 string) 16)
1155 (epg--time-from-seconds (match-string 5 string))
1156 (substring string (match-end 0)))
1157 (epg-context-result-for context 'sign)))))
1159 (defun epg--status-KEY_CREATED (context string)
1160 (if (string-match "\\`\\([BPS]\\) \\([^ ]+\\)" string)
1161 (epg-context-set-result-for
1162 context 'generate-key
1163 (cons (list (cons 'type (string-to-char (match-string 1 string)))
1164 (cons 'fingerprint (match-string 2 string)))
1165 (epg-context-result-for context 'generate-key)))))
1167 (defun epg--status-KEY_NOT_CREATED (context _string)
1168 (epg-context-set-result-for
1169 context 'error
1170 (cons '(key-not-created)
1171 (epg-context-result-for context 'error))))
1173 (defun epg--status-IMPORTED (_context string)
1174 (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
1175 (let* ((key-id (match-string 1 string))
1176 (user-id (match-string 2 string))
1177 (entry (assoc key-id epg-user-id-alist)))
1178 (condition-case nil
1179 (setq user-id (epg--decode-coding-string
1180 (epg--decode-percent-escape user-id)
1181 'utf-8))
1182 (error))
1183 (if entry
1184 (setcdr entry user-id)
1185 (setq epg-user-id-alist (cons (cons key-id user-id)
1186 epg-user-id-alist))))))
1188 (defun epg--status-IMPORT_OK (context string)
1189 (if (string-match "\\`\\([0-9]+\\)\\( \\(.+\\)\\)?" string)
1190 (let ((reason (string-to-number (match-string 1 string))))
1191 (epg-context-set-result-for
1192 context 'import-status
1193 (cons (epg-make-import-status (if (match-beginning 2)
1194 (match-string 3 string))
1196 (/= (logand reason 1) 0)
1197 (/= (logand reason 2) 0)
1198 (/= (logand reason 4) 0)
1199 (/= (logand reason 8) 0)
1200 (/= (logand reason 16) 0))
1201 (epg-context-result-for context 'import-status))))))
1203 (defun epg--status-IMPORT_PROBLEM (context string)
1204 (if (string-match "\\`\\([0-9]+\\)\\( \\(.+\\)\\)?" string)
1205 (epg-context-set-result-for
1206 context 'import-status
1207 (cons (epg-make-import-status
1208 (if (match-beginning 2)
1209 (match-string 3 string))
1210 (string-to-number (match-string 1 string)))
1211 (epg-context-result-for context 'import-status)))))
1213 (defun epg--status-IMPORT_RES (context string)
1214 (when (string-match "\\`\\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\) \
1215 \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\) \
1216 \\([0-9]+\\) \\([0-9]+\\) \\([0-9]+\\)" string)
1217 (epg-context-set-result-for
1218 context 'import
1219 (epg-make-import-result (string-to-number (match-string 1 string))
1220 (string-to-number (match-string 2 string))
1221 (string-to-number (match-string 3 string))
1222 (string-to-number (match-string 4 string))
1223 (string-to-number (match-string 5 string))
1224 (string-to-number (match-string 6 string))
1225 (string-to-number (match-string 7 string))
1226 (string-to-number (match-string 8 string))
1227 (string-to-number (match-string 9 string))
1228 (string-to-number (match-string 10 string))
1229 (string-to-number (match-string 11 string))
1230 (string-to-number (match-string 12 string))
1231 (string-to-number (match-string 13 string))
1232 (epg-context-result-for context 'import-status)))
1233 (epg-context-set-result-for context 'import-status nil)))
1235 (defun epg-passphrase-callback-function (context key-id _handback)
1236 (declare (obsolete epa-passphrase-callback-function "23.1"))
1237 (if (eq key-id 'SYM)
1238 (read-passwd "Passphrase for symmetric encryption: "
1239 (eq (epg-context-operation context) 'encrypt))
1240 (read-passwd
1241 (if (eq key-id 'PIN)
1242 "Passphrase for PIN: "
1243 (let ((entry (assoc key-id epg-user-id-alist)))
1244 (if entry
1245 (format "Passphrase for %s %s: " key-id (cdr entry))
1246 (format "Passphrase for %s: " key-id)))))))
1248 (defun epg--list-keys-1 (context name mode)
1249 (let ((args (append (if (epg-context-home-directory context)
1250 (list "--homedir"
1251 (epg-context-home-directory context)))
1252 '("--with-colons" "--no-greeting" "--batch"
1253 "--with-fingerprint" "--with-fingerprint")
1254 (unless (eq (epg-context-protocol context) 'CMS)
1255 '("--fixed-list-mode"))))
1256 (list-keys-option (if (memq mode '(t secret))
1257 "--list-secret-keys"
1258 (if (memq mode '(nil public))
1259 "--list-keys"
1260 "--list-sigs")))
1261 (coding-system-for-read 'binary)
1262 keys string field index)
1263 (if name
1264 (progn
1265 (unless (listp name)
1266 (setq name (list name)))
1267 (while name
1268 (setq args (append args (list list-keys-option (car name)))
1269 name (cdr name))))
1270 (setq args (append args (list list-keys-option))))
1271 (with-temp-buffer
1272 (apply #'call-process
1273 (epg-context-program context)
1274 nil (list t nil) nil args)
1275 (goto-char (point-min))
1276 (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
1277 (setq keys (cons (make-vector 15 nil) keys)
1278 string (match-string 0)
1279 index 0
1280 field 0)
1281 (while (and (< field (length (car keys)))
1282 (eq index
1283 (string-match "\\([^:]+\\)?:" string index)))
1284 (setq index (match-end 0))
1285 (aset (car keys) field (match-string 1 string))
1286 (setq field (1+ field))))
1287 (nreverse keys))))
1289 (defun epg--make-sub-key-1 (line)
1290 (epg-make-sub-key
1291 (if (aref line 1)
1292 (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist)))
1293 (delq nil
1294 (mapcar (lambda (char) (cdr (assq char epg-key-capability-alist)))
1295 (aref line 11)))
1296 (member (aref line 0) '("sec" "ssb"))
1297 (string-to-number (aref line 3))
1298 (string-to-number (aref line 2))
1299 (aref line 4)
1300 (epg--time-from-seconds (aref line 5))
1301 (if (aref line 6)
1302 (epg--time-from-seconds (aref line 6)))))
1304 (defun epg-list-keys (context &optional name mode)
1305 "Return a list of epg-key objects matched with NAME.
1306 If MODE is nil or 'public, only public keyring should be searched.
1307 If MODE is t or 'secret, only secret keyring should be searched.
1308 Otherwise, only public keyring should be searched and the key
1309 signatures should be included.
1310 NAME is either a string or a list of strings."
1311 (let ((lines (epg--list-keys-1 context name mode))
1312 keys cert pointer pointer-1 index string)
1313 (while lines
1314 (cond
1315 ((member (aref (car lines) 0) '("pub" "sec" "crt" "crs"))
1316 (setq cert (member (aref (car lines) 0) '("crt" "crs"))
1317 keys (cons (epg-make-key
1318 (if (aref (car lines) 8)
1319 (cdr (assq (string-to-char (aref (car lines) 8))
1320 epg-key-validity-alist))))
1321 keys))
1322 (push (epg--make-sub-key-1 (car lines))
1323 (epg-key-sub-key-list (car keys))))
1324 ((member (aref (car lines) 0) '("sub" "ssb"))
1325 (push (epg--make-sub-key-1 (car lines))
1326 (epg-key-sub-key-list (car keys))))
1327 ((equal (aref (car lines) 0) "uid")
1328 ;; Decode the UID name as a backslash escaped UTF-8 string,
1329 ;; generated by GnuPG/GpgSM.
1330 (setq string (copy-sequence (aref (car lines) 9))
1331 index 0)
1332 (while (string-match "\"" string index)
1333 (setq string (replace-match "\\\"" t t string)
1334 index (1+ (match-end 0))))
1335 (condition-case nil
1336 (setq string (epg--decode-coding-string
1337 (car (read-from-string (concat "\"" string "\"")))
1338 'utf-8))
1339 (error
1340 (setq string (aref (car lines) 9))))
1341 (push (epg-make-user-id
1342 (if (aref (car lines) 1)
1343 (cdr (assq (string-to-char (aref (car lines) 1))
1344 epg-key-validity-alist)))
1345 (if cert
1346 (condition-case nil
1347 (epg-dn-from-string string)
1348 (error string))
1349 string))
1350 (epg-key-user-id-list (car keys))))
1351 ((equal (aref (car lines) 0) "fpr")
1352 (setf (epg-sub-key-fingerprint (car (epg-key-sub-key-list (car keys))))
1353 (aref (car lines) 9)))
1354 ((equal (aref (car lines) 0) "sig")
1355 (push
1356 (epg-make-key-signature
1357 (if (aref (car lines) 1)
1358 (cdr (assq (string-to-char (aref (car lines) 1))
1359 epg-key-validity-alist)))
1360 (string-to-number (aref (car lines) 3))
1361 (aref (car lines) 4)
1362 (epg--time-from-seconds (aref (car lines) 5))
1363 (epg--time-from-seconds (aref (car lines) 6))
1364 (aref (car lines) 9)
1365 (string-to-number (aref (car lines) 10) 16)
1366 (eq (aref (aref (car lines) 10) 2) ?x))
1367 (epg-user-id-signature-list
1368 (car (epg-key-user-id-list (car keys)))))))
1369 (setq lines (cdr lines)))
1370 (setq keys (nreverse keys)
1371 pointer keys)
1372 (while pointer
1373 (epg--gv-nreverse (epg-key-sub-key-list (car pointer)))
1374 (setq pointer-1 (epg--gv-nreverse (epg-key-user-id-list (car pointer))))
1375 (while pointer-1
1376 (epg--gv-nreverse (epg-user-id-signature-list (car pointer-1)))
1377 (setq pointer-1 (cdr pointer-1)))
1378 (setq pointer (cdr pointer)))
1379 keys))
1381 (eval-and-compile
1382 (if (fboundp 'make-temp-file)
1383 (defalias 'epg--make-temp-file 'make-temp-file)
1384 (defvar temporary-file-directory)
1385 ;; stolen from poe.el.
1386 (defun epg--make-temp-file (prefix)
1387 "Create a temporary file.
1388 The returned file name (created by appending some random characters at the end
1389 of PREFIX, and expanding against `temporary-file-directory' if necessary),
1390 is guaranteed to point to a newly created empty file.
1391 You can then use `write-region' to write new data into the file."
1392 (let ((orig-modes (default-file-modes))
1393 tempdir tempfile)
1394 (setq prefix (expand-file-name prefix
1395 (if (featurep 'xemacs)
1396 (temp-directory)
1397 temporary-file-directory)))
1398 (unwind-protect
1399 (let (file)
1400 ;; First, create a temporary directory.
1401 (set-default-file-modes #o700)
1402 (while (condition-case ()
1403 (progn
1404 (setq tempdir (make-temp-name
1405 (concat
1406 (file-name-directory prefix)
1407 "DIR")))
1408 ;; return nil or signal an error.
1409 (make-directory tempdir))
1410 ;; let's try again.
1411 (file-already-exists t)))
1412 ;; Second, create a temporary file in the tempdir.
1413 ;; There *is* a race condition between `make-temp-name'
1414 ;; and `write-region', but we don't care it since we are
1415 ;; in a private directory now.
1416 (setq tempfile (make-temp-name (concat tempdir "/EMU")))
1417 (write-region "" nil tempfile nil 'silent)
1418 ;; Finally, make a hard-link from the tempfile.
1419 (while (condition-case ()
1420 (progn
1421 (setq file (make-temp-name prefix))
1422 ;; return nil or signal an error.
1423 (add-name-to-file tempfile file))
1424 ;; let's try again.
1425 (file-already-exists t)))
1426 file)
1427 (set-default-file-modes orig-modes)
1428 ;; Cleanup the tempfile.
1429 (and tempfile
1430 (file-exists-p tempfile)
1431 (delete-file tempfile))
1432 ;; Cleanup the tempdir.
1433 (and tempdir
1434 (file-directory-p tempdir)
1435 (delete-directory tempdir)))))))
1437 (defun epg--args-from-sig-notations (notations)
1438 (apply #'nconc
1439 (mapcar
1440 (lambda (notation)
1441 (if (and (epg-sig-notation-name notation)
1442 (not (epg-sig-notation-human-readable notation)))
1443 (error "Unreadable"))
1444 (if (epg-sig-notation-name notation)
1445 (list "--sig-notation"
1446 (if (epg-sig-notation-critical notation)
1447 (concat "!" (epg-sig-notation-name notation)
1448 "=" (epg-sig-notation-value notation))
1449 (concat (epg-sig-notation-name notation)
1450 "=" (epg-sig-notation-value notation))))
1451 (list "--sig-policy-url"
1452 (if (epg-sig-notation-critical notation)
1453 (concat "!" (epg-sig-notation-value notation))
1454 (epg-sig-notation-value notation)))))
1455 notations)))
1457 (defun epg-cancel (context)
1458 (if (buffer-live-p (process-buffer (epg-context-process context)))
1459 (with-current-buffer (process-buffer (epg-context-process context))
1460 (epg-context-set-result-for
1461 epg-context 'error
1462 (cons '(quit)
1463 (epg-context-result-for epg-context 'error)))))
1464 (if (eq (process-status (epg-context-process context)) 'run)
1465 (delete-process (epg-context-process context))))
1467 (defun epg-start-decrypt (context cipher)
1468 "Initiate a decrypt operation on CIPHER.
1469 CIPHER must be a file data object.
1471 If you use this function, you will need to wait for the completion of
1472 `epg-gpg-program' by using `epg-wait-for-completion' and call
1473 `epg-reset' to clear a temporary output file.
1474 If you are unsure, use synchronous version of this function
1475 `epg-decrypt-file' or `epg-decrypt-string' instead."
1476 (unless (epg-data-file cipher)
1477 (error "Not a file"))
1478 (setf (epg-context-operation context) 'decrypt)
1479 (setf (epg-context-result context) nil)
1480 (epg--start context (list "--decrypt" "--" (epg-data-file cipher)))
1481 ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1482 (unless (eq (epg-context-protocol context) 'CMS)
1483 (epg-wait-for-status context '("BEGIN_DECRYPTION"))))
1485 (defun epg--check-error-for-decrypt (context)
1486 (let ((errors (epg-context-result-for context 'error)))
1487 (if (epg-context-result-for context 'decryption-failed)
1488 (signal 'epg-error
1489 (list "Decryption failed" (epg-errors-to-string errors))))
1490 (unless (epg-context-result-for context 'decryption-okay)
1491 (signal 'epg-error
1492 (list "Can't decrypt" (epg-errors-to-string errors))))))
1494 (defun epg-decrypt-file (context cipher plain)
1495 "Decrypt a file CIPHER and store the result to a file PLAIN.
1496 If PLAIN is nil, it returns the result as a string."
1497 (unwind-protect
1498 (progn
1499 (setf (epg-context-output-file context)
1500 (or plain (epg--make-temp-file "epg-output")))
1501 (epg-start-decrypt context (epg-make-data-from-file cipher))
1502 (epg-wait-for-completion context)
1503 (epg--check-error-for-decrypt context)
1504 (unless plain
1505 (epg-read-output context)))
1506 (unless plain
1507 (epg-delete-output-file context))
1508 (epg-reset context)))
1510 (defun epg-decrypt-string (context cipher)
1511 "Decrypt a string CIPHER and return the plain text."
1512 (let ((input-file (epg--make-temp-file "epg-input"))
1513 (coding-system-for-write 'binary))
1514 (unwind-protect
1515 (progn
1516 (write-region cipher nil input-file nil 'quiet)
1517 (setf (epg-context-output-file context)
1518 (epg--make-temp-file "epg-output"))
1519 (epg-start-decrypt context (epg-make-data-from-file input-file))
1520 (epg-wait-for-completion context)
1521 (epg--check-error-for-decrypt context)
1522 (epg-read-output context))
1523 (epg-delete-output-file context)
1524 (if (file-exists-p input-file)
1525 (delete-file input-file))
1526 (epg-reset context))))
1528 (defun epg-start-verify (context signature &optional signed-text)
1529 "Initiate a verify operation on SIGNATURE.
1530 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
1532 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
1533 For a normal or a cleartext signature, SIGNED-TEXT should be nil.
1535 If you use this function, you will need to wait for the completion of
1536 `epg-gpg-program' by using `epg-wait-for-completion' and call
1537 `epg-reset' to clear a temporary output file.
1538 If you are unsure, use synchronous version of this function
1539 `epg-verify-file' or `epg-verify-string' instead."
1540 (setf (epg-context-operation context) 'verify)
1541 (setf (epg-context-result context) nil)
1542 (if signed-text
1543 ;; Detached signature.
1544 (if (epg-data-file signed-text)
1545 (epg--start context (list "--verify" "--" (epg-data-file signature)
1546 (epg-data-file signed-text)))
1547 (epg--start context (list "--verify" "--" (epg-data-file signature)
1548 "-"))
1549 (if (eq (process-status (epg-context-process context)) 'run)
1550 (process-send-string (epg-context-process context)
1551 (epg-data-string signed-text)))
1552 (if (eq (process-status (epg-context-process context)) 'run)
1553 (process-send-eof (epg-context-process context))))
1554 ;; Normal (or cleartext) signature.
1555 (if (epg-data-file signature)
1556 (epg--start context (if (eq (epg-context-protocol context) 'CMS)
1557 (list "--verify" "--" (epg-data-file signature))
1558 (list "--" (epg-data-file signature))))
1559 (epg--start context (if (eq (epg-context-protocol context) 'CMS)
1560 '("--verify" "-")
1561 '("-")))
1562 (if (eq (process-status (epg-context-process context)) 'run)
1563 (process-send-string (epg-context-process context)
1564 (epg-data-string signature)))
1565 (if (eq (process-status (epg-context-process context)) 'run)
1566 (process-send-eof (epg-context-process context))))))
1568 (defun epg-verify-file (context signature &optional signed-text plain)
1569 "Verify a file SIGNATURE.
1570 SIGNED-TEXT and PLAIN are also a file if they are specified.
1572 For a detached signature, both SIGNATURE and SIGNED-TEXT should be
1573 string. For a normal or a cleartext signature, SIGNED-TEXT should be
1574 nil. In the latter case, if PLAIN is specified, the plaintext is
1575 stored into the file after successful verification.
1577 Note that this function does not return verification result as t
1578 or nil, nor signal error on failure. That's a design decision to
1579 handle the case where SIGNATURE has multiple signature.
1581 To check the verification results, use `epg-context-result-for' as follows:
1583 \(epg-context-result-for context 'verify)
1585 which will return a list of `epg-signature' object."
1586 (unwind-protect
1587 (progn
1588 (setf (epg-context-output-file context)
1589 (or plain (epg--make-temp-file "epg-output")))
1590 (if signed-text
1591 (epg-start-verify context
1592 (epg-make-data-from-file signature)
1593 (epg-make-data-from-file signed-text))
1594 (epg-start-verify context
1595 (epg-make-data-from-file signature)))
1596 (epg-wait-for-completion context)
1597 (unless plain
1598 (epg-read-output context)))
1599 (unless plain
1600 (epg-delete-output-file context))
1601 (epg-reset context)))
1603 (defun epg-verify-string (context signature &optional signed-text)
1604 "Verify a string SIGNATURE.
1605 SIGNED-TEXT is a string if it is specified.
1607 For a detached signature, both SIGNATURE and SIGNED-TEXT should be
1608 string. For a normal or a cleartext signature, SIGNED-TEXT should be
1609 nil. In the latter case, this function returns the plaintext after
1610 successful verification.
1612 Note that this function does not return verification result as t
1613 or nil, nor signal error on failure. That's a design decision to
1614 handle the case where SIGNATURE has multiple signature.
1616 To check the verification results, use `epg-context-result-for' as follows:
1618 \(epg-context-result-for context 'verify)
1620 which will return a list of `epg-signature' object."
1621 (let ((coding-system-for-write 'binary)
1622 input-file)
1623 (unwind-protect
1624 (progn
1625 (setf (epg-context-output-file context)
1626 (epg--make-temp-file "epg-output"))
1627 (if signed-text
1628 (progn
1629 (setq input-file (epg--make-temp-file "epg-signature"))
1630 (write-region signature nil input-file nil 'quiet)
1631 (epg-start-verify context
1632 (epg-make-data-from-file input-file)
1633 (epg-make-data-from-string signed-text)))
1634 (epg-start-verify context (epg-make-data-from-string signature)))
1635 (epg-wait-for-completion context)
1636 (epg-read-output context))
1637 (epg-delete-output-file context)
1638 (if (and input-file
1639 (file-exists-p input-file))
1640 (delete-file input-file))
1641 (epg-reset context))))
1643 (defun epg-start-sign (context plain &optional mode)
1644 "Initiate a sign operation on PLAIN.
1645 PLAIN is a data object.
1647 If optional 3rd argument MODE is t or 'detached, it makes a detached signature.
1648 If it is nil or 'normal, it makes a normal signature.
1649 Otherwise, it makes a cleartext signature.
1651 If you use this function, you will need to wait for the completion of
1652 `epg-gpg-program' by using `epg-wait-for-completion' and call
1653 `epg-reset' to clear a temporary output file.
1654 If you are unsure, use synchronous version of this function
1655 `epg-sign-file' or `epg-sign-string' instead."
1656 (setf (epg-context-operation context) 'sign)
1657 (setf (epg-context-result context) nil)
1658 (unless (memq mode '(t detached nil normal)) ;i.e. cleartext
1659 (epg-context-set-armor context nil)
1660 (epg-context-set-textmode context nil))
1661 (epg--start context
1662 (append (list (if (memq mode '(t detached))
1663 "--detach-sign"
1664 (if (memq mode '(nil normal))
1665 "--sign"
1666 "--clearsign")))
1667 (apply #'nconc
1668 (mapcar
1669 (lambda (signer)
1670 (list "-u"
1671 (epg-sub-key-id
1672 (car (epg-key-sub-key-list signer)))))
1673 (epg-context-signers context)))
1674 (epg--args-from-sig-notations
1675 (epg-context-sig-notations context))
1676 (if (epg-data-file plain)
1677 (list "--" (epg-data-file plain)))))
1678 ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1679 (unless (eq (epg-context-protocol context) 'CMS)
1680 (epg-wait-for-status context '("BEGIN_SIGNING")))
1681 (when (epg-data-string plain)
1682 (if (eq (process-status (epg-context-process context)) 'run)
1683 (process-send-string (epg-context-process context)
1684 (epg-data-string plain)))
1685 (if (eq (process-status (epg-context-process context)) 'run)
1686 (process-send-eof (epg-context-process context)))))
1688 (defun epg-sign-file (context plain signature &optional mode)
1689 "Sign a file PLAIN and store the result to a file SIGNATURE.
1690 If SIGNATURE is nil, it returns the result as a string.
1691 If optional 3rd argument MODE is t or 'detached, it makes a detached signature.
1692 If it is nil or 'normal, it makes a normal signature.
1693 Otherwise, it makes a cleartext signature."
1694 (unwind-protect
1695 (progn
1696 (setf (epg-context-output-file context)
1697 (or signature (epg--make-temp-file "epg-output")))
1698 (epg-start-sign context (epg-make-data-from-file plain) mode)
1699 (epg-wait-for-completion context)
1700 (unless (epg-context-result-for context 'sign)
1701 (let ((errors (epg-context-result-for context 'error)))
1702 (signal 'epg-error
1703 (list "Sign failed" (epg-errors-to-string errors)))))
1704 (unless signature
1705 (epg-read-output context)))
1706 (unless signature
1707 (epg-delete-output-file context))
1708 (epg-reset context)))
1710 (defun epg-sign-string (context plain &optional mode)
1711 "Sign a string PLAIN and return the output as string.
1712 If optional 3rd argument MODE is t or 'detached, it makes a detached signature.
1713 If it is nil or 'normal, it makes a normal signature.
1714 Otherwise, it makes a cleartext signature."
1715 (let ((input-file
1716 (unless (or (eq (epg-context-protocol context) 'CMS)
1717 (condition-case nil
1718 (progn
1719 (epg-check-configuration (epg-configuration))
1721 (error)))
1722 (epg--make-temp-file "epg-input")))
1723 (coding-system-for-write 'binary))
1724 (unwind-protect
1725 (progn
1726 (setf (epg-context-output-file context)
1727 (epg--make-temp-file "epg-output"))
1728 (if input-file
1729 (write-region plain nil input-file nil 'quiet))
1730 (epg-start-sign context
1731 (if input-file
1732 (epg-make-data-from-file input-file)
1733 (epg-make-data-from-string plain))
1734 mode)
1735 (epg-wait-for-completion context)
1736 (unless (epg-context-result-for context 'sign)
1737 (if (epg-context-result-for context 'error)
1738 (let ((errors (epg-context-result-for context 'error)))
1739 (signal 'epg-error
1740 (list "Sign failed" (epg-errors-to-string errors))))))
1741 (epg-read-output context))
1742 (epg-delete-output-file context)
1743 (if input-file
1744 (delete-file input-file))
1745 (epg-reset context))))
1747 (defun epg-start-encrypt (context plain recipients
1748 &optional sign always-trust)
1749 "Initiate an encrypt operation on PLAIN.
1750 PLAIN is a data object.
1751 If RECIPIENTS is nil, it performs symmetric encryption.
1753 If you use this function, you will need to wait for the completion of
1754 `epg-gpg-program' by using `epg-wait-for-completion' and call
1755 `epg-reset' to clear a temporary output file.
1756 If you are unsure, use synchronous version of this function
1757 `epg-encrypt-file' or `epg-encrypt-string' instead."
1758 (setf (epg-context-operation context) 'encrypt)
1759 (setf (epg-context-result context) nil)
1760 (epg--start context
1761 (append (if always-trust '("--always-trust"))
1762 (if recipients '("--encrypt") '("--symmetric"))
1763 (if sign '("--sign"))
1764 (if sign
1765 (apply #'nconc
1766 (mapcar
1767 (lambda (signer)
1768 (list "-u"
1769 (epg-sub-key-id
1770 (car (epg-key-sub-key-list
1771 signer)))))
1772 (epg-context-signers context))))
1773 (if sign
1774 (epg--args-from-sig-notations
1775 (epg-context-sig-notations context)))
1776 (apply #'nconc
1777 (mapcar
1778 (lambda (recipient)
1779 (list "-r"
1780 (epg-sub-key-id
1781 (car (epg-key-sub-key-list recipient)))))
1782 recipients))
1783 (if (epg-data-file plain)
1784 (list "--" (epg-data-file plain)))))
1785 ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1786 (unless (eq (epg-context-protocol context) 'CMS)
1787 (epg-wait-for-status context
1788 (if sign '("BEGIN_SIGNING") '("BEGIN_ENCRYPTION"))))
1789 (when (epg-data-string plain)
1790 (if (eq (process-status (epg-context-process context)) 'run)
1791 (process-send-string (epg-context-process context)
1792 (epg-data-string plain)))
1793 (if (eq (process-status (epg-context-process context)) 'run)
1794 (process-send-eof (epg-context-process context)))))
1796 (defun epg-encrypt-file (context plain recipients
1797 cipher &optional sign always-trust)
1798 "Encrypt a file PLAIN and store the result to a file CIPHER.
1799 If CIPHER is nil, it returns the result as a string.
1800 If RECIPIENTS is nil, it performs symmetric encryption."
1801 (unwind-protect
1802 (progn
1803 (setf (epg-context-output-file context)
1804 (or cipher (epg--make-temp-file "epg-output")))
1805 (epg-start-encrypt context (epg-make-data-from-file plain)
1806 recipients sign always-trust)
1807 (epg-wait-for-completion context)
1808 (let ((errors (epg-context-result-for context 'error)))
1809 (if (and sign
1810 (not (epg-context-result-for context 'sign)))
1811 (signal 'epg-error
1812 (list "Sign failed" (epg-errors-to-string errors))))
1813 (if errors
1814 (signal 'epg-error
1815 (list "Encrypt failed" (epg-errors-to-string errors)))))
1816 (unless cipher
1817 (epg-read-output context)))
1818 (unless cipher
1819 (epg-delete-output-file context))
1820 (epg-reset context)))
1822 (defun epg-encrypt-string (context plain recipients
1823 &optional sign always-trust)
1824 "Encrypt a string PLAIN.
1825 If RECIPIENTS is nil, it performs symmetric encryption."
1826 (let ((input-file
1827 (unless (or (not sign)
1828 (eq (epg-context-protocol context) 'CMS)
1829 (condition-case nil
1830 (progn
1831 (epg-check-configuration (epg-configuration))
1833 (error)))
1834 (epg--make-temp-file "epg-input")))
1835 (coding-system-for-write 'binary))
1836 (unwind-protect
1837 (progn
1838 (setf (epg-context-output-file context)
1839 (epg--make-temp-file "epg-output"))
1840 (if input-file
1841 (write-region plain nil input-file nil 'quiet))
1842 (epg-start-encrypt context
1843 (if input-file
1844 (epg-make-data-from-file input-file)
1845 (epg-make-data-from-string plain))
1846 recipients sign always-trust)
1847 (epg-wait-for-completion context)
1848 (let ((errors (epg-context-result-for context 'error)))
1849 (if (and sign
1850 (not (epg-context-result-for context 'sign)))
1851 (signal 'epg-error
1852 (list "Sign failed" (epg-errors-to-string errors))))
1853 (if errors
1854 (signal 'epg-error
1855 (list "Encrypt failed" (epg-errors-to-string errors)))))
1856 (epg-read-output context))
1857 (epg-delete-output-file context)
1858 (if input-file
1859 (delete-file input-file))
1860 (epg-reset context))))
1862 (defun epg-start-export-keys (context keys)
1863 "Initiate an export keys operation.
1865 If you use this function, you will need to wait for the completion of
1866 `epg-gpg-program' by using `epg-wait-for-completion' and call
1867 `epg-reset' to clear a temporary output file.
1868 If you are unsure, use synchronous version of this function
1869 `epg-export-keys-to-file' or `epg-export-keys-to-string' instead."
1870 (setf (epg-context-operation context) 'export-keys)
1871 (setf (epg-context-result context) nil)
1872 (epg--start context (cons "--export"
1873 (mapcar
1874 (lambda (key)
1875 (epg-sub-key-id
1876 (car (epg-key-sub-key-list key))))
1877 keys))))
1879 (defun epg-export-keys-to-file (context keys file)
1880 "Extract public KEYS."
1881 (unwind-protect
1882 (progn
1883 (setf (epg-context-output-file context)
1884 (or file (epg--make-temp-file "epg-output")))
1885 (epg-start-export-keys context keys)
1886 (epg-wait-for-completion context)
1887 (let ((errors (epg-context-result-for context 'error)))
1888 (if errors
1889 (signal 'epg-error
1890 (list "Export keys failed"
1891 (epg-errors-to-string errors)))))
1892 (unless file
1893 (epg-read-output context)))
1894 (unless file
1895 (epg-delete-output-file context))
1896 (epg-reset context)))
1898 (defun epg-export-keys-to-string (context keys)
1899 "Extract public KEYS and return them as a string."
1900 (epg-export-keys-to-file context keys nil))
1902 (defun epg-start-import-keys (context keys)
1903 "Initiate an import keys operation.
1904 KEYS is a data object.
1906 If you use this function, you will need to wait for the completion of
1907 `epg-gpg-program' by using `epg-wait-for-completion' and call
1908 `epg-reset' to clear a temporary output file.
1909 If you are unsure, use synchronous version of this function
1910 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1911 (setf (epg-context-operation context) 'import-keys)
1912 (setf (epg-context-result context) nil)
1913 (epg--start context (if (epg-data-file keys)
1914 (list "--import" "--" (epg-data-file keys))
1915 (list "--import")))
1916 (when (epg-data-string keys)
1917 (if (eq (process-status (epg-context-process context)) 'run)
1918 (process-send-string (epg-context-process context)
1919 (epg-data-string keys)))
1920 (if (eq (process-status (epg-context-process context)) 'run)
1921 (process-send-eof (epg-context-process context)))))
1923 (defun epg--import-keys-1 (context keys)
1924 (unwind-protect
1925 (progn
1926 (epg-start-import-keys context keys)
1927 (epg-wait-for-completion context)
1928 (let ((errors (epg-context-result-for context 'error)))
1929 (if errors
1930 (signal 'epg-error
1931 (list "Import keys failed"
1932 (epg-errors-to-string errors))))))
1933 (epg-reset context)))
1935 (defun epg-import-keys-from-file (context keys)
1936 "Add keys from a file KEYS."
1937 (epg--import-keys-1 context (epg-make-data-from-file keys)))
1939 (defun epg-import-keys-from-string (context keys)
1940 "Add keys from a string KEYS."
1941 (epg--import-keys-1 context (epg-make-data-from-string keys)))
1943 (defun epg-start-receive-keys (context key-id-list)
1944 "Initiate a receive key operation.
1945 KEY-ID-LIST is a list of key IDs.
1947 If you use this function, you will need to wait for the completion of
1948 `epg-gpg-program' by using `epg-wait-for-completion' and call
1949 `epg-reset' to clear a temporary output file.
1950 If you are unsure, use synchronous version of this function
1951 `epg-receive-keys' instead."
1952 (setf (epg-context-operation context) 'receive-keys)
1953 (setf (epg-context-result context) nil)
1954 (epg--start context (cons "--recv-keys" key-id-list)))
1956 (defun epg-receive-keys (context keys)
1957 "Add keys from server.
1958 KEYS is a list of key IDs"
1959 (unwind-protect
1960 (progn
1961 (epg-start-receive-keys context keys)
1962 (epg-wait-for-completion context)
1963 (let ((errors (epg-context-result-for context 'error)))
1964 (if errors
1965 (signal 'epg-error
1966 (list "Receive keys failed"
1967 (epg-errors-to-string errors))))))
1968 (epg-reset context)))
1970 (defalias 'epg-import-keys-from-server 'epg-receive-keys)
1972 (defun epg-start-delete-keys (context keys &optional allow-secret)
1973 "Initiate a delete keys operation.
1975 If you use this function, you will need to wait for the completion of
1976 `epg-gpg-program' by using `epg-wait-for-completion' and call
1977 `epg-reset' to clear a temporary output file.
1978 If you are unsure, use synchronous version of this function
1979 `epg-delete-keys' instead."
1980 (setf (epg-context-operation context) 'delete-keys)
1981 (setf (epg-context-result context) nil)
1982 (epg--start context (cons (if allow-secret
1983 "--delete-secret-key"
1984 "--delete-key")
1985 (mapcar
1986 (lambda (key)
1987 (epg-sub-key-id
1988 (car (epg-key-sub-key-list key))))
1989 keys))))
1991 (defun epg-delete-keys (context keys &optional allow-secret)
1992 "Delete KEYS from the key ring."
1993 (unwind-protect
1994 (progn
1995 (epg-start-delete-keys context keys allow-secret)
1996 (epg-wait-for-completion context)
1997 (let ((errors (epg-context-result-for context 'error)))
1998 (if errors
1999 (signal 'epg-error
2000 (list "Delete keys failed"
2001 (epg-errors-to-string errors))))))
2002 (epg-reset context)))
2004 (defun epg-start-sign-keys (context keys &optional local)
2005 "Initiate a sign keys operation.
2007 If you use this function, you will need to wait for the completion of
2008 `epg-gpg-program' by using `epg-wait-for-completion' and call
2009 `epg-reset' to clear a temporary output file.
2010 If you are unsure, use synchronous version of this function
2011 `epg-sign-keys' instead."
2012 (declare (obsolete nil "23.1"))
2013 (setf (epg-context-operation context) 'sign-keys)
2014 (setf (epg-context-result context) nil)
2015 (epg--start context (cons (if local
2016 "--lsign-key"
2017 "--sign-key")
2018 (mapcar
2019 (lambda (key)
2020 (epg-sub-key-id
2021 (car (epg-key-sub-key-list key))))
2022 keys))))
2024 (defun epg-sign-keys (context keys &optional local)
2025 "Sign KEYS from the key ring."
2026 (declare (obsolete nil "23.1"))
2027 (unwind-protect
2028 (progn
2029 (epg-start-sign-keys context keys local)
2030 (epg-wait-for-completion context)
2031 (let ((errors (epg-context-result-for context 'error)))
2032 (if errors
2033 (signal 'epg-error
2034 (list "Sign keys failed"
2035 (epg-errors-to-string errors))))))
2036 (epg-reset context)))
2038 (defun epg-start-generate-key (context parameters)
2039 "Initiate a key generation.
2040 PARAMETERS specifies parameters for the key.
2042 If you use this function, you will need to wait for the completion of
2043 `epg-gpg-program' by using `epg-wait-for-completion' and call
2044 `epg-reset' to clear a temporary output file.
2045 If you are unsure, use synchronous version of this function
2046 `epg-generate-key-from-file' or `epg-generate-key-from-string' instead."
2047 (setf (epg-context-operation context) 'generate-key)
2048 (setf (epg-context-result context) nil)
2049 (if (epg-data-file parameters)
2050 (epg--start context (list "--batch" "--genkey" "--"
2051 (epg-data-file parameters)))
2052 (epg--start context '("--batch" "--genkey"))
2053 (if (eq (process-status (epg-context-process context)) 'run)
2054 (process-send-string (epg-context-process context)
2055 (epg-data-string parameters)))
2056 (if (eq (process-status (epg-context-process context)) 'run)
2057 (process-send-eof (epg-context-process context)))))
2059 (defun epg-generate-key-from-file (context parameters)
2060 "Generate a new key pair.
2061 PARAMETERS is a file which tells how to create the key."
2062 (unwind-protect
2063 (progn
2064 (epg-start-generate-key context (epg-make-data-from-file parameters))
2065 (epg-wait-for-completion context)
2066 (let ((errors (epg-context-result-for context 'error)))
2067 (if errors
2068 (signal 'epg-error
2069 (list "Generate key failed"
2070 (epg-errors-to-string errors))))))
2071 (epg-reset context)))
2073 (defun epg-generate-key-from-string (context parameters)
2074 "Generate a new key pair.
2075 PARAMETERS is a string which tells how to create the key."
2076 (unwind-protect
2077 (progn
2078 (epg-start-generate-key context (epg-make-data-from-string parameters))
2079 (epg-wait-for-completion context)
2080 (let ((errors (epg-context-result-for context 'error)))
2081 (if errors
2082 (signal 'epg-error
2083 (list "Generate key failed"
2084 (epg-errors-to-string errors))))))
2085 (epg-reset context)))
2087 (defun epg--decode-percent-escape (string)
2088 (let ((index 0))
2089 (while (string-match "%\\(\\(%\\)\\|\\([0-9A-Fa-f][0-9A-Fa-f]\\)\\)"
2090 string index)
2091 (if (match-beginning 2)
2092 (setq string (replace-match "%" t t string)
2093 index (1- (match-end 0)))
2094 (setq string (replace-match
2095 (string (string-to-number (match-string 3 string) 16))
2096 t t string)
2097 index (- (match-end 0) 2))))
2098 string))
2100 (defun epg--decode-hexstring (string)
2101 (let ((index 0))
2102 (while (eq index (string-match "[0-9A-Fa-f][0-9A-Fa-f]" string index))
2103 (setq string (replace-match (string (string-to-number
2104 (match-string 0 string) 16))
2105 t t string)
2106 index (1- (match-end 0))))
2107 string))
2109 (defun epg--decode-quotedstring (string)
2110 (let ((index 0))
2111 (while (string-match "\\\\\\(\\([,=+<>#;\\\"]\\)\\|\
2112 \\([0-9A-Fa-f][0-9A-Fa-f]\\)\\)"
2113 string index)
2114 (if (match-beginning 2)
2115 (setq string (replace-match "\\2" t nil string)
2116 index (1- (match-end 0)))
2117 (if (match-beginning 3)
2118 (setq string (replace-match (string (string-to-number
2119 (match-string 0 string) 16))
2120 t t string)
2121 index (- (match-end 0) 2)))))
2122 string))
2124 (defun epg-dn-from-string (string)
2125 "Parse STRING as LADPv3 Distinguished Names (RFC2253).
2126 The return value is an alist mapping from types to values."
2127 (let ((index 0)
2128 (length (length string))
2129 alist type value group)
2130 (while (< index length)
2131 (if (eq index (string-match "[ \t\n\r]*" string index))
2132 (setq index (match-end 0)))
2133 (if (eq index (string-match
2134 "\\([0-9]+\\(\\.[0-9]+\\)*\\)\[ \t\n\r]*=[ \t\n\r]*"
2135 string index))
2136 (setq type (match-string 1 string)
2137 index (match-end 0))
2138 (if (eq index (string-match "\\([0-9A-Za-z]+\\)[ \t\n\r]*=[ \t\n\r]*"
2139 string index))
2140 (setq type (match-string 1 string)
2141 index (match-end 0))))
2142 (unless type
2143 (error "Invalid type"))
2144 (if (eq index (string-match
2145 "\\([^,=+<>#;\\\"]\\|\\\\.\\)+"
2146 string index))
2147 (setq index (match-end 0)
2148 value (epg--decode-quotedstring (match-string 0 string)))
2149 (if (eq index (string-match "#\\([0-9A-Fa-f]+\\)" string index))
2150 (setq index (match-end 0)
2151 value (epg--decode-hexstring (match-string 1 string)))
2152 (if (eq index (string-match "\"\\([^\\\"]\\|\\\\.\\)*\""
2153 string index))
2154 (setq index (match-end 0)
2155 value (epg--decode-quotedstring
2156 (match-string 0 string))))))
2157 (if group
2158 (if (stringp (car (car alist)))
2159 (setcar alist (list (cons type value) (car alist)))
2160 (setcar alist (cons (cons type value) (car alist))))
2161 (if (consp (car (car alist)))
2162 (setcar alist (nreverse (car alist))))
2163 (setq alist (cons (cons type value) alist)
2164 type nil
2165 value nil))
2166 (if (eq index (string-match "[ \t\n\r]*\\([,;+]\\)" string index))
2167 (setq index (match-end 0)
2168 group (eq (aref string (match-beginning 1)) ?+))))
2169 (nreverse alist)))
2171 (defun epg-decode-dn (alist)
2172 "Convert ALIST returned by `epg-dn-from-string' to a human readable form.
2173 Type names are resolved using `epg-dn-type-alist'."
2174 (mapconcat
2175 (lambda (rdn)
2176 (if (stringp (car rdn))
2177 (let ((entry (assoc (car rdn) epg-dn-type-alist)))
2178 (if entry
2179 (format "%s=%s" (cdr entry) (cdr rdn))
2180 (format "%s=%s" (car rdn) (cdr rdn))))
2181 (concat "(" (epg-decode-dn rdn) ")")))
2182 alist
2183 ", "))
2185 (provide 'epg)
2187 ;;; epg.el ends here