b2ac8f163a05a20957f74221b43392c7f5e0596c
[elisp/epg.git] / epg.el
1 ;;; epg.el --- the EasyPG Library
2 ;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
3 ;;   2005, 2006 Free Software Foundation, Inc.
4 ;; Copyright (C) 2006 Daiki Ueno
5
6 ;; Author: Daiki Ueno <ueno@unixuser.org>
7 ;; Keywords: PGP, GnuPG
8
9 ;; This file is part of EasyPG.
10
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Code:
27
28 (defgroup epg ()
29   "The EasyPG Library")
30
31 (defcustom epg-gpg-program "gpg"
32   "The `gpg' executable."
33   :group 'epg
34   :type 'string)
35
36 (defcustom epg-gpgsm-program "gpgsm"
37   "The `gpgsm' executable."
38   :group 'epg
39   :type 'string)
40
41 (defconst epg-version-number "0.0.0")
42
43 (defvar epg-user-id nil
44   "GnuPG ID of your default identity.")
45
46 (defvar epg-user-id-alist nil
47   "An alist mapping from key ID to user ID.")
48
49 (defvar epg-read-point nil)
50 (defvar epg-pending-status-list nil)
51 (defvar epg-key-id nil)
52 (defvar epg-context nil)
53 (defvar epg-debug nil)
54 (defvar epg-debug-buffer nil)
55
56 ;; from gnupg/include/cipher.h
57 (defconst epg-cipher-algorithm-alist
58   '((0 . "NONE")
59     (1 . "IDEA")
60     (2 . "3DES")
61     (3 . "CAST5")
62     (4 . "BLOWFISH")
63     (7 . "AES")
64     (8 . "AES192")
65     (9 . "AES256")
66     (10 . "TWOFISH")
67     (110 . "DUMMY")))
68
69 ;; from gnupg/include/cipher.h
70 (defconst epg-pubkey-algorithm-alist
71   '((1 . "RSA")
72     (2 . "RSA_E")
73     (3 . "RSA_S")
74     (16 . "ELGAMAL_E")
75     (17 . "DSA")
76     (20 . "ELGAMAL")))
77
78 ;; from gnupg/include/cipher.h
79 (defconst epg-digest-algorithm-alist
80   '((1 . "MD5")
81     (2 . "SHA1")
82     (3 . "RMD160")
83     (8 . "SHA256")
84     (9 . "SHA384")
85     (10 . "SHA512")))
86
87 ;; from gnupg/include/cipher.h
88 (defconst epg-compress-algorithm-alist
89   '((0 . "NONE")
90     (1 . "ZIP")
91     (2 . "ZLIB")
92     (3 . "BZIP2")))
93
94 (defconst epg-invalid-recipients-alist
95   '((0 . "No specific reason given")
96     (1 . "Not Found")
97     (2 . "Ambigious specification")
98     (3 . "Wrong key usage")
99     (4 . "Key revoked")
100     (5 . "Key expired")
101     (6 . "No CRL known")
102     (7 . "CRL too old")
103     (8 . "Policy mismatch")
104     (9 . "Not a secret key")
105     (10 . "Key not trusted")))
106
107 (defconst epg-delete-problem-alist
108   '((1 . "No such key")
109     (2 . "Must delete secret key first")
110     (3 . "Ambigious specification")))
111
112 (defvar epg-key-validity-alist
113   '((?o . unknown)
114     (?i . invalid)
115     (?d . disabled)
116     (?r . revoked)
117     (?e . expired)
118     (?- . none)
119     (?q . undefined)
120     (?n . never)
121     (?m . marginal)
122     (?f . full)
123     (?u . ultimate)))
124
125 (defvar epg-key-capablity-alist
126   '((?e . encrypt)
127     (?s . sign)
128     (?c . certify)
129     (?a . authentication)))
130
131 (defvar epg-dn-type-alist
132   '(("1.2.840.113549.1.9.1" . "EMail")
133     ("2.5.4.12" . "T")
134     ("2.5.4.42" . "GN")
135     ("2.5.4.4" . "SN")
136     ("0.2.262.1.10.7.20" . "NameDistinguisher")
137     ("2.5.4.16" . "ADDR")
138     ("2.5.4.15" . "BC")
139     ("2.5.4.13" . "D")
140     ("2.5.4.17" . "PostalCode")
141     ("2.5.4.65" . "Pseudo")
142     ("2.5.4.5" . "SerialNumber")))
143
144 (defvar epg-prompt-alist nil)
145
146 (defun epg-make-data-from-file (file)
147   "Make a data object from FILE."
148   (vector file nil))
149
150 (defun epg-make-data-from-string (string)
151   "Make a data object from STRING."
152   (vector nil string))
153
154 (defun epg-data-file (data)
155   "Return the file of DATA."
156   (aref data 0))
157
158 (defun epg-data-string (data)
159   "Return the string of DATA."
160   (aref data 1))
161
162 (defun epg-make-context (&optional protocol armor textmode include-certs
163                                    cipher-algorithm digest-algorithm
164                                    compress-algorithm)
165   "Return a context object."
166   (vector protocol armor textmode include-certs
167           cipher-algorithm digest-algorithm compress-algorithm
168           #'epg-passphrase-callback-function
169           #'epg-progress-callback-function
170           nil nil nil nil))
171
172 (defun epg-context-protocol (context)
173   "Return the protocol used within CONTEXT."
174   (aref context 0))
175
176 (defun epg-context-armor (context)
177   "Return t if the output shouled be ASCII armored in CONTEXT."
178   (aref context 1))
179
180 (defun epg-context-textmode (context)
181   "Return t if canonical text mode should be used in CONTEXT."
182   (aref context 2))
183
184 (defun epg-context-include-certs (context)
185   "Return how many certificates should be included in an S/MIME signed
186 message."
187   (aref context 3))
188
189 (defun epg-context-cipher-algorithm (context)
190   "Return the cipher algorithm in CONTEXT."
191   (aref context 4))
192
193 (defun epg-context-digest-algorithm (context)
194   "Return the digest algorithm in CONTEXT."
195   (aref context 5))
196
197 (defun epg-context-compress-algorithm (context)
198   "Return the compress algorithm in CONTEXT."
199   (aref context 6))
200
201 (defun epg-context-passphrase-callback (context)
202   "Return the function used to query passphrase."
203   (aref context 7))
204
205 (defun epg-context-progress-callback (context)
206   "Return the function which handles progress update."
207   (aref context 8))
208
209 (defun epg-context-signers (context)
210   "Return the list of key-id for singning."
211   (aref context 9))
212
213 (defun epg-context-process (context)
214   "Return the process object of `epg-gpg-program'.
215 This function is for internal use only."
216   (aref context 10))
217
218 (defun epg-context-output-file (context)
219   "Return the output file of `epg-gpg-program'.
220 This function is for internal use only."
221   (aref context 11))
222
223 (defun epg-context-result (context)
224   "Return the result of the previous cryptographic operation."
225   (aref context 12))
226
227 (defun epg-context-set-protocol (context protocol)
228   "Set the protocol used within CONTEXT."
229   (aset context 0 protocol))
230
231 (defun epg-context-set-armor (context armor)
232   "Specify if the output shouled be ASCII armored in CONTEXT."
233   (aset context 1 armor))
234
235 (defun epg-context-set-textmode (context textmode)
236   "Specify if canonical text mode should be used in CONTEXT."
237   (aset context 2 textmode))
238
239 (defun epg-context-set-include-certs (context include-certs)
240  "Set how many certificates should be included in an S/MIME signed message."
241   (aset context 3 include-certs))
242
243 (defun epg-context-set-cipher-algorithm (context cipher-algorithm)
244  "Set the cipher algorithm in CONTEXT."
245   (aset context 4 cipher-algorithm))
246
247 (defun epg-context-set-digest-algorithm (context digest-algorithm)
248  "Set the digest algorithm in CONTEXT."
249   (aset context 5 digest-algorithm))
250
251 (defun epg-context-set-compress-algorithm (context compress-algorithm)
252  "Set the compress algorithm in CONTEXT."
253   (aset context 6 compress-algorithm))
254
255 (defun epg-context-set-passphrase-callback (context
256                                                  passphrase-callback)
257   "Set the function used to query passphrase."
258   (aset context 7 passphrase-callback))
259
260 (defun epg-context-set-progress-callback (context progress-callback)
261   "Set the function which handles progress update."
262   (aset context 8 progress-callback))
263
264 (defun epg-context-set-signers (context signers)
265  "Set the list of key-id for singning."
266   (aset context 9 signers))
267
268 (defun epg-context-set-process (context process)
269   "Set the process object of `epg-gpg-program'.
270 This function is for internal use only."
271   (aset context 10 process))
272
273 (defun epg-context-set-output-file (context output-file)
274   "Set the output file of `epg-gpg-program'.
275 This function is for internal use only."
276   (aset context 11 output-file))
277
278 (defun epg-context-set-result (context result)
279   "Set the result of the previous cryptographic operation."
280   (aset context 12 result))
281
282 (defun epg-make-signature (status key-id user-id)
283   "Return a signature object."
284   (vector status key-id user-id nil nil))
285
286 (defun epg-signature-status (signature)
287   "Return the status code of SIGNATURE."
288   (aref signature 0))
289
290 (defun epg-signature-key-id (signature)
291   "Return the key-id of SIGNATURE."
292   (aref signature 1))
293
294 (defun epg-signature-user-id (signature)
295   "Return the user-id of SIGNATURE."
296   (aref signature 2))
297   
298 (defun epg-signature-validity (signature)
299   "Return the validity of SIGNATURE."
300   (aref signature 3))
301
302 (defun epg-signature-fingerprint (signature)
303   "Return the fingerprint of SIGNATURE."
304   (aref signature 4))
305
306 (defun epg-signature-set-status (signature status)
307  "Set the status code of SIGNATURE."
308   (aset signature 0 status))
309
310 (defun epg-signature-set-key-id (signature key-id)
311  "Set the key-id of SIGNATURE."
312   (aset signature 1 key-id))
313
314 (defun epg-signature-set-user-id (signature user-id)
315  "Set the user-id of SIGNATURE."
316   (aset signature 2 user-id))
317   
318 (defun epg-signature-set-validity (signature validity)
319  "Set the validity of SIGNATURE."
320   (aset signature 3 validity))
321
322 (defun epg-signature-set-fingerprint (signature fingerprint)
323  "Set the fingerprint of SIGNATURE."
324   (aset signature 4 fingerprint))
325
326 (defun epg-make-key (owner-trust)
327   "Return a key object."
328   (vector owner-trust nil nil))
329
330 (defun epg-key-owner-trust (key)
331   "Return the owner trust of KEY."
332   (aref key 0))
333
334 (defun epg-key-sub-key-list (key)
335   "Return the sub key list of KEY."
336   (aref key 1))
337
338 (defun epg-key-user-id-list (key)
339   "Return the user ID list of KEY."
340   (aref key 2))
341
342 (defun epg-key-set-sub-key-list (key sub-key-list)
343   "Set the sub key list of KEY."
344   (aset key 1 sub-key-list))
345
346 (defun epg-key-set-user-id-list (key user-id-list)
347   "Set the user ID list of KEY."
348   (aset key 2 user-id-list))
349
350 (defun epg-make-sub-key (validity capability secret algorithm length id
351                                   creation-time expiration-time)
352   "Return a sub key object."
353   (vector validity capability secret algorithm length id creation-time
354           expiration-time nil))
355
356 (defun epg-sub-key-validity (sub-key)
357   "Return the validity of SUB-KEY."
358   (aref sub-key 0))
359
360 (defun epg-sub-key-capability (sub-key)
361   "Return the capability of SUB-KEY."
362   (aref sub-key 1))
363
364 (defun epg-sub-key-secret (sub-key)
365   "Return non-nil if SUB-KEY is a secret key."
366   (aref sub-key 2))
367
368 (defun epg-sub-key-algorithm (sub-key)
369   "Return the algorithm of SUB-KEY."
370   (aref sub-key 3))
371
372 (defun epg-sub-key-length (sub-key)
373   "Return the length of SUB-KEY."
374   (aref sub-key 4))
375
376 (defun epg-sub-key-id (sub-key)
377   "Return the ID of SUB-KEY."
378   (aref sub-key 5))
379
380 (defun epg-sub-key-creation-time (sub-key)
381   "Return the creation time of SUB-KEY."
382   (aref sub-key 6))
383
384 (defun epg-sub-key-expiration-time (sub-key)
385   "Return the expiration time of SUB-KEY."
386   (aref sub-key 7))
387
388 (defun epg-sub-key-fingerprint (sub-key)
389   "Return the fingerprint of SUB-KEY."
390   (aref sub-key 8))
391
392 (defun epg-sub-key-set-fingerprint (sub-key fingerprint)
393   "Set the fingerprint of SUB-KEY.
394 This function is for internal use only."
395   (aset sub-key 8 fingerprint))
396
397 (defun epg-make-user-id (validity name)
398   "Return a user ID object."
399   (vector validity name nil))
400
401 (defun epg-user-id-validity (user-id)
402   "Return the validity of USER-ID."
403   (aref user-id 0))
404
405 (defun epg-user-id-name (user-id)
406   "Return the name of USER-ID."
407   (aref user-id 1))
408
409 (defun epg-user-id-signature-list (user-id)
410   "Return the signature list of USER-ID."
411   (aref user-id 2))
412
413 (defun epg-user-id-set-signature-list (user-id signature-list)
414   "Set the signature list of USER-ID."
415   (aset user-id 2 signature-list))
416
417 (defun epg-context-result-for (context name)
418   (cdr (assq name (epg-context-result context))))
419
420 (defun epg-context-set-result-for (context name value)
421   (let* ((result (epg-context-result context))
422          (entry (assq name result)))
423     (if entry
424         (setcdr entry value)
425       (epg-context-set-result context (cons (cons name value) result)))))
426
427 (defun epg-signature-to-string (signature)
428   (format "%s signature from %s %s%s"
429           (capitalize (symbol-name (epg-signature-status signature)))
430           (epg-signature-key-id signature)
431           (epg-signature-user-id signature)
432           (if (epg-signature-validity signature)
433               (format " (trust %s)"
434                       (epg-signature-validity signature))
435             "")))
436
437 (defun epg-verify-result-to-string (verify-result)
438   (mapconcat #'epg-signature-to-string verify-result "\n"))
439
440 (defun epg-start (context args)
441   "Start `epg-gpg-program' in a subprocess with given ARGS."
442   (let* ((args (append (list "--no-tty"
443                              "--status-fd" "1"
444                              "--yes")
445                        (unless (eq (epg-context-protocol context) 'CMS)
446                          (list "--command-fd" "0"))
447                        (if (epg-context-armor context) '("--armor"))
448                        (if (epg-context-textmode context) '("--textmode"))
449                        (if (epg-context-output-file context)
450                            (list "--output" (epg-context-output-file context)))
451                        args))
452          (coding-system-for-write 'binary)
453          process-connection-type
454          (orig-mode (default-file-modes))
455          (buffer (generate-new-buffer " *epg*"))
456          process)
457     (if epg-debug
458         (save-excursion
459           (unless epg-debug-buffer
460             (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
461           (set-buffer epg-debug-buffer)
462           (goto-char (point-max))
463           (insert (format "%s %s\n"
464                           (if (eq (epg-context-protocol context) 'CMS)
465                               epg-gpgsm-program
466                            epg-gpg-program)
467                           (mapconcat #'identity args " ")))))
468     (with-current-buffer buffer
469       (make-local-variable 'epg-read-point)
470       (setq epg-read-point (point-min))
471       (make-local-variable 'epg-pending-status-list)
472       (setq epg-pending-status-list nil)
473       (make-local-variable 'epg-key-id)
474       (setq epg-key-id nil)
475       (make-local-variable 'epg-context)
476       (setq epg-context context))
477     (unwind-protect
478         (progn
479           (set-default-file-modes 448)
480           (setq process
481                 (apply #'start-process "epg" buffer
482                        (if (eq (epg-context-protocol context) 'CMS)
483                            epg-gpgsm-program
484                          epg-gpg-program)
485                        args)))
486       (set-default-file-modes orig-mode))
487     (set-process-filter process #'epg-process-filter)
488     (set-process-sentinel process #'epg-process-sentinel)
489     (epg-context-set-process context process)))
490
491 (defun epg-process-filter (process input)
492   (if epg-debug
493       (save-excursion
494         (unless epg-debug-buffer
495           (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
496         (set-buffer epg-debug-buffer)
497         (goto-char (point-max))
498         (insert input)))
499   (if (buffer-live-p (process-buffer process))
500       (save-excursion
501         (set-buffer (process-buffer process))
502         (goto-char (point-max))
503         (insert input)
504         (goto-char epg-read-point)
505         (beginning-of-line)
506         (while (looking-at ".*\n")      ;the input line finished
507           (save-excursion
508             (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
509                 (let* ((status (match-string 1))
510                        (string (match-string 2))
511                        (symbol (intern-soft (concat "epg-status-" status))))
512                   (if (member status epg-pending-status-list)
513                       (setq epg-pending-status-list nil))
514                   (if (and symbol
515                            (fboundp symbol))
516                       (funcall symbol process string)))))
517           (forward-line))
518         (setq epg-read-point (point)))))
519
520 (defun epg-process-sentinel (process status)
521   (if (and (buffer-live-p (process-buffer process))
522            (not (equal status "finished\n")))
523       (save-excursion
524         (set-buffer (process-buffer process))
525         ;; gpg process exited abnormally, but we have not received an
526         ;; error response from it.  Set it here.
527         (unless (epg-context-result-for epg-context 'error)
528           (if (string-match "\\`exited abnormally with code \\(.*\\)\n" status)
529               (epg-context-set-result-for
530                epg-context 'error
531                (list (cons 'exit (string-to-number (match-string 1 status)))))
532             (epg-context-set-result-for epg-context 'error
533                                     (list (cons 'signal status))))))))
534
535 (defun epg-read-output (context)
536   (with-temp-buffer
537     (if (fboundp 'set-buffer-multibyte)
538         (set-buffer-multibyte nil))
539     (if (file-exists-p (epg-context-output-file context))
540         (let ((coding-system-for-read (if (epg-context-textmode context)
541                                           'raw-text
542                                         'binary)))
543           (insert-file-contents (epg-context-output-file context))
544           (buffer-string)))))
545
546 (defun epg-wait-for-status (context status-list)
547   (with-current-buffer (process-buffer (epg-context-process context))
548     (setq epg-pending-status-list status-list)
549     (while (and (eq (process-status (epg-context-process context)) 'run)
550                 epg-pending-status-list)
551       (accept-process-output (epg-context-process context) 1))))
552
553 (defun epg-wait-for-completion (context)
554   (while (eq (process-status (epg-context-process context)) 'run)
555     ;; We can't use accept-process-output instead of sit-for here
556     ;; because it may cause an interrupt during the sentinel execution.
557     (sit-for 0.1)))
558
559 (defun epg-flush (context)
560   (if (eq (process-status (epg-context-process context)) 'run)
561       (process-send-eof (epg-context-process context))))
562
563 (defun epg-reset (context)
564   (if (and (epg-context-process context)
565            (buffer-live-p (process-buffer (epg-context-process context))))
566       (kill-buffer (process-buffer (epg-context-process context))))
567   (epg-context-set-process context nil))
568
569 (defun epg-delete-output-file (context)
570   (if (and (epg-context-output-file context)
571            (file-exists-p (epg-context-output-file context)))
572       (delete-file (epg-context-output-file context))))
573
574 (defun epg-status-USERID_HINT (process string)
575   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
576       (let* ((key-id (match-string 1 string))
577              (user-id (match-string 2 string))
578              (entry (assoc key-id epg-user-id-alist)))
579         (if entry
580             (setcdr entry user-id)
581           (setq epg-user-id-alist (cons (cons key-id user-id)
582                                         epg-user-id-alist))))))
583
584 (defun epg-status-NEED_PASSPHRASE (process string)
585   (if (string-match "\\`\\([^ ]+\\)" string)
586       (setq epg-key-id (match-string 1 string))))
587
588 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
589   (setq epg-key-id 'SYM))
590
591 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
592   (setq epg-key-id 'PIN))
593
594 (defun epg-status-GET_HIDDEN (process string)
595   (if (and epg-key-id
596            (string-match "\\`passphrase\\." string))
597       (let (inhibit-quit
598             passphrase
599             passphrase-with-new-line)
600         (unwind-protect
601             (condition-case nil
602                 (progn
603                   (setq passphrase
604                         (funcall
605                          (if (consp (epg-context-passphrase-callback
606                                      epg-context))
607                              (car (epg-context-passphrase-callback
608                                    epg-context))
609                            (epg-context-passphrase-callback epg-context))
610                          epg-context
611                          epg-key-id
612                          (if (consp (epg-context-passphrase-callback
613                                      epg-context))
614                              (cdr (epg-context-passphrase-callback
615                                    epg-context)))))
616                   (when passphrase
617                     (setq passphrase-with-new-line (concat passphrase "\n"))
618                     (fillarray passphrase 0)
619                     (setq passphrase nil)
620                     (process-send-string process passphrase-with-new-line)))
621               (quit
622                (epg-context-set-result-for
623                 epg-context 'error
624                 (cons 'quit
625                       (epg-context-result-for epg-context 'error)))
626                (delete-process process)))
627           (if passphrase
628               (fillarray passphrase 0))
629           (if passphrase-with-new-line
630               (fillarray passphrase-with-new-line 0))))))
631
632 (defun epg-status-GET_BOOL (process string)
633   (let ((entry (assoc string epg-prompt-alist))
634         inhibit-quit)
635     (condition-case nil
636       (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
637           (process-send-string process "y\n")
638         (process-send-string process "n\n"))
639       (quit
640        (epg-context-set-result-for
641         epg-context 'error
642         (cons 'quit
643               (epg-context-result-for epg-context 'error)))
644        (delete-process process)))))
645
646 (defun epg-status-GET_LINE (process string)
647   (let ((entry (assoc string epg-prompt-alist))
648         inhibit-quit)
649     (condition-case nil
650         (process-send-string
651          process
652          (concat (read-string (if entry (cdr entry) (concat string ": ")))
653                  "\n"))
654       (quit
655        (epg-context-set-result-for
656         epg-context 'error
657         (cons 'quit
658               (epg-context-result-for epg-context 'error)))
659        (delete-process process)))))
660
661 (defun epg-status-GOODSIG (process string)
662   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
663       (epg-context-set-result-for
664        epg-context
665        'verify
666        (cons (epg-make-signature
667               'good
668               (match-string 1 string)
669               (if (eq (epg-context-protocol epg-context) 'CMS)
670                   (condition-case nil
671                       (epg-dn-from-string (match-string 2 string))
672                     (error (match-string 2 string)))
673                 (match-string 2 string)))
674              (epg-context-result-for epg-context 'verify)))))
675
676 (defun epg-status-EXPSIG (process string)
677   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
678       (epg-context-set-result-for
679        epg-context
680        'verify
681        (cons (epg-make-signature
682               'expired
683               (match-string 1 string)
684               (if (eq (epg-context-protocol epg-context) 'CMS)
685                   (condition-case nil
686                       (epg-dn-from-string (match-string 2 string))
687                     (error (match-string 2 string)))
688                 (match-string 2 string)))
689              (epg-context-result-for epg-context 'verify)))))
690
691 (defun epg-status-EXPKEYSIG (process string)
692   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
693       (epg-context-set-result-for
694        epg-context
695        'verify
696        (cons (epg-make-signature
697               'expired-key
698               (match-string 1 string)
699               (if (eq (epg-context-protocol epg-context) 'CMS)
700                   (condition-case nil
701                       (epg-dn-from-string (match-string 2 string))
702                     (error (match-string 2 string)))
703                 (match-string 2 string)))
704              (epg-context-result-for epg-context 'verify)))))
705
706 (defun epg-status-REVKEYSIG (process string)
707   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
708       (epg-context-set-result-for
709        epg-context
710        'verify
711        (cons (epg-make-signature
712               'revoked-key
713               (match-string 1 string)
714               (if (eq (epg-context-protocol epg-context) 'CMS)
715                   (condition-case nil
716                       (epg-dn-from-string (match-string 2 string))
717                     (error (match-string 2 string)))
718                 (match-string 2 string)))
719              (epg-context-result-for epg-context 'verify)))))
720
721 (defun epg-status-BADSIG (process string)
722   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
723       (epg-context-set-result-for
724        epg-context
725        'verify
726        (cons (epg-make-signature
727               'bad
728               (match-string 1 string)
729               (if (eq (epg-context-protocol epg-context) 'CMS)
730                   (condition-case nil
731                       (epg-dn-from-string (match-string 2 string))
732                     (error (match-string 2 string)))
733                 (match-string 2 string)))
734              (epg-context-result-for epg-context 'verify)))))
735
736 (defun epg-status-VALIDSIG (process string)
737   (let ((signature (car (epg-context-result-for epg-context 'verify))))
738     (if (and signature
739              (eq (epg-signature-status signature) 'good)
740              (string-match "\\`\\([^ ]+\\) " string))
741         (epg-signature-set-fingerprint signature (match-string 1 string)))))
742
743 (defun epg-status-TRUST_UNDEFINED (process string)
744   (let ((signature (car (epg-context-result-for epg-context 'verify))))
745     (if (and signature
746              (eq (epg-signature-status signature) 'good))
747         (epg-signature-set-validity signature 'undefined))))
748
749 (defun epg-status-TRUST_NEVER (process string)
750   (let ((signature (car (epg-context-result-for epg-context 'verify))))
751     (if (and signature
752              (eq (epg-signature-status signature) 'good))
753         (epg-signature-set-validity signature 'never))))
754
755 (defun epg-status-TRUST_MARGINAL (process string)
756   (let ((signature (car (epg-context-result-for epg-context 'verify))))
757     (if (and signature
758              (eq (epg-signature-status signature) 'marginal))
759         (epg-signature-set-validity signature 'marginal))))
760
761 (defun epg-status-TRUST_FULLY (process string)
762   (let ((signature (car (epg-context-result-for epg-context 'verify))))
763     (if (and signature
764              (eq (epg-signature-status signature) 'good))
765         (epg-signature-set-validity signature 'full))))
766
767 (defun epg-status-TRUST_ULTIMATE (process string)
768   (let ((signature (car (epg-context-result-for epg-context 'verify))))
769     (if (and signature
770              (eq (epg-signature-status signature) 'good))
771         (epg-signature-set-validity signature 'ultimate))))
772
773 (defun epg-status-PROGRESS (process string)
774   (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
775                     string)
776       (funcall (if (consp (epg-context-progress-callback epg-context))
777                    (car (epg-context-progress-callback epg-context))
778                  (epg-context-progress-callback epg-context))
779                epg-context
780                (match-string 1 string)
781                (match-string 2 string)
782                (string-to-number (match-string 3 string))
783                (string-to-number (match-string 4 string))
784                (if (consp (epg-context-progress-callback epg-context))
785                    (cdr (epg-context-progress-callback epg-context))))))
786
787 (defun epg-status-DECRYPTION_FAILED (process string)
788   (epg-context-set-result-for
789    epg-context 'error
790    (cons 'decryption-failed
791          (epg-context-result-for epg-context 'error))))
792
793 (defun epg-status-NODATA (process string)
794   (epg-context-set-result-for
795    epg-context 'error
796    (cons (cons 'no-data (string-to-number string))
797          (epg-context-result-for epg-context 'error))))
798
799 (defun epg-status-UNEXPECTED (process string)
800   (epg-context-set-result-for
801    epg-context 'error
802    (cons (cons 'unexpected (string-to-number string))
803          (epg-context-result-for epg-context 'error))))
804
805 (defun epg-status-KEYEXPIRED (process string)
806   (epg-context-set-result-for
807    epg-context 'error
808    (cons (cons 'key-expired string)
809          (epg-context-result-for epg-context 'error))))
810
811 (defun epg-status-KEYREVOKED (process string)
812   (epg-context-set-result-for
813    epg-context 'error
814    (cons 'key-revoked
815          (epg-context-result-for epg-context 'error))))
816
817 (defun epg-status-BADARMOR (process string)
818   (epg-context-set-result-for
819    epg-context 'error
820    (cons 'bad-armor
821          (epg-context-result-for epg-context 'error))))
822
823 (defun epg-status-INV_RECP (process string)
824   (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
825       (epg-context-set-result-for
826        epg-context 'error
827        (cons (list 'invalid-recipient
828                    (string-to-number (match-string 1 string))
829                    (match-string 2 string))
830              (epg-context-result-for epg-context 'error)))))
831
832 (defun epg-status-NO_RECP (process string)
833   (epg-context-set-result-for
834    epg-context 'error
835    (cons 'no-recipients
836          (epg-context-result-for epg-context 'error))))
837
838 (defun epg-status-DELETE_PROBLEM (process string)
839   (if (string-match "\\`\\([0-9]+\\)" string)
840       (epg-context-set-result-for
841        epg-context 'error
842        (cons (cons 'delete-problem (string-to-number (match-string 1 string)))
843              (epg-context-result-for epg-context 'error)))))
844
845 (defun epg-status-SIG_CREATED (process string)
846   (if (string-match "\\`\\([DCS]\\) \\([0-9]+\\) \\([0-9]+\\) \
847 \\([0-9A-Fa-F][0-9A-Fa-F]\\) \\(.*\\) " string)
848       (epg-context-set-result-for
849        epg-context 'sign
850        (cons (list (cons 'type (string-to-char (match-string 1 string)))
851                    (cons 'pubkey-algorithm
852                          (string-to-number (match-string 2 string)))
853                    (cons 'digest-algorithm
854                          (string-to-number (match-string 3 string)))
855                    (cons 'class (string-to-number (match-string 4 string) 16))
856                    (cons 'creation-time (match-string 5 string))
857                    (cons 'fingerprint (substring string (match-end 0))))
858              (epg-context-result-for epg-context 'sign)))))
859
860 (defun epg-passphrase-callback-function (context key-id handback)
861   (read-passwd
862    (if (eq key-id 'SYM)
863        "Passphrase for symmetric encryption: "
864      (if (eq key-id 'PIN)
865          "Passphrase for PIN: "
866        (let ((entry (assoc key-id epg-user-id-alist)))
867          (if entry
868              (format "Passphrase for %s %s: " key-id (cdr entry))
869            (format "Passphrase for %s: " key-id)))))))
870
871 (defun epg-progress-callback-function (context what char current total
872                                                handback)
873   (message "%s: %d%%/%d%%" what current total))
874
875 (defun epg-configuration ()
876   "Return a list of internal configuration parameters of `epg-gpg-program'."
877   (let (config type)
878     (with-temp-buffer
879       (apply #'call-process epg-gpg-program nil (list t nil) nil
880              '("--with-colons" "--list-config"))
881       (goto-char (point-min))
882       (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
883         (setq type (intern (match-string 1))
884               config (cons (cons type
885                                  (if (memq type
886                                            '(pubkey cipher digest compress))
887                                      (mapcar #'string-to-number
888                                              (delete "" (split-string
889                                                          (match-string 2)
890                                                          ";")))
891                                    (match-string 2)))
892                            config))))
893     config))
894
895 (defun epg-list-keys-1 (context name mode)
896   (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
897                             "--with-fingerprint"
898                             "--with-fingerprint"
899                             (if mode "--list-secret-keys" "--list-keys"))
900                       (unless (eq (epg-context-protocol context) 'CMS)
901                         '("--fixed-list-mode"))
902                       (if name (list name))))
903         keys string field index)
904     (with-temp-buffer
905       (apply #'call-process
906              (if (eq (epg-context-protocol context) 'CMS)
907                  epg-gpgsm-program
908                epg-gpg-program)
909              nil (list t nil) nil args)
910       (goto-char (point-min))
911       (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
912         (setq keys (cons (make-vector 15 nil) keys)
913               string (match-string 0)
914               index 0
915               field 0)
916         (while (eq index
917                    (string-match "\\([^:]+\\)?:" string index))
918           (setq index (match-end 0))
919           (aset (car keys) field (match-string 1 string))
920           (setq field (1+ field))))
921       (nreverse keys))))
922
923 (defun epg-make-sub-key-1 (line)
924   (epg-make-sub-key
925    (if (aref line 1)
926        (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist)))
927    (delq nil
928          (mapcar (lambda (char) (cdr (assq char epg-key-capablity-alist)))
929                  (aref line 11)))
930    (member (aref line 0) '("sec" "ssb"))
931    (string-to-number (aref line 3))
932    (string-to-number (aref line 2))
933    (aref line 4)
934    (aref line 5)
935    (aref line 6)))
936
937 (defun epg-list-keys (context &optional name mode)
938   (let ((lines (epg-list-keys-1 context name mode))
939         keys cert)
940     (while lines
941       (cond
942        ((member (aref (car lines) 0) '("pub" "sec" "crt" "crs"))
943         (when (car keys)
944           (epg-key-set-sub-key-list
945            (car keys)
946            (nreverse (epg-key-sub-key-list (car keys))))
947           (epg-key-set-user-id-list
948            (car keys)
949            (nreverse (epg-key-user-id-list (car keys)))))
950         (setq cert (member (aref (car lines) 0) '("crt" "crs"))
951               keys (cons (epg-make-key
952                           (if (aref (car lines) 8)
953                               (cdr (assq (string-to-char (aref (car lines) 8))
954                                          epg-key-validity-alist))))
955                          keys))
956         (epg-key-set-sub-key-list
957          (car keys)
958          (cons (epg-make-sub-key-1 (car lines))
959                (epg-key-sub-key-list (car keys)))))
960        ((member (aref (car lines) 0) '("sub" "ssb"))
961         (epg-key-set-sub-key-list
962          (car keys)
963          (cons (epg-make-sub-key-1 (car lines))
964                (epg-key-sub-key-list (car keys)))))
965        ((equal (aref (car lines) 0) "uid")
966         (epg-key-set-user-id-list
967          (car keys)
968          (cons (epg-make-user-id
969                 (if (aref (car lines) 1)
970                     (cdr (assq (string-to-char (aref (car lines) 1))
971                                epg-key-validity-alist)))
972                 (if cert
973                     (condition-case nil
974                         (epg-dn-from-string (aref (car lines) 9))
975                       (error (aref (car lines) 9)))
976                   (aref (car lines) 9)))
977                (epg-key-user-id-list (car keys)))))
978        ((equal (aref (car lines) 0) "fpr")
979         (epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
980                                      (aref (car lines) 9))))
981       (setq lines (cdr lines)))
982     (when (car keys)
983       (epg-key-set-sub-key-list
984        (car keys)
985        (nreverse (epg-key-sub-key-list (car keys))))
986       (epg-key-set-user-id-list
987        (car keys)
988        (nreverse (epg-key-user-id-list (car keys)))))
989     (nreverse keys)))
990
991 (if (fboundp 'make-temp-file)
992     (defalias 'epg-make-temp-file 'make-temp-file)
993   ;; stolen from poe.el.
994   (defun epg-make-temp-file (prefix)
995     "Create a temporary file.
996 The returned file name (created by appending some random characters at the end
997 of PREFIX, and expanding against `temporary-file-directory' if necessary),
998 is guaranteed to point to a newly created empty file.
999 You can then use `write-region' to write new data into the file."
1000     (let (tempdir tempfile)
1001       (unwind-protect
1002           (let (file)
1003             ;; First, create a temporary directory.
1004             (while (condition-case ()
1005                        (progn
1006                          (setq tempdir (make-temp-name
1007                                         (concat
1008                                          (file-name-directory prefix)
1009                                          "DIR")))
1010                          ;; return nil or signal an error.
1011                          (make-directory tempdir))
1012                      ;; let's try again.
1013                      (file-already-exists t)))
1014             (set-file-modes tempdir 448)
1015             ;; Second, create a temporary file in the tempdir.
1016             ;; There *is* a race condition between `make-temp-name'
1017             ;; and `write-region', but we don't care it since we are
1018             ;; in a private directory now.
1019             (setq tempfile (make-temp-name (concat tempdir "/EMU")))
1020             (write-region "" nil tempfile nil 'silent)
1021             (set-file-modes tempfile 384)
1022             ;; Finally, make a hard-link from the tempfile.
1023             (while (condition-case ()
1024                        (progn
1025                          (setq file (make-temp-name prefix))
1026                          ;; return nil or signal an error.
1027                          (add-name-to-file tempfile file))
1028                      ;; let's try again.
1029                      (file-already-exists t)))
1030             file)
1031         ;; Cleanup the tempfile.
1032         (and tempfile
1033              (file-exists-p tempfile)
1034              (delete-file tempfile))
1035         ;; Cleanup the tempdir.
1036         (and tempdir
1037              (file-directory-p tempdir)
1038              (delete-directory tempdir))))))
1039
1040 ;;;###autoload
1041 (defun epg-cancel (context)
1042   (if (eq (process-status (epg-context-process context)) 'run)
1043       (delete-process (epg-context-process context))))
1044   
1045 ;;;###autoload
1046 (defun epg-start-decrypt (context cipher)
1047   "Initiate a decrypt operation on CIPHER.
1048 CIPHER is a data object.
1049
1050 If you use this function, you will need to wait for the completion of
1051 `epg-gpg-program' by using `epg-wait-for-completion' and call
1052 `epg-reset' to clear a temporaly output file.
1053 If you are unsure, use synchronous version of this function
1054 `epg-decrypt-file' or `epg-decrypt-string' instead."
1055   (unless (epg-data-file cipher)
1056     (error "Not a file"))
1057   (epg-context-set-result context nil)
1058   (epg-start context (list "--decrypt" (epg-data-file cipher)))
1059   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1060   (unless (eq (epg-context-protocol context) 'CMS)
1061     (epg-wait-for-status context '("BEGIN_DECRYPTION"))))
1062
1063 ;;;###autoload
1064 (defun epg-decrypt-file (context cipher plain)
1065   "Decrypt a file CIPHER and store the result to a file PLAIN.
1066 If PLAIN is nil, it returns the result as a string."
1067   (unwind-protect
1068       (progn
1069         (if plain
1070             (epg-context-set-output-file context plain)
1071           (epg-context-set-output-file context
1072                                        (epg-make-temp-file "epg-output")))
1073         (epg-start-decrypt context (epg-make-data-from-file cipher))
1074         (epg-wait-for-completion context)
1075         (if (epg-context-result-for context 'error)
1076             (error "Decrypt failed: %S"
1077                    (epg-context-result-for context 'error)))
1078         (unless plain
1079           (epg-read-output context)))
1080     (unless plain
1081       (epg-delete-output-file context))
1082     (epg-reset context)))
1083
1084 ;;;###autoload
1085 (defun epg-decrypt-string (context cipher)
1086   "Decrypt a string CIPHER and return the plain text."
1087   (let ((input-file (epg-make-temp-file "epg-input"))
1088         (coding-system-for-write 'binary))
1089     (unwind-protect
1090         (progn
1091           (write-region cipher nil input-file nil 'quiet)
1092           (epg-context-set-output-file context
1093                                        (epg-make-temp-file "epg-output"))
1094           (epg-start-decrypt context (epg-make-data-from-file input-file))
1095           (epg-flush context)
1096           (epg-wait-for-completion context)
1097           (if (epg-context-result-for context 'error)
1098               (error "Decrypt failed: %S"
1099                      (epg-context-result-for context 'error)))
1100           (epg-read-output context))
1101       (epg-delete-output-file context)
1102       (if (file-exists-p input-file)
1103           (delete-file input-file))
1104       (epg-reset context))))
1105
1106 ;;;###autoload
1107 (defun epg-start-verify (context signature &optional signed-text)
1108   "Initiate a verify operation on SIGNATURE.
1109 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
1110
1111 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
1112 For a normal or a clear text signature, SIGNED-TEXT should be nil.
1113
1114 If you use this function, you will need to wait for the completion of
1115 `epg-gpg-program' by using `epg-wait-for-completion' and call
1116 `epg-reset' to clear a temporaly output file.
1117 If you are unsure, use synchronous version of this function
1118 `epg-verify-file' or `epg-verify-string' instead."
1119   (epg-context-set-result context nil)
1120   (if signed-text
1121       ;; Detached signature.
1122       (if (epg-data-file signed-text)
1123           (epg-start context (list "--verify" (epg-data-file signature)
1124                                    (epg-data-file signed-text)))
1125         (epg-start context (list "--verify" (epg-data-file signature) "-"))
1126         (if (eq (process-status (epg-context-process context)) 'run)
1127             (process-send-string (epg-context-process context)
1128                                  (epg-data-string signed-text))))
1129     ;; Normal (or cleartext) signature.
1130     (if (epg-data-file signature)
1131         (epg-start context (list "--verify" (epg-data-file signature)))
1132       (epg-start context (list "--verify"))
1133       (if (eq (process-status (epg-context-process context)) 'run)
1134           (process-send-string (epg-context-process context)
1135                                (epg-data-string signature))))))
1136
1137 ;;;###autoload
1138 (defun epg-verify-file (context signature &optional signed-text plain)
1139   "Verify a file SIGNATURE.
1140 SIGNED-TEXT and PLAIN are also a file if they are specified.
1141
1142 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1143 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1144   (unwind-protect
1145       (progn
1146         (if plain
1147             (epg-context-set-output-file context plain)
1148           (epg-context-set-output-file context
1149                                        (epg-make-temp-file "epg-output")))
1150         (if signed-text
1151             (epg-start-verify context
1152                               (epg-make-data-from-file signature)
1153                               (epg-make-data-from-file signed-text))
1154           (epg-start-verify context
1155                             (epg-make-data-from-file signature)))
1156         (epg-wait-for-completion context)
1157         (unless plain
1158           (epg-read-output context)))
1159     (unless plain
1160       (epg-delete-output-file context))
1161     (epg-reset context)))
1162
1163 ;;;###autoload
1164 (defun epg-verify-string (context signature &optional signed-text)
1165   "Verify a string SIGNATURE.
1166 SIGNED-TEXT is a string if it is specified.
1167
1168 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1169 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1170   (let ((coding-system-for-write 'binary)
1171         input-file)
1172     (unwind-protect
1173         (progn
1174           (epg-context-set-output-file context
1175                                        (epg-make-temp-file "epg-output"))
1176           (if signed-text
1177               (progn
1178                 (setq input-file (epg-make-temp-file "epg-signature"))
1179                 (write-region signature nil input-file nil 'quiet)
1180                 (epg-start-verify context
1181                                   (epg-make-data-from-file input-file)
1182                                   (epg-make-data-from-string signed-text)))
1183             (epg-start-verify context (epg-make-data-from-string signature)))
1184           (epg-flush context)
1185           (epg-wait-for-completion context)
1186           (epg-read-output context))
1187       (epg-delete-output-file context)
1188       (if (and input-file
1189                (file-exists-p input-file))
1190           (delete-file input-file))
1191       (epg-reset context))))
1192
1193 ;;;###autoload
1194 (defun epg-start-sign (context plain &optional mode)
1195   "Initiate a sign operation on PLAIN.
1196 PLAIN is a data object.
1197
1198 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1199 If MODE is t or 'detached, it makes a detached signature.
1200 Otherwise, it makes a normal signature.
1201
1202 If you use this function, you will need to wait for the completion of
1203 `epg-gpg-program' by using `epg-wait-for-completion' and call
1204 `epg-reset' to clear a temporaly output file.
1205 If you are unsure, use synchronous version of this function
1206 `epg-sign-file' or `epg-sign-string' instead."
1207   (epg-context-set-result context nil)
1208   (epg-start context
1209              (append (list (if (eq mode 'clearsign)
1210                                "--clearsign"
1211                              (if (or (eq mode t) (eq mode 'detached))
1212                                  "--detach-sign"
1213                                "--sign")))
1214                      (apply #'nconc
1215                             (mapcar
1216                              (lambda (signer)
1217                                (list "-u"
1218                                      (epg-sub-key-id
1219                                       (car (epg-key-sub-key-list signer)))))
1220                              (epg-context-signers context)))
1221                      (if (epg-data-file plain)
1222                          (list (epg-data-file plain)))))
1223   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1224   (unless (eq (epg-context-protocol context) 'CMS)
1225     (epg-wait-for-status context '("BEGIN_SIGNING")))
1226   (if (and (epg-data-string plain)
1227            (eq (process-status (epg-context-process context)) 'run))
1228       (process-send-string (epg-context-process context)
1229                            (epg-data-string plain))))
1230
1231 ;;;###autoload
1232 (defun epg-sign-file (context plain signature &optional mode)
1233   "Sign a file PLAIN and store the result to a file SIGNATURE.
1234 If SIGNATURE is nil, it returns the result as a string.
1235 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1236 If MODE is t or 'detached, it makes a detached signature.
1237 Otherwise, it makes a normal signature."
1238   (unwind-protect
1239       (progn
1240         (if signature
1241             (epg-context-set-output-file context signature)
1242           (epg-context-set-output-file context
1243                                        (epg-make-temp-file "epg-output")))
1244         (epg-start-sign context (epg-make-data-from-file plain) mode)
1245         (epg-wait-for-completion context)
1246         (if (epg-context-result-for context 'sign)
1247             (if (epg-context-result-for context 'error)
1248                 (message "Sign warning: %S"
1249                          (epg-context-result-for context 'error)))
1250           (if (epg-context-result-for context 'error)
1251               (error "Sign failed: %S"
1252                      (epg-context-result-for context 'error))
1253             (error "Sign failed")))
1254         (unless signature
1255           (epg-read-output context)))
1256     (unless signature
1257       (epg-delete-output-file context))
1258     (epg-reset context)))
1259
1260 ;;;###autoload
1261 (defun epg-sign-string (context plain &optional mode)
1262   "Sign a string PLAIN and return the output as string.
1263 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1264 If MODE is t or 'detached, it makes a detached signature.
1265 Otherwise, it makes a normal signature."
1266   (unwind-protect
1267       (progn
1268         (epg-context-set-output-file context
1269                                      (epg-make-temp-file "epg-output"))
1270         (epg-start-sign context (epg-make-data-from-string plain) mode)
1271         (epg-flush context)
1272         (epg-wait-for-completion context)
1273         (if (epg-context-result-for context 'sign)
1274             (if (epg-context-result-for context 'error)
1275                 (message "Sign warning: %S"
1276                          (epg-context-result-for context 'error)))
1277           (if (epg-context-result-for context 'error)
1278               (error "Sign failed: %S"
1279                      (epg-context-result-for context 'error))
1280             (error "Sign failed")))
1281         (epg-read-output context))
1282     (epg-delete-output-file context)
1283     (epg-reset context)))
1284
1285 ;;;###autoload
1286 (defun epg-start-encrypt (context plain recipients
1287                                   &optional sign always-trust)
1288   "Initiate an encrypt operation on PLAIN.
1289 PLAIN is a data object.
1290 If RECIPIENTS is nil, it performs symmetric encryption.
1291
1292 If you use this function, you will need to wait for the completion of
1293 `epg-gpg-program' by using `epg-wait-for-completion' and call
1294 `epg-reset' to clear a temporaly output file.
1295 If you are unsure, use synchronous version of this function
1296 `epg-encrypt-file' or `epg-encrypt-string' instead."
1297   (epg-context-set-result context nil)
1298   (epg-start context
1299              (append (if always-trust '("--always-trust"))
1300                      (if recipients '("--encrypt") '("--symmetric"))
1301                      (if sign
1302                          (cons "--sign"
1303                                (apply #'nconc
1304                                       (mapcar (lambda (signer)
1305                                                 (list "-u" signer))
1306                                               (epg-context-signers context)))))
1307                      (apply #'nconc
1308                             (mapcar
1309                              (lambda (recipient)
1310                                (list "-r"
1311                                      (epg-sub-key-id
1312                                       (car (epg-key-sub-key-list recipient)))))
1313                              recipients))
1314                      (if (epg-data-file plain)
1315                          (list (epg-data-file plain)))))
1316   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1317   (unless (eq (epg-context-protocol context) 'CMS)
1318     (if sign
1319         (epg-wait-for-status context '("BEGIN_SIGNING"))
1320       (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
1321   (if (and (epg-data-string plain)
1322            (eq (process-status (epg-context-process context)) 'run))
1323       (process-send-string (epg-context-process context)
1324                            (epg-data-string plain))))
1325
1326 ;;;###autoload
1327 (defun epg-encrypt-file (context plain recipients
1328                                  cipher &optional sign always-trust)
1329   "Encrypt a file PLAIN and store the result to a file CIPHER.
1330 If CIPHER is nil, it returns the result as a string.
1331 If RECIPIENTS is nil, it performs symmetric encryption."
1332   (unwind-protect
1333       (progn
1334         (if cipher
1335             (epg-context-set-output-file context cipher)
1336           (epg-context-set-output-file context
1337                                        (epg-make-temp-file "epg-output")))
1338         (epg-start-encrypt context (epg-make-data-from-file plain)
1339                            recipients sign always-trust)
1340         (epg-wait-for-completion context)
1341         (if sign
1342             (if (epg-context-result-for context 'sign)
1343                 (if (epg-context-result-for context 'error)
1344                     (message "Sign warning: %S"
1345                              (epg-context-result-for context 'error)))
1346               (if (epg-context-result-for context 'error)
1347                   (error "Sign failed: %S"
1348                          (epg-context-result-for context 'error))
1349                 (error "Sign failed"))))
1350         (if (epg-context-result-for context 'error)
1351             (error "Encrypt failed: %S"
1352                    (epg-context-result-for context 'error)))
1353         (unless cipher
1354           (epg-read-output context)))
1355     (unless cipher
1356       (epg-delete-output-file context))
1357     (epg-reset context)))
1358
1359 ;;;###autoload
1360 (defun epg-encrypt-string (context plain recipients
1361                                    &optional sign always-trust)
1362   "Encrypt a string PLAIN.
1363 If RECIPIENTS is nil, it performs symmetric encryption."
1364   (unwind-protect
1365       (progn
1366         (epg-context-set-output-file context
1367                                      (epg-make-temp-file "epg-output"))
1368         (epg-start-encrypt context (epg-make-data-from-string plain)
1369                            recipients sign always-trust)
1370         (epg-flush context)
1371         (epg-wait-for-completion context)
1372         (if sign
1373             (if (epg-context-result-for context 'sign)
1374                 (if (epg-context-result-for context 'error)
1375                     (message "Sign warning: %S"
1376                              (epg-context-result-for context 'error)))
1377               (if (epg-context-result-for context 'error)
1378                   (error "Sign failed: %S"
1379                          (epg-context-result-for context 'error))
1380                 (error "Sign failed"))))
1381         (if (epg-context-result-for context 'error)
1382             (error "Encrypt failed: %S"
1383                    (epg-context-result-for context 'error)))
1384         (epg-read-output context))
1385     (epg-delete-output-file context)
1386     (epg-reset context)))
1387
1388 ;;;###autoload
1389 (defun epg-start-export-keys (context keys)
1390   "Initiate an export keys operation.
1391
1392 If you use this function, you will need to wait for the completion of
1393 `epg-gpg-program' by using `epg-wait-for-completion' and call
1394 `epg-reset' to clear a temporaly output file.
1395 If you are unsure, use synchronous version of this function
1396 `epg-export-keys-to-file' or `epg-export-keys-to-string' instead."
1397   (epg-context-set-result context nil)
1398   (epg-start context (cons "--export"
1399                            (mapcar
1400                             (lambda (key)
1401                               (epg-sub-key-id
1402                                (car (epg-key-sub-key-list key))))
1403                             keys))))
1404
1405 ;;;###autoload
1406 (defun epg-export-keys-to-file (context keys file)
1407   "Extract public KEYS."
1408   (unwind-protect
1409       (progn
1410         (if keys
1411             (epg-context-set-output-file context file)
1412           (epg-context-set-output-file context
1413                                        (epg-make-temp-file "epg-output")))
1414         (epg-start-export-keys context keys)
1415         (epg-wait-for-completion context)
1416         (if (epg-context-result-for context 'error)
1417             (error "Export keys failed: %S"
1418                    (epg-context-result-for context 'error)))
1419         (unless file
1420           (epg-read-output context)))
1421     (unless file
1422       (epg-delete-output-file context))
1423     (epg-reset context)))
1424
1425 ;;;###autoload
1426 (defun epg-export-keys-to-string (context keys)
1427   "Extract public KEYS and return them as a string."
1428   (epg-export-keys-to-file context keys nil))
1429
1430 ;;;###autoload
1431 (defun epg-start-import-keys (context keys)
1432   "Initiate an import keys operation.
1433 KEYS is a data object.
1434
1435 If you use this function, you will need to wait for the completion of
1436 `epg-gpg-program' by using `epg-wait-for-completion' and call
1437 `epg-reset' to clear a temporaly output file.
1438 If you are unsure, use synchronous version of this function
1439 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1440   (epg-context-set-result context nil)
1441   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1442   (epg-start context (list "--import" (epg-data-file keys)))
1443   (if (and (epg-data-string keys)
1444            (eq (process-status (epg-context-process context)) 'run))
1445       (process-send-string (epg-context-process context)
1446                            (epg-data-string keys))))
1447   
1448 (defun epg-import-keys-1 (context keys)
1449   (unwind-protect
1450       (progn
1451         (epg-start-import-keys context keys)
1452         (if (epg-data-file keys)
1453             (epg-flush context))
1454         (epg-wait-for-completion context)
1455         (if (epg-context-result-for context 'error)
1456             (error "Import keys failed: %S"
1457                    (epg-context-result-for context 'error)))
1458         (epg-read-output context))
1459     (epg-reset context)))
1460
1461 ;;;###autoload
1462 (defun epg-import-keys-from-file (context keys)
1463   "Add keys from a file KEYS."
1464   (epg-import-keys-1 context (epg-make-data-from-file keys)))
1465
1466 ;;;###autoload
1467 (defun epg-import-keys-from-string (context keys)
1468   "Add keys from a string KEYS."
1469   (epg-import-keys-1 context (epg-make-data-from-string keys)))
1470
1471 ;;;###autoload
1472 (defun epg-start-delete-keys (context keys &optional allow-secret)
1473   "Initiate an delete keys operation.
1474
1475 If you use this function, you will need to wait for the completion of
1476 `epg-gpg-program' by using `epg-wait-for-completion' and call
1477 `epg-reset' to clear a temporaly output file.
1478 If you are unsure, use synchronous version of this function
1479 `epg-delete-keys' instead."
1480   (epg-context-set-result context nil)
1481   (epg-start context (cons (if allow-secret
1482                                "--delete-secret-key"
1483                              "--delete-key")
1484                            (mapcar
1485                             (lambda (key)
1486                               (epg-sub-key-id
1487                                (car (epg-key-sub-key-list key))))
1488                             keys))))
1489
1490 ;;;###autoload
1491 (defun epg-delete-keys (context keys &optional allow-secret)
1492   "Delete KEYS from the key ring."
1493   (unwind-protect
1494       (progn
1495         (epg-start-delete-keys context keys allow-secret)
1496         (epg-wait-for-completion context)
1497         (if (epg-context-result-for context 'error)
1498             (error "Delete keys failed: %S"
1499                    (epg-context-result-for context 'error))))
1500     (epg-reset context)))
1501
1502 ;;;###autoload
1503 (defun epg-start-sign-keys (context keys &optional local)
1504   "Initiate an sign keys operation.
1505
1506 If you use this function, you will need to wait for the completion of
1507 `epg-gpg-program' by using `epg-wait-for-completion' and call
1508 `epg-reset' to clear a temporaly output file.
1509 If you are unsure, use synchronous version of this function
1510 `epg-sign-keys' instead."
1511   (epg-context-set-result context nil)
1512   (epg-start context (cons (if local
1513                                "--lsign-key"
1514                              "--sign-key")
1515                            (mapcar
1516                             (lambda (key)
1517                               (epg-sub-key-id
1518                                (car (epg-key-sub-key-list key))))
1519                             keys))))
1520
1521 ;;;###autoload
1522 (defun epg-sign-keys (context keys &optional local)
1523   "Sign KEYS from the key ring."
1524   (unwind-protect
1525       (progn
1526         (epg-start-sign-keys context keys local)
1527         (epg-wait-for-completion context)
1528         (if (epg-context-result-for context 'error)
1529             (error "Sign keys failed: %S"
1530                    (epg-context-result-for context 'error))))
1531     (epg-reset context)))
1532
1533 (defun epg-decode-hexstring (string)
1534   (let ((index 0))
1535     (while (eq index (string-match "[0-9A-Fa-f][0-9A-Fa-f]" string index))
1536       (setq string (replace-match "\\x\\&" t nil string)
1537             index (+ index 4)))
1538     (car (read-from-string (concat "\"" string "\"")))))
1539
1540 (defun epg-decode-quotedstring (string)
1541   (let ((index 0))
1542     (while (string-match "\\\\\\(\\([,=+<>#;\\\"]\\)\\|\
1543 \\([0-9A-Fa-f][0-9A-Fa-f]\\)\\|\\(.\\)\\)"
1544                          string index)
1545       (if (match-beginning 2)
1546           (setq string (replace-match "\\2" t nil string)
1547                 index (1+ index))
1548         (if (match-beginning 3)
1549             (setq string (replace-match "\\x\\3" t nil string)
1550                   index (+ index 4))
1551           (setq string (replace-match "\\\\\\\\\\4" t nil string)
1552                 index (+ index 3)))))
1553     (car (read-from-string (concat "\"" string "\"")))))
1554
1555 (defun epg-dn-from-string (string)
1556   "Parse STRING as LADPv3 Distinguished Names (RFC2253).
1557 The return value is an alist mapping from types to values."
1558   (let ((index 0)
1559         (length (length string))
1560         alist type value group)
1561     (while (< index length)
1562       (if (eq index (string-match "[ \t\n\r]*" string index))
1563           (setq index (match-end 0)))
1564       (if (eq index (string-match
1565                      "\\([0-9]+\\(\\.[0-9]+\\)*\\)\[ \t\n\r]*=[ \t\n\r]*"
1566                      string index))
1567           (setq type (match-string 1 string)
1568                 index (match-end 0))
1569         (if (eq index (string-match "\\([0-9A-Za-z]+\\)[ \t\n\r]*=[ \t\n\r]*"
1570                                     string index))
1571             (setq type (match-string 1 string)
1572                   index (match-end 0))))
1573       (unless type
1574         (error "Invalid type"))
1575       (if (eq index (string-match
1576                      "\\([^,=+<>#;\\\"]\\|\\\\.\\)+"
1577                      string index))
1578           (setq index (match-end 0)
1579                 value (epg-decode-quotedstring (match-string 0 string)))
1580         (if (eq index (string-match "#\\([0-9A-Fa-f]+\\)" string index))
1581             (setq index (match-end 0)
1582                   value (epg-decode-hexstring (match-string 1 string)))
1583           (if (eq index (string-match "\"\\([^\\\"]\\|\\\\.\\)*\""
1584                                       string index))
1585               (setq index (match-end 0)
1586                     value (epg-decode-quotedstring (match-string 0 string))))))
1587       (if group
1588           (if (stringp (car (car alist)))
1589               (setcar alist (list (cons type value) (car alist)))
1590             (setcar alist (cons (cons type value) (car alist))))
1591         (if (consp (car (car alist)))
1592             (setcar alist (nreverse (car alist))))
1593         (setq alist (cons (cons type value) alist)
1594               type nil
1595               value nil))
1596       (if (eq index (string-match "[ \t\n\r]*\\([,;+]\\)" string index))
1597           (setq index (match-end 0)
1598                 group (eq (aref string (match-beginning 1)) ?+))))
1599     (nreverse alist)))
1600
1601 (defun epg-decode-dn (alist)
1602   "Convert ALIST returned by `epg-dn-from-string' to a human readable form.
1603 Type names are resolved using `epg-dn-type-alist'."
1604   (mapconcat
1605    (lambda (rdn)
1606      (if (stringp (car rdn))
1607          (let ((entry (assoc (car rdn) epg-dn-type-alist)))
1608            (if entry
1609                (format "%s=%s" (cdr entry) (cdr rdn))
1610              (format "%s=%s" (car rdn) (cdr rdn))))
1611        (concat "(" (epg-decode-dn rdn) ")")))
1612    alist
1613    ", "))
1614
1615 (provide 'epg)
1616
1617 ;;; epg.el ends here