2001-07-30 15:00:00 ShengHuo ZHU <zsh@cs.rochester.edu>
[gnus] / lisp / mml2015.el
1 ;;; mml2015.el --- MIME Security with Pretty Good Privacy (PGP)
2 ;; Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3
4 ;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
5 ;; Keywords: PGP MIME MML
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published
11 ;; by the Free Software Foundation; either version 2, or (at your
12 ;; option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful, but
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;; General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
21 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;; Commentary:
25
26 ;;; Code:
27
28 (eval-when-compile (require 'cl))
29 (require 'mm-decode)
30
31 (defvar mml2015-use (or
32                      (progn
33                        (ignore-errors
34                          (require 'gpg))
35                        (and (fboundp 'gpg-sign-detached)
36                             'gpg))
37                      (progn (ignore-errors
38                               (load "mc-toplev"))
39                             (and (fboundp 'mc-encrypt-generic)
40                                  (fboundp 'mc-sign-generic)
41                                  (fboundp 'mc-cleanup-recipient-headers)
42                                  'mailcrypt)))
43   "The package used for PGP/MIME.")
44
45 ;; Something is not RFC2015.
46 (defvar mml2015-function-alist
47   '((mailcrypt mml2015-mailcrypt-sign
48                mml2015-mailcrypt-encrypt
49                mml2015-mailcrypt-verify
50                mml2015-mailcrypt-decrypt
51                mml2015-mailcrypt-clear-verify
52                mml2015-mailcrypt-clear-decrypt)
53     (gpg mml2015-gpg-sign
54          mml2015-gpg-encrypt
55          mml2015-gpg-verify
56          mml2015-gpg-decrypt
57          mml2015-gpg-clear-verify
58          mml2015-gpg-clear-decrypt))
59   "Alist of PGP/MIME functions.")
60
61 (defvar mml2015-result-buffer nil)
62
63 (defvar mml2015-trust-boundaries-alist
64   '((trust-undefined . nil)
65     (trust-none      . nil)
66     (trust-marginal  . t)
67     (trust-fully     . t)
68     (trust-ultimate  . t))
69   "Trust boundaries for a signer's GnuPG key.
70 This alist contains pairs of the form (trust-symbol . boolean), with
71 symbols that are contained in `gpg-unabbrev-trust-alist'. The boolean
72 specifies whether the given trust value is good enough to be trusted
73 by you.")
74
75 ;;; mailcrypt wrapper
76
77 (eval-and-compile
78   (autoload 'mailcrypt-decrypt "mailcrypt")
79   (autoload 'mailcrypt-verify "mailcrypt")
80   (autoload 'mc-pgp-always-sign "mailcrypt")
81   (autoload 'mc-encrypt-generic "mc-toplev")
82   (autoload 'mc-cleanup-recipient-headers "mc-toplev")
83   (autoload 'mc-sign-generic "mc-toplev"))
84
85 (eval-when-compile
86   (defvar mc-default-scheme)
87   (defvar mc-schemes))
88
89 (defvar mml2015-decrypt-function 'mailcrypt-decrypt)
90 (defvar mml2015-verify-function 'mailcrypt-verify)
91
92 (defun mml2015-format-error (err)
93   (if (stringp (cadr err))
94       (cadr err)
95     (format "%S" (cdr err))))
96
97 (defun mml2015-mailcrypt-decrypt (handle ctl)
98   (catch 'error
99     (let (child handles result)
100       (unless (setq child (mm-find-part-by-type
101                            (cdr handle)
102                            "application/octet-stream" nil t))
103         (mm-set-handle-multipart-parameter
104          mm-security-handle 'gnus-info "Corrupted")
105         (throw 'error handle))
106       (with-temp-buffer
107         (mm-insert-part child)
108         (setq result
109               (condition-case err
110                   (funcall mml2015-decrypt-function)
111                 (error
112                  (mm-set-handle-multipart-parameter
113                   mm-security-handle 'gnus-details (mml2015-format-error err))
114                  nil)
115                 (quit
116                  (mm-set-handle-multipart-parameter
117                   mm-security-handle 'gnus-details "Quit.")
118                  nil)))
119         (unless (car result)
120           (mm-set-handle-multipart-parameter
121            mm-security-handle 'gnus-info "Failed")
122           (throw 'error handle))
123         (setq handles (mm-dissect-buffer t)))
124       (mm-destroy-parts handle)
125       (mm-set-handle-multipart-parameter
126        mm-security-handle 'gnus-info "OK")
127       (if (listp (car handles))
128           handles
129         (list handles)))))
130
131 (defun mml2015-mailcrypt-clear-decrypt ()
132   (let (result)
133     (setq result
134           (condition-case err
135               (funcall mml2015-decrypt-function)
136             (error
137              (mm-set-handle-multipart-parameter
138               mm-security-handle 'gnus-details (mml2015-format-error err))
139              nil)
140             (quit
141              (mm-set-handle-multipart-parameter
142               mm-security-handle 'gnus-details "Quit.")
143              nil)))
144     (if (car result)
145         (mm-set-handle-multipart-parameter
146          mm-security-handle 'gnus-info "OK")
147       (mm-set-handle-multipart-parameter
148        mm-security-handle 'gnus-info "Failed"))))
149
150 (defun mml2015-fix-micalg (alg)
151   (and alg
152        (upcase (if (string-match "^pgp-" alg)
153                    (substring alg (match-end 0))
154                  alg))))
155
156 (defun mml2015-mailcrypt-verify (handle ctl)
157   (catch 'error
158     (let (part)
159       (unless (setq part (mm-find-raw-part-by-type
160                           ctl (or (mm-handle-multipart-ctl-parameter
161                                    ctl 'protocol)
162                                   "application/pgp-signature")
163                           t))
164         (mm-set-handle-multipart-parameter
165          mm-security-handle 'gnus-info "Corrupted")
166         (throw 'error handle))
167       (with-temp-buffer
168         (insert "-----BEGIN PGP SIGNED MESSAGE-----\n")
169         (insert (format "Hash: %s\n\n"
170                         (or (mml2015-fix-micalg
171                              (mm-handle-multipart-ctl-parameter
172                               ctl 'micalg))
173                             "SHA1")))
174         (save-restriction
175           (narrow-to-region (point) (point))
176           (insert part "\n")
177           (goto-char (point-min))
178           (while (not (eobp))
179             (if (looking-at "^-")
180                 (insert "- "))
181             (forward-line)))
182         (unless (setq part (mm-find-part-by-type
183                             (cdr handle) "application/pgp-signature" nil t))
184           (mm-set-handle-multipart-parameter
185            mm-security-handle 'gnus-info "Corrupted")
186           (throw 'error handle))
187         (save-restriction
188           (narrow-to-region (point) (point))
189           (mm-insert-part part)
190           (goto-char (point-min))
191           (if (re-search-forward "^-----BEGIN PGP [^-]+-----\r?$" nil t)
192               (replace-match "-----BEGIN PGP SIGNATURE-----" t t))
193           (if (re-search-forward "^-----END PGP [^-]+-----\r?$" nil t)
194               (replace-match "-----END PGP SIGNATURE-----" t t)))
195         (let ((mc-gpg-debug-buffer (get-buffer-create " *gnus gpg debug*")))
196           (unless (condition-case err
197                       (prog1
198                           (funcall mml2015-verify-function)
199                         (if (get-buffer " *mailcrypt stderr temp")
200                             (mm-set-handle-multipart-parameter
201                              mm-security-handle 'gnus-details
202                              (with-current-buffer " *mailcrypt stderr temp"
203                                (buffer-string))))
204                         (if (get-buffer " *mailcrypt stdout temp")
205                             (kill-buffer " *mailcrypt stdout temp"))
206                         (if (get-buffer " *mailcrypt stderr temp")
207                             (kill-buffer " *mailcrypt stderr temp"))
208                         (if (get-buffer " *mailcrypt status temp")
209                             (kill-buffer " *mailcrypt status temp"))
210                         (if (get-buffer mc-gpg-debug-buffer)
211                             (kill-buffer mc-gpg-debug-buffer)))
212                     (error
213                      (mm-set-handle-multipart-parameter
214                       mm-security-handle 'gnus-details (mml2015-format-error err))
215                      nil)
216                     (quit
217                      (mm-set-handle-multipart-parameter
218                       mm-security-handle 'gnus-details "Quit.")
219                      nil))
220             (mm-set-handle-multipart-parameter
221              mm-security-handle 'gnus-info "Failed")
222             (throw 'error handle))))
223       (mm-set-handle-multipart-parameter
224        mm-security-handle 'gnus-info "OK")
225       handle)))
226
227 (defun mml2015-mailcrypt-clear-verify ()
228   (let ((mc-gpg-debug-buffer (get-buffer-create " *gnus gpg debug*")))
229     (if (condition-case err
230             (prog1
231                 (funcall mml2015-verify-function)
232               (if (get-buffer " *mailcrypt stderr temp")
233                   (mm-set-handle-multipart-parameter
234                    mm-security-handle 'gnus-details
235                    (with-current-buffer " *mailcrypt stderr temp"
236                      (buffer-string))))
237               (if (get-buffer " *mailcrypt stdout temp")
238                   (kill-buffer " *mailcrypt stdout temp"))
239               (if (get-buffer " *mailcrypt stderr temp")
240                   (kill-buffer " *mailcrypt stderr temp"))
241               (if (get-buffer " *mailcrypt status temp")
242                   (kill-buffer " *mailcrypt status temp"))
243               (if (get-buffer mc-gpg-debug-buffer)
244                   (kill-buffer mc-gpg-debug-buffer)))
245           (error
246            (mm-set-handle-multipart-parameter
247             mm-security-handle 'gnus-details (mml2015-format-error err))
248            nil)
249           (quit
250            (mm-set-handle-multipart-parameter
251             mm-security-handle 'gnus-details "Quit.")
252            nil))
253         (mm-set-handle-multipart-parameter
254          mm-security-handle 'gnus-info "OK")
255       (mm-set-handle-multipart-parameter
256        mm-security-handle 'gnus-info "Failed"))))
257
258 (defun mml2015-mailcrypt-sign (cont)
259   (mc-sign-generic (message-options-get 'message-sender)
260                    nil nil nil nil)
261   (let ((boundary
262          (funcall mml-boundary-function (incf mml-multipart-number)))
263         hash point)
264     (goto-char (point-min))
265     (unless (re-search-forward "^-----BEGIN PGP SIGNED MESSAGE-----\r?$" nil t)
266       (error "Cannot find signed begin line"))
267     (goto-char (match-beginning 0))
268     (forward-line 1)
269     (unless (looking-at "Hash:[ \t]*\\([a-zA-Z0-9]+\\)")
270       (error "Cannot not find PGP hash"))
271     (setq hash (match-string 1))
272     (unless (re-search-forward "^$" nil t)
273       (error "Cannot not find PGP message"))
274     (forward-line 1)
275     (delete-region (point-min) (point))
276     (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
277                     boundary))
278     (insert (format "\tmicalg=pgp-%s; protocol=\"application/pgp-signature\"\n"
279                     (downcase hash)))
280     (insert (format "\n--%s\n" boundary))
281     (setq point (point))
282     (goto-char (point-max))
283     (unless (re-search-backward "^-----END PGP SIGNATURE-----\r?$" nil t)
284       (error "Cannot find signature part"))
285     (replace-match "-----END PGP MESSAGE-----" t t)
286     (goto-char (match-beginning 0))
287     (unless (re-search-backward "^-----BEGIN PGP SIGNATURE-----\r?$"
288                                 nil t)
289       (error "Cannot find signature part"))
290     (replace-match "-----BEGIN PGP MESSAGE-----" t t)
291     (goto-char (match-beginning 0))
292     (save-restriction
293       (narrow-to-region point (point))
294       (goto-char point)
295       (while (re-search-forward "^- -" nil t)
296         (replace-match "-" t t))
297       (goto-char (point-max)))
298     (insert (format "--%s\n" boundary))
299     (insert "Content-Type: application/pgp-signature\n\n")
300     (goto-char (point-max))
301     (insert (format "--%s--\n" boundary))
302     (goto-char (point-max))))
303
304 (defun mml2015-mailcrypt-encrypt (cont)
305   (let ((mc-pgp-always-sign
306          (or mc-pgp-always-sign
307              (eq t (or (message-options-get 'message-sign-encrypt)
308                        (message-options-set
309                         'message-sign-encrypt
310                         (or (y-or-n-p "Sign the message? ")
311                             'not))))
312              'never)))
313     (mm-with-unibyte-current-buffer-mule4
314       (mc-encrypt-generic
315        (or (message-options-get 'message-recipients)
316            (message-options-set 'message-recipients
317                               (mc-cleanup-recipient-headers
318                                (read-string "Recipients: "))))
319        nil nil nil
320        (message-options-get 'message-sender))))
321   (goto-char (point-min))
322   (unless (looking-at "-----BEGIN PGP MESSAGE-----")
323     (error "Fail to encrypt the message"))
324   (let ((boundary
325          (funcall mml-boundary-function (incf mml-multipart-number))))
326     (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
327                     boundary))
328     (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
329     (insert (format "--%s\n" boundary))
330     (insert "Content-Type: application/pgp-encrypted\n\n")
331     (insert "Version: 1\n\n")
332     (insert (format "--%s\n" boundary))
333     (insert "Content-Type: application/octet-stream\n\n")
334     (goto-char (point-max))
335     (insert (format "--%s--\n" boundary))
336     (goto-char (point-max))))
337
338 ;;; gpg wrapper
339
340 (eval-and-compile
341   (autoload 'gpg-decrypt "gpg")
342   (autoload 'gpg-verify "gpg")
343   (autoload 'gpg-verify-cleartext "gpg")
344   (autoload 'gpg-sign-detached "gpg")
345   (autoload 'gpg-sign-encrypt "gpg")
346   (autoload 'gpg-passphrase-read "gpg"))
347
348 (defun mml2015-gpg-passphrase ()
349   (or (message-options-get 'gpg-passphrase)
350       (message-options-set 'gpg-passphrase (gpg-passphrase-read))))
351
352 (defun mml2015-gpg-decrypt-1 ()
353   (let ((cipher (current-buffer)) plain result)
354     (if (with-temp-buffer
355           (prog1
356               (gpg-decrypt cipher (setq plain (current-buffer))
357                            mml2015-result-buffer nil)
358             (mm-set-handle-multipart-parameter
359              mm-security-handle 'gnus-details
360              (with-current-buffer mml2015-result-buffer
361                (buffer-string)))
362             (set-buffer cipher)
363             (erase-buffer)
364             (insert-buffer plain)))
365         '(t)
366       ;; Some wrong with the return value, check plain text buffer.
367       (if (> (point-max) (point-min))
368           '(t)
369         nil))))
370
371 (defun mml2015-gpg-decrypt (handle ctl)
372   (let ((mml2015-decrypt-function 'mml2015-gpg-decrypt-1))
373     (mml2015-mailcrypt-decrypt handle ctl)))
374
375 (defun mml2015-gpg-clear-decrypt ()
376   (let (result)
377     (setq result (mml2015-gpg-decrypt-1))
378     (if (car result)
379         (mm-set-handle-multipart-parameter
380          mm-security-handle 'gnus-info "OK")
381       (mm-set-handle-multipart-parameter
382        mm-security-handle 'gnus-info "Failed"))))
383
384 (defun mml2015-gpg-pretty-print-fpr (fingerprint)
385   (let* ((result "")
386          (fpr-length (string-width fingerprint))
387          (n-slice 0)
388          slice)
389     (setq fingerprint (string-to-list fingerprint))
390     (while fingerprint
391       (setq fpr-length (- fpr-length 4))
392       (setq slice (butlast fingerprint fpr-length))
393       (setq fingerprint (nthcdr 4 fingerprint))
394       (setq n-slice (1+ n-slice))
395       (setq result
396             (concat
397              result
398              (case n-slice
399                (1  slice)
400                (otherwise (concat " " slice))))))
401     result))
402           
403 (defun mml2015-gpg-extract-signature-details ()
404   (goto-char (point-min))
405   (if (boundp 'gpg-unabbrev-trust-alist)
406       (let* ((signer (and (re-search-forward
407                            "^\\[GNUPG:\\] GOODSIG [0-9A-Za-z]* \\(.*\\)$"
408                            nil t)
409                           (match-string 1)))
410          (fprint (and (re-search-forward
411                        "^\\[GNUPG:\\] VALIDSIG \\([0-9a-zA-Z]*\\) "
412                        nil t)
413                       (match-string 1)))
414          (trust  (and (re-search-forward "^\\[GNUPG:\\] \\(TRUST_.*\\)$" nil t)
415                       (match-string 1)))
416          (trust-good-enough-p
417           (cdr (assoc (cdr (assoc trust gpg-unabbrev-trust-alist))
418                       mml2015-trust-boundaries-alist))))
419         (if (and signer trust fprint)
420             (concat signer
421                     (unless trust-good-enough-p
422                       (concat "\nUntrusted, Fingerprint: "
423                               (mml2015-gpg-pretty-print-fpr fprint))))
424           (error "From unknown user")))
425     (if (re-search-forward "^gpg: Good signature from \"\\(.*\\)\"$" nil t)
426         (match-string 1)
427       "From unknown user")))
428
429 (defun mml2015-gpg-verify (handle ctl)
430   (catch 'error
431     (let (part message signature info-is-set-p)
432       (unless (setq part (mm-find-raw-part-by-type
433                           ctl (or (mm-handle-multipart-ctl-parameter
434                                    ctl 'protocol)
435                                   "application/pgp-signature")
436                           t))
437         (mm-set-handle-multipart-parameter
438          mm-security-handle 'gnus-info "Corrupted")
439         (throw 'error handle))
440       (with-temp-buffer
441         (setq message (current-buffer))
442         (insert part)
443         (with-temp-buffer
444           (setq signature (current-buffer))
445           (unless (setq part (mm-find-part-by-type
446                               (cdr handle) "application/pgp-signature" nil t))
447             (mm-set-handle-multipart-parameter
448              mm-security-handle 'gnus-info "Corrupted")
449             (throw 'error handle))
450           (mm-insert-part part)
451           (unless (condition-case err
452                       (prog1
453                           (gpg-verify message signature mml2015-result-buffer)
454                         (mm-set-handle-multipart-parameter
455                          mm-security-handle 'gnus-details
456                          (with-current-buffer mml2015-result-buffer
457                            (buffer-string))))
458                     (error
459                      (mm-set-handle-multipart-parameter
460                       mm-security-handle 'gnus-details (mml2015-format-error err))
461                      (mm-set-handle-multipart-parameter
462                       mm-security-handle 'gnus-info "Error.")
463                      (setq info-is-set-p t)
464                      nil)
465                     (quit
466                      (mm-set-handle-multipart-parameter
467                       mm-security-handle 'gnus-details "Quit.")
468                      (mm-set-handle-multipart-parameter
469                       mm-security-handle 'gnus-info "Quit.")
470                      (setq info-is-set-p t)
471                      nil))
472             (unless info-is-set-p
473               (mm-set-handle-multipart-parameter
474                mm-security-handle 'gnus-info "Failed"))
475             (throw 'error handle)))
476         (mm-set-handle-multipart-parameter
477          mm-security-handle 'gnus-info
478          (with-current-buffer mml2015-result-buffer
479            (mml2015-gpg-extract-signature-details))))
480       handle)))
481
482 (defun mml2015-gpg-clear-verify ()
483   (if (condition-case err
484           (prog1
485               (gpg-verify-cleartext (current-buffer) mml2015-result-buffer)
486             (mm-set-handle-multipart-parameter
487              mm-security-handle 'gnus-details
488              (with-current-buffer mml2015-result-buffer
489                (buffer-string))))
490         (error
491          (mm-set-handle-multipart-parameter
492           mm-security-handle 'gnus-details (mml2015-format-error err))
493          nil)
494         (quit
495          (mm-set-handle-multipart-parameter
496           mm-security-handle 'gnus-details "Quit.")
497          nil))
498       (mm-set-handle-multipart-parameter
499        mm-security-handle 'gnus-info
500        (with-current-buffer mml2015-result-buffer
501          (mml2015-gpg-extract-signature-details)))
502     (mm-set-handle-multipart-parameter
503      mm-security-handle 'gnus-info "Failed")))
504
505 (defun mml2015-gpg-sign (cont)
506   (let ((boundary
507          (funcall mml-boundary-function (incf mml-multipart-number)))
508         (text (current-buffer)) signature)
509     (goto-char (point-max))
510     (unless (bolp)
511       (insert "\n"))
512     (with-temp-buffer
513       (unless (gpg-sign-detached text (setq signature (current-buffer))
514                                  mml2015-result-buffer
515                                  nil
516                                  (message-options-get 'message-sender)
517                                  t t) ; armor & textmode
518         (unless (> (point-max) (point-min))
519           (pop-to-buffer mml2015-result-buffer)
520           (error "Sign error")))
521       (goto-char (point-min))
522       (while (re-search-forward "\r+$" nil t)
523         (replace-match "" t t))
524       (set-buffer text)
525       (goto-char (point-min))
526       (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
527                       boundary))
528       ;;; FIXME: what is the micalg?
529       (insert "\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"\n")
530       (insert (format "\n--%s\n" boundary))
531       (goto-char (point-max))
532       (insert (format "\n--%s\n" boundary))
533       (insert "Content-Type: application/pgp-signature\n\n")
534       (insert-buffer signature)
535       (goto-char (point-max))
536       (insert (format "--%s--\n" boundary))
537       (goto-char (point-max)))))
538
539 (defun mml2015-gpg-encrypt (cont)
540   (let ((boundary
541          (funcall mml-boundary-function (incf mml-multipart-number)))
542         (text (current-buffer))
543         cipher)
544     (mm-with-unibyte-current-buffer-mule4
545       (with-temp-buffer
546         (unless (gpg-sign-encrypt
547                  text (setq cipher (current-buffer))
548                  mml2015-result-buffer
549                  (split-string
550                   (or
551                    (message-options-get 'message-recipients)
552                    (message-options-set 'message-recipients
553                                         (read-string "Recipients: ")))
554                   "[ \f\t\n\r\v,]+")
555                  nil
556                  (message-options-get 'message-sender)
557                  t t) ; armor & textmode
558           (unless (> (point-max) (point-min))
559             (pop-to-buffer mml2015-result-buffer)
560             (error "Encrypt error")))
561         (goto-char (point-min))
562         (while (re-search-forward "\r+$" nil t)
563           (replace-match "" t t))
564         (set-buffer text)
565         (delete-region (point-min) (point-max))
566         (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
567                         boundary))
568         (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
569         (insert (format "--%s\n" boundary))
570         (insert "Content-Type: application/pgp-encrypted\n\n")
571         (insert "Version: 1\n\n")
572         (insert (format "--%s\n" boundary))
573         (insert "Content-Type: application/octet-stream\n\n")
574         (insert-buffer cipher)
575         (goto-char (point-max))
576         (insert (format "--%s--\n" boundary))
577         (goto-char (point-max))))))
578
579 ;;; General wrapper
580
581 (defun mml2015-clean-buffer ()
582   (if (gnus-buffer-live-p mml2015-result-buffer)
583       (with-current-buffer mml2015-result-buffer
584         (erase-buffer)
585         t)
586     (setq mml2015-result-buffer
587           (gnus-get-buffer-create "*MML2015 Result*"))
588     nil))
589
590 (defsubst mml2015-clear-decrypt-function ()
591   (nth 6 (assq mml2015-use mml2015-function-alist)))
592
593 (defsubst mml2015-clear-verify-function ()
594   (nth 5 (assq mml2015-use mml2015-function-alist)))
595
596 ;;;###autoload
597 (defun mml2015-decrypt (handle ctl)
598   (mml2015-clean-buffer)
599   (let ((func (nth 4 (assq mml2015-use mml2015-function-alist))))
600     (if func
601         (funcall func handle ctl)
602       handle)))
603
604 ;;;###autoload
605 (defun mml2015-decrypt-test (handle ctl)
606   mml2015-use)
607
608 ;;;###autoload
609 (defun mml2015-verify (handle ctl)
610   (mml2015-clean-buffer)
611   (let ((func (nth 3 (assq mml2015-use mml2015-function-alist))))
612     (if func
613         (funcall func handle ctl)
614       handle)))
615
616 ;;;###autoload
617 (defun mml2015-verify-test (handle ctl)
618   mml2015-use)
619
620 ;;;###autoload
621 (defun mml2015-encrypt (cont)
622   (mml2015-clean-buffer)
623   (let ((func (nth 2 (assq mml2015-use mml2015-function-alist))))
624     (if func
625         (funcall func cont)
626       (error "Cannot find encrypt function"))))
627
628 ;;;###autoload
629 (defun mml2015-sign (cont)
630   (mml2015-clean-buffer)
631   (let ((func (nth 1 (assq mml2015-use mml2015-function-alist))))
632     (if func
633         (funcall func cont)
634       (error "Cannot find sign function"))))
635
636 ;;;###autoload
637 (defun mml2015-self-encrypt ()
638   (mml2015-encrypt nil))
639
640 (provide 'mml2015)
641
642 ;;; mml2015.el ends here