Build Fix -- compatibility issue with newer autoconf
[sxemacs] / src / openssl.c
1 /*
2   openssl.c -- Emacs Lisp binding to OpenSSL ciphers and digests
3   Copyright (C) 2005, 2006 Sebastian Freundt
4
5   Author:  Sebastian Freundt <hroptatyr@sxemacs.org>
6
7 This file is part of SXEmacs
8
9 SXEmacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 SXEmacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
21
22
23 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
24  * All rights reserved.
25  *
26  * This package is an SSL implementation written
27  * by Eric Young (eay@cryptsoft.com).
28  * The implementation was written so as to conform with Netscapes SSL.
29  *
30  * This library is free for commercial and non-commercial use as long as
31  * the following conditions are aheared to.  The following conditions
32  * apply to all code found in this distribution, be it the RC4, RSA,
33  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
34  * included with this distribution is covered by the same copyright terms
35  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
36  *
37  * Copyright remains Eric Young's, and as such any Copyright notices in
38  * the code are not to be removed.
39  * If this package is used in a product, Eric Young should be given attribution
40  * as the author of the parts of the library used.
41  * This can be in the form of a textual message at program startup or
42  * in documentation (online or textual) provided with the package.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *    "This product includes cryptographic software written by
55  *     Eric Young (eay@cryptsoft.com)"
56  *    The word 'cryptographic' can be left out if the rouines from the library
57  *    being used are not cryptographic related :-).
58  * 4. If you include any Windows specific code (or a derivative thereof) from
59  *    the apps directory (application code) you must include an acknowledgement:
60  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
61  *
62  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
63  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
66  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72  * SUCH DAMAGE.
73  *
74  * The licence and distribution terms for any publically available version or
75  * derivative of this code cannot be changed.  i.e. this code cannot simply be
76  * copied and put under another distribution licence
77  * [including the GNU Public Licence.]
78  */
79
80 /* General overview:
81  * openssl provides an assortment of cryptographic routines and interfaces
82  * to access them.
83  * This API hook attempts to bring them all as pure as possible into SXE
84  * elisp. This in turn means that the feature 'openssl is NOT a higher
85  * level crypto library for elisp. Personally I consider implementing the
86  * latter one, too, based on the API provided by this feature.
87  *
88  *
89  * * Detailed overview:
90  *  Currently provided routines:
91  *  - all of openssl message digest algorithms (md)
92  *  - all of openssl message authentication algorithms (hmac)
93  *  - all of openssl (pseudo) random number generators (rand)
94  *  - all of openssl symmetric block and stream cipher algorithms (cipher)
95  *  - basic functionality of openssl asymmetric crypto-systems (pkey)
96  *  - all of openssl envelope handling (hybrid)
97  *  - all of EVP interface functionality minus `engine' support
98  *  - all of PEM interface functionality
99  *  - a simple SSL client
100  *
101  *  In addition, we are trying hard to provide not only an exact elisp
102  *  copy of openssl, but also a _comprehensive_ one
103  *
104  *
105  * * src/openssl.c: functions overview:
106  *
107  * - General
108  *  ossl-version - version info
109  *  ossl-available-digests - list of available message digests
110  *  ossl-available-ciphers - list of available ciphers
111  *  ossl-digest-bits - effective length of the digest in bits
112  *  ossl-cipher-bits - effective length of the key in bits
113  *
114  * - RAND
115  *  ossl-rand-bytes - generation of (pseudo) randomness
116  *
117  * - MD
118  *  ossl-digest - gateway to digest functions
119  *
120  * - HMAC
121  *  ossl-hmac - gateway to message authentication codes
122  *
123  * - CIPHER
124  *  ossl-bytes-to-key - key generation for symmetric ciphers
125  *  ossl-encrypt - gateway to symmetric cipher encryption
126  *  ossl-decrypt - gateway to symmetric cipher decryption
127  *
128  * - PKEY
129  * + General
130  *  ossl-pkey-p - discriminator of public keys
131  *  ossl-pkey-size - selector of public key sizes
132  *  ossl-pkey-get-public - strip the private data
133  *  Lisp_EVP_PKEY - lrecord object to store public keys
134  * + RSA
135  *  ossl-rsa-generate-key - constructor of RSA public keys
136  *  ossl-rsa-pkey-p - discriminator of RSA public keys
137  *  ossl-rsa-subkey-p - comparator of two keys
138  * + DSA
139  *  ossl-dsa-generate-key - constructor of DSA public keys
140  *  ossl-dsa-pkey-p - discriminator of DSA public keys
141  *  ossl-dsa-subkey-p - comparator of two keys
142  * + EC
143  *  ossl-ec-generate-key - constructor of EC public keys
144  *  ossl-ec-pkey-p - discriminator of EC public keys
145  * + DH
146  *  ossl-dh-pkey-p - discriminator of DH public keys
147  *
148  * - HYBRID
149  *  ossl-seal - gateway to public key hybrid (envelope) encryption
150  *  ossl-open - gateway to public key hybrid (envelope) decryption
151  *
152  * - SIGN
153  *  ossl-sign - gateway to public key signature
154  *  ossl-verify - gateway to public key signature verification
155  *
156  * - PEM
157  *  ossl-pem-read-public-key
158  *  ossl-pem-read-key
159  *  ossl-pem-write-public-key
160  *  ossl-pem-write-key
161  *
162  * - SSL (it is highly likely to change entirely)
163  *  ossl-connect - constructor for SSL connection objects
164  *  ossl-finish - destructor of SSL connection objects
165  *  ossl-pending - predicate if data is available for read
166  *  ossl-read -
167  *  ossl-write -
168  *  ossl-x509-get-subject
169  *  ossl-x509-get-issuer
170  *  ossl-x509-get-pubkey
171  *  ossl-sslcipher-version
172  *  ossl-sslcipher-name
173  *  ossl-sslcipher-bits
174  *
175  *
176  * * Todo (internally):
177  *  - implement the usage of engines
178  *  - implement X.509 stuff
179  *  - make TLS/SSL version selectable by user instead of #ifdef'fing it
180  *
181  *
182  * * Roadmap:
183  *  1. Implement basic C stuff, mostly for accessing the structures
184  *     which is evil and insecure if done with an elisp interface
185  *  2. Implement higher level API functions (without the guts of the actual
186  *     OpenSSL libcrypto implementation)
187  *  3. Implement highest level user functions for actual daily consumption
188  *     (e.g. keyrings, import/export of keys, stuff like that)
189  *  4. Build an API (called CERTS) on top of that which transparently
190  *     brings security functions to elisp-libraries
191  *     Goals:
192  *     - install a master password system a la firefox
193  *     - implement an opaque lisp type for storing security relevant stuff
194  *     - securify parts of the obarray against other parts of it
195  *       (useful e.g. for erbot which otherwise brags your secrets to the
196  *        world)
197  *
198  *
199  * * Bugs:
200  *  - any function using or needing random data assumes you have /dev/urandom
201  *
202  *
203  * * Examples:
204  *
205  *  - RAND:
206  *    (ossl-rand-bytes 8)
207  *    (base16-encode-string (ossl-rand-bytes 16))
208  *
209  *  - MD:
210  *    (ossl-available-digests)
211  *
212  *    (ossl-digest 'MD5 "test")
213  *    (base16-encode-string (ossl-digest 'MD5 "test"))
214  *    ;; compare to
215  *    (md5 "test")
216  *
217  *    (base64-encode-string (ossl-digest 'SHA1 "test"))
218  *
219  *    (base16-encode-string (ossl-digest 'RIPEMD160 "test"))
220  *
221  *  - HMAC:
222  *    (ossl-hmac 'md5 "testmess" "testpass")
223  *
224  *    (base16-encode-string (ossl-hmac 'dsa-sha1 "testmess" "testpass"))
225  *
226  *  - CIPHER:
227  *    ;; retrieve a list of available cipher algorithms first
228  *    (ossl-available-ciphers)
229  *
230  *    ;; generate a key/iv pair (iv = initialisation vector)
231  *    ;; from a password
232  *    (ossl-bytes-to-key 'AES-256-ECB 'RIPEMD160 nil "password" 1)
233  *
234  *    ;; use a key/iv pair to initiate an encryption
235  *    (setq key (ossl-bytes-to-key 'BF-CBC 'DSA-SHA1 "somesalt" "somepass" 24))
236  *    (setq enc (ossl-encrypt 'BF-CBC "a test string" (car key) (cdr key)))
237  *    ;; of course we can decrypt it again
238  *    (ossl-decrypt 'BF-CBC enc (car key) (cdr key))
239  *    ;; in contrast:
240  *    (ossl-decrypt 'BF-ECB enc (car key) (cdr key))
241  *      ;; this one yields an error since BF-CBC is not BF-ECB
242  *
243  *  - PKEY:
244  *  + General:
245  *    ;; SOMETHING HERE
246  *
247  *  + RSA:
248  *    ;; generate an rsa key of size 2048
249  *    (setq pkey (ossl-rsa-generate-key 2048 17))
250  *    (ossl-rsa-pkey-p pkey)
251  *
252  *    ;; generate an rsa key of size 1024 and flush the private data
253  *    (setq k1 (ossl-rsa-generate-key 1024 17))
254  *    (setq k2 (ossl-rsa-get-public k1))
255  *    (setq k2 (ossl-pkey-get-public k1))
256  *    ;; now check if k2 fits into k1 (i.e. if the public data is the same)
257  *    (ossl-rsa-subkey-p k2 k1)
258  *
259  *  + DSA:
260  *    ;; generate a dsa key of size 1024 (dsa is digital signature algo)
261  *    ;; Note: I dont restrict the size, but it has to be <=1024 if
262  *    ;; used to actually sign something
263  *    (setq pkey (ossl-dsa-generate-key 1024))
264  *    (ossl-dsa-pkey-p pkey)
265  *
266  *    ;; now generate a dsa key again and flush the private data
267  *    ;; k2 can then only be used to verify signatures
268  *    (setq k1 (ossl-dsa-generate-key 1024))
269  *    (setq k2 (ossl-dsa-get-public k1))
270  *    (setq k2 (ossl-pkey-get-public k1))
271  *    ;; check if k2 is a public copy of k1
272  *    (ossl-dsa-subkey-p k2 k1)
273  *
274  *  + EC:
275  *  Note: For these functions you must have enabled EC in your OpenSSL lib
276  *    (setq pkey (ossl-ec-generate-key))
277  *    (ossl-ec-pkey-p pkey)
278  *    ;; generate an ec (elliptic curve) key
279  *    ;; Note: this is probably disabled in your openssl
280  *    (when (featurep 'openssl-ec)
281  *      (setq pkey (ossl-ec-generate-key))
282  *      (ossl-ec-pkey-p pkey))
283  *
284  *  + DH:
285  *  Note: For these functions you must have enabled DH in your OpenSSL lib
286  *    ;; not yet
287  *
288  *  - HYBRID
289  *    (setq key (ossl-rsa-generate-key 2048 3))
290  *    (setq enc (ossl-seal 'AES-256-ECB "a tight secret" key))
291  *    (ossl-open 'AES-256-ECB (car enc) key (cadr enc) (caddr enc))
292  *    ;; behold also:
293  *    (ossl-open 'AES-256-ECB (car enc) key (cadr enc) "some other iv!!!")
294  *      ;; this one is okay, too! since AES-256-ECB needs no IV
295  *    ;; but:
296  *    (setq key (ossl-rsa-generate-key 2048 3))
297  *    (ossl-open 'AES-256-ECB (car enc) key (cadr enc) (caddr enc))
298  *      ;; this yields probably an error since now key holds another key!
299  *
300  *  - SIGN
301  *    (setq key (ossl-dsa-generate-key 1024))
302  *    (setq sig (ossl-sign 'DSA-SHA1 "this is MY msg" key))
303  *    (ossl-verify 'DSA-SHA1 "this is MY msg" sig key)
304  *    ;; and behold:
305  *    (ossl-verify 'DSA-SHA1 "this is not MY msg" sig key)
306  *
307  *    (setq key (ossl-rsa-generate-key 2048 3))
308  *    (setq sig1 (ossl-sign 'RSA-MD5 "this is MY msg" key))
309  *    (setq sig2 (ossl-sign 'RSA-MD5 "this is MY other msg" key))
310  *    (ossl-verify 'RSA-MD5 "this is MY msg" sig1 key)
311  *    ;; and behold:
312  *    (ossl-verify 'RSA-SHA1 "this is MY msg" sig2 key)
313  *
314  *    (setq key (ossl-ec-generate-key))
315  *    (setq sig (ossl-sign 'ecdsa-with-SHA1 "this is MY msg" key))
316  *    (ossl-verify 'ecdsa-with-SHA1 "this is MY msg" sig key)
317  *
318  *  - PEM
319  *    (setq key (ossl-rsa-generate-key 1024 3))
320  *    (ossl-pem-write-key "/tmp/pkey1.pem" key)
321  *    (ossl-pem-write-key "/tmp/pkey2.pem" key 'AES-256-ECB "somepass")
322  *    (ossl-pem-write-public-key "/tmp/pkeyp.pem" key)
323  *
324  *  - SSL
325  *    ;; no examples yet
326  *    (setq p (open-network-stream "tmp" "tmp" "www.redhat.com" "443"))
327  *    (setq m (ossl-connect p))
328  *    (ossl-x509-get-subject m)
329  *    (ossl-x509-get-issuer m)
330  *    (ossl-x509-get-pubkey m)
331  *    (ossl-cipher-get-version m)
332  *    (ossl-cipher-get-name m)
333  *    (ossl-finish m)
334  *
335  */
336
337 #include <config.h>
338
339 #include "lisp.h"
340
341 #include "buffer.h"
342 #include "sysdep.h"
343 #include "lrecord.h"
344 #include "lstream.h"
345 #include "opaque.h"
346
347 #ifdef HAVE_SOCKETS
348 #include "events/events.h"
349 #include "process.h"
350 #include "procimpl.h"
351 #endif
352
353 #include <errno.h>
354
355 #include "openssl.h"
356
357 #ifdef FILE_CODING
358 #include "mule/file-coding.h"
359 #endif
360
361 #ifdef HAVE_POSTGRESQL
362 #include "database/postgresql.h"
363 #endif
364
365 #define OSSL_CODING Qbinary
366
367 #define OSSL_STRING_LENGTH XSTRING_CHAR_LENGTH
368
369 static Lisp_Object Qopenssl;
370
371 #define __OSSL_DEBUG__(args...)         fprintf(stderr, "OSSL " args)
372 #ifndef OSSL_DEBUG_FLAG
373 #define OSSL_DEBUG(args...)
374 #else
375 #define OSSL_DEBUG(args...)             __OSSL_DEBUG__(args)
376 #endif
377 #define OSSL_DEBUG_CTX(args...)         OSSL_DEBUG("[connection]: " args)
378 #define OSSL_CRITICAL(args...)          __OSSL_DEBUG__("CRITICAL: " args)
379
380 \f
381 int ossl_pkey_has_public_data(EVP_PKEY *pkey);
382 int ossl_pkey_has_private_data(EVP_PKEY *pkey);
383
384 int rsa_pkey_p(EVP_PKEY *pkey);
385 #ifndef OPENSSL_NO_RSA
386 int rsa_pkey_has_public_data(RSA *rsakey);
387 int rsa_pkey_has_private_data(RSA *rsakey);
388 #endif
389
390 int dsa_pkey_p(EVP_PKEY *pkey);
391 #ifndef OPENSSL_NO_DSA
392 int dsa_pkey_has_public_data(DSA *dsakey);
393 int dsa_pkey_has_private_data(DSA *dsakey);
394 DSA *dsa_get_public(EVP_PKEY *pk);
395 #endif
396
397 int ec_pkey_p(EVP_PKEY *pkey);
398 #ifndef OPENSSL_NO_EC
399 int ec_pkey_has_public_data(EC_KEY *ec_key);
400 int ec_pkey_has_private_data(EC_KEY *ec_key);
401 EC_KEY *ec_get_public(EVP_PKEY *pk);
402 int ec_curve_by_name(char *name);
403 #endif
404
405 int dh_pkey_p(EVP_PKEY *pkey);
406 #ifndef OPENSSL_NO_DH
407 int dh_pkey_has_public_data(DH *dh_key);
408 int dh_pkey_has_private_data(DH *dh_key);
409 DH *dh_get_public(EVP_PKEY *pk);
410 #endif
411
412 #ifdef OSSL_DEBUG_FLAG
413 static long ossl_bio_dump_callback(BIO*, int, const char*, int, long, long);
414 #endif
415 static int ossl_ssl_proselytise_process(Lisp_Object, Lisp_Object);
416 static int ossl_ssl_unproselytise_process(Lisp_Object, Lisp_Object);
417 int ossl_ssl_inject_ca(Lisp_Object, Lisp_Object);
418 int ossl_ssl_inject_ca_file(Lisp_Object, Lisp_Object);
419 int ossl_ssl_inject_ca_path(Lisp_Object, Lisp_Object);
420 int ossl_ssl_inject_cert(Lisp_Object, Lisp_Object, Lisp_Object);
421 int ossl_ssl_inject_cert_file(Lisp_Object, Lisp_Object, Lisp_Object);
422
423 Lisp_Object Qssl2, Qssl23, Qssl3, Qtls1;
424
425 /* Problem Ciphers */
426 Lisp_Object QAES_256_XTS, QAES_128_XTS, Qid_aes256_CCM, Qid_aes256_GCM;
427 Lisp_Object Qid_aes192_CCM, Qid_aes192_GCM, Qid_aes128_CCM;
428 Lisp_Object Qid_aes128_GCM, Qid_aes256_wrap, Qid_aes192_wrap;
429 Lisp_Object Qid_aes128_wrap, QCAMELLIA_256_CFB8, QCAMELLIA_192_CFB8;
430 Lisp_Object QCAMELLIA_128_CFB8, QCAMELLIA_256_CFB1, QCAMELLIA_192_CFB1;
431 Lisp_Object QCAMELLIA_128_CFB1, QDES_EDE3_CFB8, QDES_EDE3_CFB1, QDES_CFB8;
432 Lisp_Object QDES_CFB1, QAES_256_CFB8, QAES_192_CFB8, QAES_128_CFB8;
433 Lisp_Object QAES_256_CFB1, QAES_192_CFB1, QAES_128_CFB1;
434 Lisp_Object Qid_smime_alg_CMS3DESwrap;
435 Lisp_Object Vossl_cipher_blacklist;
436 int ossl_check_cipher(Lisp_Object);
437
438 extern Lisp_Object Qfile_readable_p;
439 extern Lisp_Object Qfile_writable_p;
440
441 /*
442  *
443  * AUXILIARY
444  *
445  */
446 DEFUN("ossl-version", Fossl_version, 0, 0, 0, /*
447 Return a descriptive version number of the OpenSSL in use.
448 */
449       ())
450 {
451         return build_string(SSLeay_version(SSLEAY_VERSION));
452 }
453
454
455 DEFUN("ossl-available-digests", Fossl_available_digests, 0, 0, 0, /*
456 Return a list of digest algorithms in the underlying crypto library.
457 This yields a plain list of symbols.
458 */
459       ())
460 {
461         int nid;
462         Lisp_Object digests;
463
464         digests = Qnil;
465
466         OpenSSL_add_all_digests();
467
468         /*  is there a better way to get the size of the nid list? */
469         for (nid = 10000; nid >= 0; --nid) {
470                 const EVP_MD *digest = EVP_get_digestbynid(nid);
471                 if (digest) {
472                         digests = Fcons(intern(OBJ_nid2sn(nid)), digests);
473                 }
474         }
475
476         EVP_cleanup();
477
478         return digests;
479 }
480
481 int
482 ossl_check_cipher(Lisp_Object cipher)
483 {
484         if (!NILP(Fmember(cipher, Vossl_cipher_blacklist))) {
485                 return 1;
486         } else {
487                 return 0;
488         }
489 }
490
491 DEFUN("ossl-available-ciphers", Fossl_available_ciphers, 0, 0, 0, /*
492 Return a list of cipher algorithms in the underlying crypto library.
493 This yields a plain list of symbols.
494 */
495       ())
496 {
497         int nid;
498         Lisp_Object ciphers;
499
500         OpenSSL_add_all_ciphers();
501
502         ciphers = Qnil;
503
504         /* is there a better way to get the size of the nid list? */
505         for (nid = 10000; nid >= 0; --nid) {
506                 const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
507                 if (cipher &&
508                     (ossl_check_cipher(intern(OBJ_nid2sn(nid))) == 0)) {
509                         ciphers = Fcons(intern(OBJ_nid2sn(nid)), ciphers);
510                 }
511         }
512
513         EVP_cleanup();
514
515         return ciphers;
516 }
517
518
519 #define ossl_digest_fun(var, fun)                                       \
520 do {                                                                    \
521         int __kl;                                                       \
522         const EVP_MD *__md;                                             \
523                                                                         \
524         OpenSSL_add_all_digests();                                      \
525                                                                         \
526         __md = EVP_get_digestbyname(                                    \
527                 (char *)string_data(XSYMBOL(var)->name));               \
528                                                                         \
529         if (!__md) {                                                    \
530                 EVP_cleanup();                                          \
531                 return -1;                                              \
532         }                                                               \
533                                                                         \
534         __kl = fun(__md);                                               \
535                                                                         \
536         EVP_cleanup();                                                  \
537                                                                         \
538         return __kl;                                                    \
539 } while (0);
540
541 static int
542 ossl_digest_size(Lisp_Object digest)
543 {
544         ossl_digest_fun(digest, EVP_MD_size);
545 }
546
547 static int
548 ossl_digest_block_size(Lisp_Object digest)
549 {
550         ossl_digest_fun(digest, EVP_MD_block_size);
551 }
552
553 DEFUN("ossl-digest-size", Fossl_digest_size, 1, 1, 0, /*
554 Return the hash length of DIGEST in bytes.
555 */
556       (digest))
557 {
558         int size = ossl_digest_size(digest);
559
560         if (size < 0)
561                 error ("no such digest");
562
563         return make_int(size);
564 }
565
566 /* deprecated */
567 DEFUN("ossl-digest-bits", Fossl_digest_bits, 1, 1, 0, /*
568 Return the number of effective output bits of DIGEST.
569 */
570       (digest))
571 {
572         int size = ossl_digest_size(digest);
573
574         if (size < 0)
575                 error ("no such digest");
576
577         return make_int(size*8);
578 }
579
580 DEFUN("ossl-digest-block-size", Fossl_digest_block_size, 1, 1, 0, /*
581 Return the block size of DIGEST in bytes.
582 */
583       (digest))
584 {
585         int size = ossl_digest_block_size(digest);
586
587         if (size < 0)
588                 error ("no such digest");
589
590         return make_int(size);
591 }
592
593
594 #define ossl_cipher_fun(var, fun)                                       \
595 do {                                                                    \
596         int __kl;                                                       \
597         const EVP_CIPHER *__ciph;                                       \
598                                                                         \
599         if (ossl_check_cipher(var) != 0)                                \
600                 error("use of blacklisted cipher prohibited");          \
601                                                                         \
602         OpenSSL_add_all_ciphers();                                      \
603                                                                         \
604         __ciph = EVP_get_cipherbyname(                                  \
605                 (char *)string_data(XSYMBOL(var)->name));               \
606                                                                         \
607         if (!__ciph) {                                                  \
608                 EVP_cleanup();                                          \
609                 return -1;                                              \
610         }                                                               \
611                                                                         \
612         __kl = fun(__ciph);                                             \
613                                                                         \
614         EVP_cleanup();                                                  \
615                                                                         \
616         return __kl;                                                    \
617 } while (0);
618
619 static int
620 ossl_cipher_key_length(Lisp_Object cipher)
621 {
622         ossl_cipher_fun(cipher, EVP_CIPHER_key_length);
623 }
624
625 static int
626 ossl_cipher_iv_length(Lisp_Object cipher)
627 {
628         ossl_cipher_fun(cipher, EVP_CIPHER_iv_length);
629 }
630
631 static int
632 ossl_cipher_block_size(Lisp_Object cipher)
633 {
634         ossl_cipher_fun(cipher, EVP_CIPHER_block_size);
635 }
636
637 static int
638 ossl_cipher_mode(Lisp_Object cipher)
639 {
640         ossl_cipher_fun(cipher, EVP_CIPHER_mode);
641 }
642
643 DEFUN("ossl-cipher-key-length", Fossl_cipher_key_length, 1, 1, 0, /*
644 Return the effective key length of CIPHER in bytes.
645 */
646       (cipher))
647 {
648         int size = ossl_cipher_key_length(cipher);
649
650         if (size < 0)
651                 error ("no such cipher");
652
653         return make_int(size);
654 }
655
656 /* deprecated */
657 DEFUN("ossl-cipher-bits", Fossl_cipher_bits, 1, 1, 0, /*
658 Return the effective key size of CIPHER in bits.
659 */
660       (cipher))
661 {
662         int size = ossl_cipher_key_length(cipher);
663
664         if (size < 0)
665                 error ("no such cipher");
666
667         return make_int(size*8);
668 }
669
670 DEFUN("ossl-cipher-iv-length", Fossl_cipher_iv_length, 1, 1, 0, /*
671 Return the initialisation vector length of CIPHER in bytes.
672 */
673       (cipher))
674 {
675         int size = ossl_cipher_iv_length(cipher);
676
677         if (size < 0)
678                 error ("no such cipher");
679
680         return make_int(size);
681 }
682
683 DEFUN("ossl-cipher-block-size", Fossl_cipher_block_size, 1, 1, 0, /*
684 Return the block size of CIPHER in bytes.
685 */
686       (cipher))
687 {
688         int size = ossl_cipher_block_size(cipher);
689
690         if (size < 0)
691                 error ("no such cipher");
692
693         return make_int(size);
694 }
695
696 DEFUN("ossl-cipher-mode", Fossl_cipher_mode, 1, 1, 0, /*
697 Return the operation mode of CIPHER.
698 */
699       (cipher))
700 {
701         Lisp_Object result = Qnil;
702         int mode = ossl_cipher_mode(cipher);
703
704         if (mode < 0)
705                 error ("no such cipher");
706
707         switch (mode) {
708         case EVP_CIPH_STREAM_CIPHER:
709                 result = intern("stream");
710                 break;
711         case EVP_CIPH_ECB_MODE:
712                 result = intern("ecb");
713                 break;
714         case EVP_CIPH_CBC_MODE:
715                 result = intern("cbc");
716                 break;
717         case EVP_CIPH_CFB_MODE:
718                 result = intern("cfb");
719                 break;
720         case EVP_CIPH_OFB_MODE:
721                 result = intern("ofb");
722                 break;
723         default:
724                 result = intern("cbc");
725                 break;
726         }
727
728         return result;
729 }
730
731 \f
732 /*
733  *
734  * RAND
735  *
736  */
737 DEFUN("ossl-rand-bytes", Fossl_rand_bytes, 1, 1, 0, /*
738 Return COUNT bytes of randomness.
739
740 Note: You probably want to put a wrapping encoder function
741 \(like `base16-encode-string'\) around it, since this returns
742 binary string data.
743 */
744       (count))
745 {
746         char *outbuf;
747         Lisp_Object l_outbuf;
748         int count_ext;
749
750         int speccount = specpdl_depth(), res;
751
752         CHECK_NATNUM(count);
753         count_ext = (int)XINT(count);
754
755         /* now allocate some output buffer externally */
756         XMALLOC_ATOMIC_OR_ALLOCA(outbuf, count_ext, char);
757
758         res = RAND_bytes((unsigned char*)outbuf, count_ext);
759         if (!res) {
760                 error("RAND_bytes did not have enough seed "
761                       "to perform operation");
762                 return Qnil;
763         } else if (res < 0) {
764                 error("RAND_bytes failed");
765                 return Qnil;
766         }
767
768         l_outbuf = make_ext_string(outbuf, count_ext, OSSL_CODING);
769         XMALLOC_UNBIND(outbuf, count_ext, speccount);
770
771         return l_outbuf;
772 }
773
774 DEFUN("ossl-rand-bytes-egd", Fossl_rand_bytes_egd, 1, 2, 0, /*
775 Return COUNT bytes of randomness from an EGD socket.
776 By default use the socket /var/run/egd-pool.
777
778 Note: You probably want to put a wrapping encoder function
779 \(like `base16-encode-string'\) around it, since this returns
780 binary string data.
781 */
782       (count, egd))
783 {
784         /* This function can GC */
785         char *outbuf;
786         Lisp_Object l_outbuf;
787         int count_ext;
788         int speccount = specpdl_depth(), res;
789         /* gc cruft */
790         struct gcpro gcpro1, gcpro2;
791
792         GCPRO2(count, egd);
793
794         CHECK_NATNUM(count);
795         if (!NILP(egd)) {
796                 CHECK_STRING(egd);
797                 egd = Fexpand_file_name(egd, Qnil);
798                 if (NILP(Ffile_exists_p(egd)))
799                         egd = Qnil;
800         }
801         count_ext = XINT(count);
802
803         /* now allocate some output buffer externally */
804         XMALLOC_ATOMIC_OR_ALLOCA(outbuf, count_ext, char);
805
806         if (!NILP(egd)) {
807                 res = RAND_query_egd_bytes((char*)XSTRING_DATA(egd),
808                                            (unsigned char*)outbuf, count_ext);
809         } else {
810                 res = RAND_query_egd_bytes("/var/run/egd-pool",
811                                            (unsigned char*)outbuf, count_ext);
812         }
813         if (!res) {
814                 UNGCPRO;
815                 error("RAND_query_egd_bytes did not have enough seed "
816                       "to perform operation");
817                 return Qnil;
818         } else if (res < 0) {
819                 UNGCPRO;
820                 error("RAND_query_egd_bytes failed");
821                 return Qnil;
822         }
823
824         l_outbuf = make_ext_string(outbuf, count_ext, OSSL_CODING);
825         XMALLOC_UNBIND(outbuf, count_ext, speccount);
826
827         UNGCPRO;
828         return l_outbuf;
829 }
830
831 /*
832  *
833  * DIGEST HANDLING
834  *
835  */
836 DEFUN("ossl-digest", Fossl_digest, 2, 2, 0,     /*
837 Return the message digest of STRING computed by DIGEST.
838 DIGEST may be one of the OpenSSL digests you have compiled.
839 See `ossl-available-digests'.
840
841 Note: You probably want to put a wrapping encoder function
842 \(like `base16-encode-string'\) around it, since this returns
843 binary string data.
844 */
845       (digest, string))
846 {
847         EVP_MD_CTX *mdctx;
848         const EVP_MD *md;
849         char md_value[EVP_MAX_MD_SIZE];
850         unsigned int md_len;
851
852         CHECK_SYMBOL(digest);
853         CHECK_STRING(string);
854
855         OpenSSL_add_all_digests();
856         md = EVP_get_digestbyname(
857                 (char *)string_data(XSYMBOL(digest)->name));
858
859         if (!md) {
860                 EVP_cleanup();
861                 error ("no such digest");
862         }
863
864         mdctx = xnew(EVP_MD_CTX);
865         EVP_MD_CTX_init(mdctx);
866         EVP_DigestInit_ex(mdctx, md, NULL);
867         EVP_DigestUpdate(mdctx,(char*)XSTRING_DATA(string),
868                          XSTRING_LENGTH(string));
869         EVP_DigestFinal_ex(mdctx, (unsigned char *)md_value, &md_len);
870         EVP_MD_CTX_cleanup(mdctx);
871
872         EVP_cleanup();
873         xfree(mdctx);
874
875         return make_ext_string(md_value, md_len, OSSL_CODING);
876 }
877
878 DEFUN("ossl-digest-file", Fossl_digest_file, 2, 2, 0,   /*
879 Return the message digest of the contents of FILE computed by DIGEST.
880 DIGEST may be one of the OpenSSL digests you have compiled.
881 See `ossl-available-digests'.
882
883 Note: You probably want to put a wrapping encoder function
884 \(like `base16-encode-string'\) around it, since this returns
885 binary string data.
886 */
887       (digest, file))
888 {
889         EVP_MD_CTX *mdctx;
890         const EVP_MD *md;
891         unsigned char md_value[EVP_MAX_MD_SIZE];
892         unsigned int md_len, md_blocksize;
893         ssize_t n;
894         /* input file */
895         FILE *fp;
896
897
898         CHECK_SYMBOL(digest);
899         CHECK_STRING(file);
900
901
902         file = Fexpand_file_name(file, Qnil);
903
904         if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
905             (fseek(fp, 0, SEEK_SET))) {
906                 if (fp)
907                         fclose(fp);
908                 return wrong_type_argument(Qfile_readable_p, file);
909         }
910
911         OpenSSL_add_all_digests();
912         md = EVP_get_digestbyname(
913                 (char *)string_data(XSYMBOL(digest)->name));
914
915         if (!md) {
916                 EVP_cleanup();
917                 fclose(fp);
918                 error ("no such digest");
919         }
920
921         mdctx = xnew(EVP_MD_CTX);
922         EVP_MD_CTX_init(mdctx);
923         md_blocksize = (unsigned int)(EVP_MD_block_size(md) / 8);
924         SXE_SET_UNUSED(md_blocksize);
925
926         EVP_DigestInit_ex(mdctx, md, NULL);
927
928         /* we reuse md_value here for streaming over fp */
929         do {
930                 n = fread(md_value, 1, EVP_MAX_MD_SIZE, fp);
931                 if (n < 0) {
932                         EVP_cleanup();
933                         fclose(fp);
934                         xfree(mdctx);
935                         error("file corrupted");
936                         return Qnil;
937                 }
938                 EVP_DigestUpdate(mdctx, md_value, n);
939         } while (n > 0);
940
941         EVP_DigestFinal_ex(mdctx, md_value, &md_len);
942         EVP_MD_CTX_cleanup(mdctx);
943
944         EVP_cleanup();
945         xfree(mdctx);
946         fclose(fp);
947
948         return make_ext_string((char *)md_value, md_len, OSSL_CODING);
949 }
950
951
952 /*
953  *
954  * HMAC (aka keyed hashes)
955  *
956  */
957 DEFUN("ossl-hmac", Fossl_hmac, 3, 3, 0, /*
958 Return the message authentication code of MSG
959 using the hash function DIGEST and the key PASSWORD.
960
961 Note: You probably want to put a wrapping encoder function
962 \(like `base16-encode-string'\) around it, since this returns
963 binary string data.
964 */
965       (digest, msg, password))
966 {
967         const EVP_MD *md;
968         HMAC_CTX *hmacctx;
969
970         /* buffer for the ciphertext */
971         unsigned char outbuf[EVP_MAX_MD_SIZE];
972         unsigned int outlen;
973         /* buffer for external password */
974         char *password_ext;
975         unsigned int password_len;
976 #if 0   /* why? */
977         /* buffer for external message */
978         char *msg_ext;
979         unsigned int msg_len;
980 #endif
981
982         CHECK_SYMBOL(digest);
983         CHECK_STRING(msg);
984         CHECK_STRING(password);
985
986         OpenSSL_add_all_digests();
987         md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
988
989         if (!md) {
990                 EVP_cleanup();
991                 error ("no such digest");
992         }
993
994         TO_EXTERNAL_FORMAT (LISP_STRING, password,
995                             C_STRING_ALLOCA, password_ext, OSSL_CODING);
996         password_len = OSSL_STRING_LENGTH(password);
997
998 #if 0   /* i wonder why */
999         TO_EXTERNAL_FORMAT (LISP_STRING, msg,
1000                             C_STRING_ALLOCA, msg_ext, OSSL_CODING);
1001         msg_len = OSSL_STRING_LENGTH(msg);
1002 #endif
1003
1004         hmacctx = xnew(HMAC_CTX);
1005         HMAC_CTX_init(hmacctx);
1006         HMAC_Init(hmacctx, password_ext, password_len, md);
1007         HMAC_Update(hmacctx, (unsigned char*)XSTRING_DATA(msg),
1008                     XSTRING_LENGTH(msg));
1009         HMAC_Final(hmacctx, outbuf, &outlen);
1010         HMAC_CTX_cleanup(hmacctx);
1011         xfree(hmacctx);
1012
1013         EVP_cleanup();
1014
1015         return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1016 }
1017
1018 DEFUN("ossl-hmac-file", Fossl_hmac_file, 3, 3, 0, /*
1019 Return the message authentication code of the contents of FILE
1020 using the hash function DIGEST and the key PASSWORD.
1021
1022 Note: You probably want to put a wrapping encoder function
1023 \(like `base16-encode-string'\) around it, since this returns
1024 binary string data.
1025 */
1026       (digest, file, password))
1027 {
1028         const EVP_MD *md;
1029         HMAC_CTX *hmacctx;
1030
1031         /* buffer for the ciphertext */
1032         unsigned char outbuf[EVP_MAX_MD_SIZE];
1033         unsigned int outlen;
1034         ssize_t n;
1035         /* buffer for external password */
1036         char *password_ext;
1037         unsigned int password_len;
1038         /* input file */
1039         FILE *fp;
1040
1041         CHECK_SYMBOL(digest);
1042         CHECK_STRING(file);
1043         CHECK_STRING(password);
1044
1045         file = Fexpand_file_name(file, Qnil);
1046
1047         if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1048             (fseek(fp, 0, SEEK_SET))) {
1049                 if (fp)
1050                         fclose(fp);
1051                 return wrong_type_argument(Qfile_readable_p, file);
1052         }
1053
1054
1055         OpenSSL_add_all_digests();
1056         md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
1057
1058         if (!md) {
1059                 EVP_cleanup();
1060                 error ("no such digest");
1061         }
1062
1063         TO_EXTERNAL_FORMAT (LISP_STRING, password,
1064                             C_STRING_ALLOCA, password_ext, OSSL_CODING);
1065         password_len = OSSL_STRING_LENGTH(password);
1066
1067         hmacctx = xnew(HMAC_CTX);
1068         HMAC_CTX_init(hmacctx);
1069         HMAC_Init(hmacctx, password_ext, password_len, md);
1070
1071         /* we reuse md_value here for streaming over fp */
1072         do {
1073                 n = fread(outbuf, 1, EVP_MAX_MD_SIZE, fp);
1074                 if (n < 0) {
1075                         EVP_cleanup();
1076                         fclose(fp);
1077                         xfree(hmacctx);
1078                         error("file corrupted");
1079                         return Qnil;
1080                 }
1081                 HMAC_Update(hmacctx, outbuf, n);
1082         } while (n > 0);
1083
1084         HMAC_Final(hmacctx, outbuf, &outlen);
1085         HMAC_CTX_cleanup(hmacctx);
1086         xfree(hmacctx);
1087
1088         EVP_cleanup();
1089         fclose(fp);
1090
1091         return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1092 }
1093
1094
1095 /*
1096  *
1097  * SYMMETRIC CIPHER
1098  *
1099  */
1100 DEFUN("ossl-bytes-to-key", Fossl_bytes_to_key, 5, 5, 0, /*
1101 Derive a key and initialisation vector (iv) suitable for a cipher.
1102 Return a string KEY being the key. The initialisation vector is
1103 put into KEY's property list as 'iv.
1104
1105 CIPHER \(a symbol\) is the cipher to derive the key and IV for.
1106 Valid ciphers can be obtained by `ossl-available-ciphers'.
1107
1108 DIGEST \(a symbol\) is the message digest to use.
1109 Valid digests can be obtained by `ossl-available-digests'.
1110
1111 SALT \(string or `nil'\) is used as a salt in the derivation.
1112 Use `nil' here to indicate that no salt is used.
1113
1114 PASSWORD is an arbitrary string which is processed to derive a
1115 unique key and IV.
1116
1117 COUNT \(a positive integer\) is the iteration count to use. This
1118 indicates how often the hash algorithm is called recursively.
1119
1120 Note: You probably want to put a wrapping encoder function
1121 \(like `base16-encode-string'\) around it, since this returns
1122 binary string data.
1123 */
1124       (cipher, digest, salt, password, count))
1125 {
1126         const EVP_MD *md;
1127         const EVP_CIPHER *ciph;
1128         const char *salt_ext;
1129
1130         char *password_ext;
1131         unsigned int password_len;
1132
1133         char key[EVP_MAX_KEY_LENGTH];
1134         char iv[EVP_MAX_IV_LENGTH];
1135
1136         Lisp_Object result;
1137
1138         CHECK_STRING(password);
1139         CHECK_SYMBOL(cipher);
1140         CHECK_SYMBOL(digest);
1141         CHECK_NATNUM(count);
1142
1143         if (ossl_check_cipher(cipher) != 0)
1144                 error("use of blacklisted cipher prohibited");
1145
1146         if (!XINT(count))
1147                 error ("count has to be a non-zero positive integer");
1148
1149         OpenSSL_add_all_algorithms();
1150         md = EVP_get_digestbyname(
1151                 (char *)string_data(XSYMBOL(digest)->name));
1152         ciph = EVP_get_cipherbyname(
1153                 (char *)string_data(XSYMBOL(cipher)->name));
1154
1155         if (!ciph) {
1156                 EVP_cleanup();
1157                 error ("no such cipher");
1158         }
1159
1160         if (!md) {
1161                 EVP_cleanup();
1162                 error ("no such digest");
1163         }
1164
1165         if (NILP(salt)) {
1166                 salt_ext = NULL;
1167         } else {
1168                 CHECK_STRING(salt);
1169                 TO_EXTERNAL_FORMAT (LISP_STRING, salt,
1170                                     C_STRING_ALLOCA, salt_ext, OSSL_CODING);
1171                 salt_ext = NULL;
1172         }
1173
1174         TO_EXTERNAL_FORMAT (LISP_STRING, password,
1175                             C_STRING_ALLOCA, password_ext, OSSL_CODING);
1176         password_len = OSSL_STRING_LENGTH(password);
1177
1178         EVP_BytesToKey(ciph, md, (const unsigned char *)salt_ext,
1179                        (const unsigned char *)password_ext, password_len,
1180                        XINT(count),
1181                        (unsigned char *)key,
1182                        (unsigned char *)iv);
1183
1184         EVP_cleanup();
1185
1186         result = make_ext_string(key, EVP_CIPHER_key_length(ciph), OSSL_CODING);
1187         Fput(result, intern("iv"),
1188              make_ext_string(iv, EVP_CIPHER_iv_length(ciph), OSSL_CODING));
1189
1190         return result;
1191 }
1192
1193
1194 DEFUN("ossl-encrypt", Fossl_encrypt, 3, 4, 0,   /*
1195 Return the cipher of STRING computed by CIPHER under KEY.
1196
1197 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1198 you have compiled. See `ossl-available-ciphers'.
1199
1200 STRING is the text to be encrypted.
1201
1202 KEY should be a key generated suitably for this cipher, for example
1203 by `ossl-bytes-to-key'.
1204
1205 Optional fourth argument IV should be an initialisation vector
1206 suitable for this cipher. Normally the initialisation vector from
1207 KEY's property list is used. However, if IV is
1208 non-nil, use this IV instead.
1209
1210 Note: You probably want to put a wrapping encoder function
1211 \(like `base16-encode-string'\) around it, since this returns
1212 binary string data.
1213 */
1214       (cipher, string, key, iv))
1215 {
1216         /* buffer for the external string */
1217         char *string_ext;
1218         unsigned int string_len;
1219         /* buffer for the ciphertext */
1220         char *outbuf;
1221         int outlen;
1222         Lisp_Object l_outbuf;
1223         /* buffer for key */
1224         char *key_ext;
1225         /* buffer for iv */
1226         char *iv_ext;
1227
1228         /* declarations for the cipher */
1229         const EVP_CIPHER *ciph;
1230         EVP_CIPHER_CTX *ciphctx;
1231
1232         int tmplen;
1233         int speccount = specpdl_depth();
1234         Charcount alloclen;
1235
1236         /* frob the IV from the plist of key maybe */
1237         if (NILP(iv))
1238                 iv = Fget(key, intern("iv"), Qnil);
1239
1240         CHECK_SYMBOL(cipher);
1241         CHECK_STRING(string);
1242         CHECK_STRING(key);
1243         CHECK_STRING(iv);
1244
1245         if (ossl_check_cipher(cipher) != 0)
1246                 error("use of blacklisted cipher prohibited");
1247
1248         TO_EXTERNAL_FORMAT(LISP_STRING, string,
1249                            C_STRING_ALLOCA, string_ext, OSSL_CODING);
1250         string_len = OSSL_STRING_LENGTH(string);
1251
1252         if (string_len <= 0)
1253                 error ("string must be of non-zero positive length.");
1254
1255         OpenSSL_add_all_algorithms();
1256         /* ENGINE_load_builtin_engines(); */
1257         /* atm, no support for different engines */
1258         ciph = EVP_get_cipherbyname(
1259                 (char *)string_data(XSYMBOL(cipher)->name));
1260
1261         if (!ciph) {
1262                 EVP_cleanup();
1263                 error ("no such cipher");
1264         }
1265
1266         /* now allocate some output buffer externally
1267          * this one has to be at least EVP_CIPHER_block_size bigger
1268          * since block algorithms merely operate blockwise
1269          */
1270         alloclen = XSTRING_LENGTH(string) + EVP_CIPHER_block_size(ciph);
1271         XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
1272
1273         TO_EXTERNAL_FORMAT(LISP_STRING, key,
1274                             C_STRING_ALLOCA, key_ext, OSSL_CODING);
1275         TO_EXTERNAL_FORMAT(LISP_STRING, iv,
1276                            C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1277
1278         ciphctx = xnew(EVP_CIPHER_CTX);
1279         EVP_CIPHER_CTX_init(ciphctx);
1280         if (!EVP_EncryptInit(ciphctx, ciph,
1281                              (unsigned char *)key_ext,
1282                              (unsigned char *)iv_ext)) {
1283                 EVP_cleanup();
1284                 xfree(ciphctx);
1285                 error ("error in EncryptInit");
1286         }
1287         if (!EVP_EncryptUpdate(ciphctx,
1288                                (unsigned char *)outbuf, &outlen,
1289                                (unsigned char *)string_ext, string_len)) {
1290                 EVP_cleanup();
1291                 xfree(ciphctx);
1292                 error ("error in EncryptUpdate");
1293         }
1294         /* Buffer passed to EVP_EncryptFinal() must be after data just
1295          * encrypted to avoid overwriting it.
1296          */
1297         if (!EVP_EncryptFinal(ciphctx,
1298                               (unsigned char *)outbuf+outlen, &tmplen)) {
1299                 EVP_cleanup();
1300                 xfree(ciphctx);
1301                 error ("error in EncryptFinal");
1302         }
1303         /* added probable padding space to the length of the output buffer */
1304         outlen += tmplen;
1305         EVP_CIPHER_CTX_cleanup(ciphctx);
1306
1307         l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1308         XMALLOC_UNBIND(outbuf, alloclen, speccount);
1309
1310         EVP_cleanup();
1311         xfree(ciphctx);
1312
1313         return l_outbuf;
1314 }
1315
1316 DEFUN("ossl-encrypt-file", Fossl_encrypt_file, 3, 5, 0, /*
1317 Return the encrypted contents of FILE computed by CIPHER under KEY.
1318
1319 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1320 you have compiled. See `ossl-available-ciphers'.
1321
1322 FILE is the file to be encrypted.
1323
1324 Third argument KEY should be a key generated suitably for this
1325 cipher, for example by `ossl-bytes-to-key'.
1326
1327 Optional fourth argument IV should be an initialisation vector
1328 suitable for this cipher. Normally the initialisation vector from
1329 KEY's property list is used. However, if IV is
1330 non-nil, use this IV instead.
1331
1332 Optional fifth argument OUTFILE may specify a file to have the
1333 encrypted data redirected.
1334
1335 Note: You probably want to put a wrapping encoder function
1336 \(like `base16-encode-string'\) around it, since this returns
1337 binary string data.
1338 */
1339       (cipher, file, key, iv, outfile))
1340 {
1341         /* buffer for the external string */
1342         unsigned char string_in[1024];
1343         ssize_t string_len;
1344         unsigned int block_len;
1345         unsigned long file_size;
1346         /* buffer for the ciphertext */
1347         unsigned char *outbuf;
1348         unsigned char *obp;
1349         int outlen;
1350         Lisp_Object l_outbuf;
1351         /* buffer for key */
1352         char *key_ext;
1353         /* buffer for iv */
1354         char *iv_ext;
1355
1356         /* input file */
1357         FILE *fp;
1358         /* output file */
1359         FILE *of;
1360
1361         /* declarations for the cipher */
1362         const EVP_CIPHER *ciph;
1363         EVP_CIPHER_CTX *ciphctx;
1364
1365         int tmplen;
1366         int speccount = specpdl_depth();
1367         Charcount alloclen;
1368
1369         /* frob the IV from the plist of key maybe */
1370         if (NILP(iv))
1371                 iv = Fget(key, intern("iv"), Qnil);
1372
1373         CHECK_SYMBOL(cipher);
1374         CHECK_STRING(file);
1375         CHECK_STRING(key);
1376         CHECK_STRING(iv);
1377
1378         if (ossl_check_cipher(cipher) != 0)
1379                 error("use of blacklisted cipher prohibited");
1380
1381         if (!NILP(outfile)) {
1382                 CHECK_STRING(outfile);
1383                 outfile = Fexpand_file_name(outfile, Qnil);
1384                 if ((of = fopen((char *)XSTRING_DATA(outfile),"wb")) == NULL)
1385                         return wrong_type_argument(Qfile_writable_p, outfile);
1386         } else {
1387                 of = NULL;
1388         }
1389
1390         file = Fexpand_file_name(file, Qnil);
1391         if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1392             (fseek(fp, 0, SEEK_SET))) {
1393                 if (fp)
1394                         fclose(fp);
1395                 if (of)
1396                         fclose(of);
1397                 return wrong_type_argument(Qfile_readable_p, file);
1398         }
1399
1400         fseek(fp, 0, SEEK_END);
1401         file_size = ftell(fp);
1402         fseek(fp, 0, SEEK_SET);
1403
1404
1405         OpenSSL_add_all_algorithms();
1406         /* ENGINE_load_builtin_engines(); */
1407         /* atm, no support for different engines */
1408         ciph = EVP_get_cipherbyname(
1409                 (char *)string_data(XSYMBOL(cipher)->name));
1410
1411         if (!ciph) {
1412                 EVP_cleanup();
1413                 fclose(fp);
1414                 if (of)
1415                         fclose(of);
1416                 error ("no such cipher");
1417         }
1418
1419         /* now allocate some output buffer externally
1420          * this one has to be at least EVP_CIPHER_block_size bigger
1421          * since block algorithms merely operate blockwise
1422          */
1423         block_len = EVP_CIPHER_block_size(ciph);
1424         if (UNLIKELY(of != NULL)) {
1425                 alloclen = 2048;
1426         } else {
1427                 alloclen = file_size + block_len;
1428         }
1429         XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
1430
1431         TO_EXTERNAL_FORMAT(LISP_STRING, key,
1432                            C_STRING_ALLOCA, key_ext, OSSL_CODING);
1433         TO_EXTERNAL_FORMAT(LISP_STRING, iv,
1434                            C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1435
1436         ciphctx = xnew(EVP_CIPHER_CTX);
1437         EVP_CIPHER_CTX_init(ciphctx);
1438         if (!EVP_EncryptInit(ciphctx, ciph,
1439                              (unsigned char *)key_ext,
1440                              (unsigned char *)iv_ext)) {
1441                 EVP_cleanup();
1442                 fclose(fp);
1443                 if (of)
1444                         fclose(of);
1445                 xfree(ciphctx);
1446                 error("error in EncryptInit");
1447         }
1448
1449         obp = outbuf;
1450         outlen = 0;
1451         do {
1452                 string_len = fread(string_in, 1, 1024, fp);
1453                 if (string_len < 0) {
1454                         EVP_cleanup();
1455                         fclose(fp);
1456                         if (of)
1457                                 fclose(of);
1458                         xfree(ciphctx);
1459                         error("file corrupted");
1460                         return Qnil;
1461                 }
1462
1463                 tmplen = 0;
1464                 if (string_len > 0 &&
1465                     !EVP_EncryptUpdate(ciphctx,
1466                                        obp, &tmplen,
1467                                        string_in, string_len)) {
1468                         EVP_cleanup();
1469                         fclose(fp);
1470                         if (of)
1471                                 fclose(of);
1472                         xfree(ciphctx);
1473                         error("error in EncryptUpdate");
1474                 }
1475
1476                 if (of)
1477                         fwrite(obp, 1, tmplen, of);
1478                 else
1479                         obp += tmplen;
1480
1481                 outlen += tmplen;
1482         } while (string_len > 0);
1483
1484         /* Buffer passed to EVP_EncryptFinal() must be after data just
1485          * encrypted to avoid overwriting it.
1486          */
1487         if (!EVP_EncryptFinal(ciphctx, obp, &tmplen)) {
1488                 EVP_cleanup();
1489                 fclose(fp);
1490                 if (of)
1491                         fclose(of);
1492                 xfree(ciphctx);
1493                 error("error in EncryptFinal");
1494         }
1495
1496         if (of)
1497                 fwrite(obp, 1, tmplen, of);
1498
1499         /* added probable padding space to the length of the output buffer */
1500         outlen += tmplen;
1501         EVP_CIPHER_CTX_cleanup(ciphctx);
1502
1503         if (UNLIKELY(of != NULL)) {
1504                 l_outbuf = outfile;
1505         } else {
1506                 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1507         }
1508         XMALLOC_UNBIND(outbuf, alloclen, speccount);
1509
1510         EVP_cleanup();
1511         xfree(ciphctx);
1512         fclose(fp);
1513         if (of)
1514                 fclose(of);
1515
1516         return l_outbuf;
1517 }
1518 /* testcase:
1519  (setq k (ossl-bytes-to-key 'AES-256-OFB 'SHA1 nil "password" 1))
1520  (ossl-encrypt-file 'AES-256-OFB "~/.gnus" k nil "/tmp/gnus-enc")
1521  (ossl-decrypt-file 'AES-256-OFB "/tmp/gnus-enc" k nil "/tmp/gnus-dec")
1522 */
1523
1524
1525 DEFUN("ossl-decrypt", Fossl_decrypt, 3, 4, 0,   /*
1526 Return the deciphered version of STRING computed by CIPHER under KEY.
1527
1528 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1529 you have compiled. See `ossl-available-ciphers'.
1530
1531 STRING is the text to be decrypted.
1532
1533 KEY should be a key generated suitably for this
1534 cipher, for example by `ossl-bytes-to-key'.
1535
1536 Optional fourth argument IV should be an initialisation vector
1537 suitable for this cipher. Normally the initialisation vector from
1538 KEY's property list is used. However, if IV is
1539 non-nil, use this IV instead.
1540 */
1541       (cipher, string, key, iv))
1542 {
1543         /* buffer for the external string */
1544         char *string_ext;
1545         unsigned int string_len;
1546         /* buffer for the deciphered text */
1547         char *outbuf;
1548         int outlen;
1549         Lisp_Object l_outbuf;
1550         /* buffer for key */
1551         char *key_ext;
1552         /* buffer for iv */
1553         char *iv_ext;
1554
1555         /* declarations for the decipher */
1556         const EVP_CIPHER *ciph;
1557         EVP_CIPHER_CTX *ciphctx;
1558
1559         int tmplen;
1560         int speccount = specpdl_depth();
1561         Charcount alloclen;
1562
1563         /* frob the IV from the plist of key maybe */
1564         if (NILP(iv))
1565                 iv = Fget(key, intern("iv"), Qnil);
1566
1567         CHECK_SYMBOL(cipher);
1568         CHECK_STRING(string);
1569         CHECK_STRING(key);
1570         CHECK_STRING(iv);
1571
1572         if (ossl_check_cipher(cipher) != 0)
1573                 error("use of blacklisted cipher prohibited");
1574
1575         TO_EXTERNAL_FORMAT(LISP_STRING, string,
1576                            C_STRING_ALLOCA, string_ext, OSSL_CODING);
1577         string_len = OSSL_STRING_LENGTH(string);
1578
1579         if (!string_len)
1580                 error ("string must be of non-zero positive length.");
1581
1582         OpenSSL_add_all_algorithms();
1583         /* ENGINE_load_builtin_engines(); */
1584         /* atm, no support for different engines */
1585         ciph = EVP_get_cipherbyname(
1586                 (char *)string_data(XSYMBOL(cipher)->name));
1587
1588         if (!ciph) {
1589                 EVP_cleanup();
1590                 error ("no such cipher");
1591         }
1592
1593         /* now allocate some output buffer externally */
1594         alloclen = XSTRING_LENGTH(string);
1595         XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
1596
1597         TO_EXTERNAL_FORMAT (LISP_STRING, key,
1598                             C_STRING_ALLOCA, key_ext, OSSL_CODING);
1599         TO_EXTERNAL_FORMAT (LISP_STRING, iv,
1600                             C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1601
1602         ciphctx = xnew(EVP_CIPHER_CTX);
1603         EVP_CIPHER_CTX_init(ciphctx);
1604         if (!EVP_DecryptInit(ciphctx, ciph,
1605                              (unsigned char *)key_ext,
1606                              (unsigned char *)iv_ext)) {
1607                 EVP_cleanup();
1608                 xfree(ciphctx);
1609                 error ("error in DecryptInit");
1610         }
1611         if (!EVP_DecryptUpdate(ciphctx,
1612                                (unsigned char *)outbuf, &outlen,
1613                                (unsigned char *)string_ext,string_len)) {
1614                 EVP_cleanup();
1615                 xfree(ciphctx);
1616                 error ("error in DecryptUpdate");
1617         }
1618         /* Buffer passed to EVP_EncryptFinal() must be after data just
1619          * encrypted to avoid overwriting it.
1620          */
1621         if (!EVP_DecryptFinal(ciphctx,
1622                               (unsigned char *)outbuf+outlen, &tmplen)) {
1623                 EVP_cleanup();
1624                 xfree(ciphctx);
1625                 error ("error in DecryptFinal");
1626         }
1627         /* added probable padding space to the length of the output buffer */
1628         outlen += tmplen;
1629         EVP_CIPHER_CTX_cleanup(ciphctx);
1630
1631         l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1632         XMALLOC_UNBIND(outbuf, alloclen, speccount);
1633
1634         EVP_cleanup();
1635         xfree(ciphctx);
1636
1637         return l_outbuf;
1638 }
1639
1640 DEFUN("ossl-decrypt-file", Fossl_decrypt_file, 3, 5, 0, /*
1641 Return the deciphered version of FILE computed by CIPHER under KEY.
1642
1643 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1644 you have compiled. See `ossl-available-ciphers'.
1645
1646 FILE is the file to be decrypted.
1647
1648 Third argument KEY should be a key generated suitably for this
1649 cipher, for example by `ossl-bytes-to-key'.
1650
1651 Optional fourth argument IV should be an initialisation vector
1652 suitable for this cipher. Normally the initialisation vector from
1653 KEY's property list is used. However, if IV is
1654 non-nil, use this IV instead.
1655
1656 Optional fifth argument OUTFILE may specify a file to have the
1657 encrypted data redirected.
1658 */
1659       (cipher, file, key, iv, outfile))
1660 {
1661         /* buffer for the external string */
1662         unsigned char string_in[1024];
1663         ssize_t string_len;
1664         unsigned int block_len;
1665         unsigned long file_size;
1666         /* buffer for the deciphered text */
1667         unsigned char *outbuf;
1668         unsigned char *obp;
1669         int outlen;
1670         Lisp_Object l_outbuf;
1671         /* buffer for key */
1672         char *key_ext;
1673         /* buffer for iv */
1674         char *iv_ext;
1675
1676         /* input file */
1677         FILE *fp;
1678         /* output file */
1679         FILE *of;
1680
1681         /* declarations for the decipher */
1682         const EVP_CIPHER *ciph;
1683         EVP_CIPHER_CTX *ciphctx;
1684
1685         int tmplen;
1686         int speccount = specpdl_depth();
1687         Charcount alloclen;
1688
1689         /* frob the IV from the plist of key maybe */
1690         if (NILP(iv))
1691                 iv = Fget(key, intern("iv"), Qnil);
1692
1693         CHECK_SYMBOL(cipher);
1694         CHECK_STRING(file);
1695         CHECK_STRING(key);
1696         CHECK_STRING(iv);
1697
1698         if (ossl_check_cipher(cipher) != 0)
1699                 error("use of blacklisted cipher prohibited");
1700
1701         if (!NILP(outfile)) {
1702                 CHECK_STRING(outfile);
1703                 outfile = Fexpand_file_name(outfile, Qnil);
1704                 if ((of = fopen((char *)XSTRING_DATA(outfile),"wb")) == NULL)
1705                         return wrong_type_argument(Qfile_writable_p, outfile);
1706         } else {
1707                 of = NULL;
1708         }
1709
1710         file = Fexpand_file_name(file, Qnil);
1711         if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1712             (fseek(fp, 0, SEEK_SET))) {
1713                 if (fp)
1714                         fclose(fp);
1715                 if (of)
1716                         fclose(of);
1717                 return wrong_type_argument(Qfile_readable_p, file);
1718         }
1719
1720         fseek(fp, 0, SEEK_END);
1721         file_size = ftell(fp);
1722         fseek(fp, 0, SEEK_SET);
1723
1724
1725         OpenSSL_add_all_algorithms();
1726         /* ENGINE_load_builtin_engines(); */
1727         /* atm, no support for different engines */
1728         ciph = EVP_get_cipherbyname(
1729                 (char *)string_data(XSYMBOL(cipher)->name));
1730
1731         if (!ciph) {
1732                 EVP_cleanup();
1733                 fclose(fp);
1734                 if (of)
1735                         fclose(of);
1736                 error ("no such cipher");
1737         }
1738
1739         /* now allocate some output buffer externally */
1740         block_len = EVP_CIPHER_block_size(ciph);
1741         if (UNLIKELY(of != NULL)) {
1742                 alloclen = 2048;
1743         } else {
1744                 alloclen = file_size + block_len;
1745         }
1746         XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
1747
1748         TO_EXTERNAL_FORMAT (LISP_STRING, key,
1749                             C_STRING_ALLOCA, key_ext, OSSL_CODING);
1750         TO_EXTERNAL_FORMAT (LISP_STRING, iv,
1751                             C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1752
1753         ciphctx = xnew(EVP_CIPHER_CTX);
1754         EVP_CIPHER_CTX_init(ciphctx);
1755         if (!EVP_DecryptInit(ciphctx, ciph,
1756                              (unsigned char *)key_ext,
1757                              (unsigned char *)iv_ext)) {
1758                 EVP_cleanup();
1759                 fclose(fp);
1760                 if (of)
1761                         fclose(of);
1762                 xfree(ciphctx);
1763                 error ("error in DecryptInit");
1764         }
1765
1766         obp = outbuf;
1767         outlen = 0;
1768         do {
1769                 string_len = fread(string_in, 1, 1024, fp);
1770                 if (string_len < 0) {
1771                         EVP_cleanup();
1772                         fclose(fp);
1773                         if (of)
1774                                 fclose(of);
1775                         xfree(ciphctx);
1776                         error("file corrupted");
1777                         return Qnil;
1778                 }
1779
1780                 tmplen = 0;
1781                 if (string_len > 0 &&
1782                     !EVP_DecryptUpdate(ciphctx,
1783                                        obp, &tmplen,
1784                                        string_in, string_len)) {
1785                         EVP_cleanup();
1786                         fclose(fp);
1787                         if (of)
1788                                 fclose(of);
1789                         xfree(ciphctx);
1790                         error ("error in DecryptUpdate");
1791                 }
1792
1793                 if (of)
1794                         fwrite(obp, 1, tmplen, of);
1795                 else
1796                         obp += tmplen;
1797
1798                 outlen += tmplen;
1799         } while (string_len > 0);
1800
1801         /* Buffer passed to EVP_EncryptFinal() must be after data just
1802          * encrypted to avoid overwriting it.
1803          */
1804         if (!EVP_DecryptFinal(ciphctx, obp, &tmplen)) {
1805                 EVP_cleanup();
1806                 fclose(fp);
1807                 if (of)
1808                         fclose(of);
1809                 xfree(ciphctx);
1810                 error ("error in DecryptFinal");
1811         }
1812
1813         if (of)
1814                 fwrite(obp, 1, tmplen, of);
1815
1816         /* added probable padding space to the length of the output buffer */
1817         outlen += tmplen;
1818         EVP_CIPHER_CTX_cleanup(ciphctx);
1819
1820         if (UNLIKELY(of != NULL)) {
1821                 l_outbuf = outfile;
1822         } else {
1823                 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1824         }
1825         XMALLOC_UNBIND(outbuf, alloclen, speccount);
1826
1827         EVP_cleanup();
1828         xfree(ciphctx);
1829         fclose(fp);
1830         if (of)
1831                 fclose(of);
1832
1833         return l_outbuf;
1834 }
1835
1836
1837 /*
1838  *
1839  * ASYMMETRIC CIPHER
1840  *
1841  */
1842 /* This is an opaque object for storing PKEYs in lisp */
1843 Lisp_Object Qevp_pkeyp;
1844
1845 static Lisp_Object
1846 mark_evp_pkey(Lisp_Object obj)
1847 {
1848         /* avoid some warning */
1849         if (obj);
1850         return Qnil;
1851 }
1852
1853 static void
1854 print_evp_pkey(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1855 {
1856         EVP_PKEY *pkey;
1857         X509 *x509;
1858
1859         pkey = XEVPPKEY(obj)->evp_pkey;
1860         x509 = XEVPPKEY(obj)->x509;
1861
1862         write_c_string("#<OpenSSL", printcharfun);
1863
1864         if (x509) {
1865                 X509_NAME *iss = X509_get_issuer_name(x509);
1866                 X509_NAME *sub = X509_get_subject_name(x509);
1867                 write_c_string(" X509 Certificate", printcharfun);
1868                 write_c_string(" iss:", printcharfun);
1869                 write_c_string(X509_NAME_oneline(sub, NULL, 0), printcharfun);
1870                 write_c_string(" sub:", printcharfun);
1871                 write_c_string(X509_NAME_oneline(iss, NULL, 0), printcharfun);
1872         }
1873
1874         if (pkey) {
1875                 if (x509)
1876                         write_c_string(";", printcharfun);
1877
1878                 if (rsa_pkey_p(pkey))
1879                         write_c_string(" RSA", printcharfun);
1880                 else if (dsa_pkey_p(pkey))
1881                         write_c_string(" DSA", printcharfun);
1882                 else if (ec_pkey_p(pkey))
1883                         write_c_string(" EC", printcharfun);
1884
1885                 if (ossl_pkey_has_private_data(pkey))
1886                         write_c_string(" private/public key", printcharfun);
1887                 else if (ossl_pkey_has_public_data(pkey))
1888                         write_c_string(" public key", printcharfun);
1889                 else
1890                         write_c_string(" empty key", printcharfun);
1891
1892                 if (EVP_PKEY_size(pkey) > 0) {
1893                         write_fmt_str(printcharfun, ", size %d", EVP_PKEY_size(pkey)*8);
1894                 }
1895         }
1896
1897         write_c_string(">", printcharfun);
1898
1899         /* avoid some warning */
1900         if (escapeflag);
1901 }
1902
1903 static Lisp_EVP_PKEY *
1904 allocate_evp_pkey(void)
1905 {
1906         Lisp_EVP_PKEY *evp_pkey =
1907                 alloc_lcrecord_type(Lisp_EVP_PKEY, &lrecord_evp_pkey);
1908         evp_pkey->evp_pkey = NULL;
1909         evp_pkey->x509 = NULL;
1910         return evp_pkey;
1911 }
1912
1913 static void
1914 finalise_evp_pkey(void *header, int for_disksave)
1915 {
1916         Lisp_EVP_PKEY *evp_pkey = (Lisp_EVP_PKEY *) header;
1917
1918         if (evp_pkey->evp_pkey) {
1919                 EVP_PKEY_free(evp_pkey->evp_pkey);
1920                 evp_pkey->evp_pkey = NULL;
1921         }
1922         if (evp_pkey->x509) {
1923                 X509_free(evp_pkey->x509);
1924                 evp_pkey->x509 = NULL;
1925         }
1926
1927         /* avoid some warning */
1928         if (for_disksave);
1929 }
1930
1931 DEFINE_LRECORD_IMPLEMENTATION("evp_pkey", evp_pkey,
1932                               mark_evp_pkey, print_evp_pkey,
1933                               finalise_evp_pkey,
1934                               NULL, NULL, 0,
1935                               Lisp_EVP_PKEY);
1936
1937 static Lisp_Object
1938 make_evp_pkey(EVP_PKEY *pkey, X509 *x509)
1939 {
1940         Lisp_EVP_PKEY *lisp_pkey = allocate_evp_pkey();
1941
1942         lisp_pkey->evp_pkey = pkey;
1943         lisp_pkey->x509 = x509;
1944
1945         return wrap_evppkey(lisp_pkey);
1946 }
1947
1948 static Lisp_Object
1949 make_evp_pkey_pk(EVP_PKEY *pkey)
1950 {
1951         return make_evp_pkey(pkey, NULL);
1952 }
1953
1954 static Lisp_Object
1955 make_evp_pkey_x509(X509 *x509)
1956 {
1957         return make_evp_pkey(X509_get_pubkey(x509), x509);
1958 }
1959
1960 DEFUN("ossl-pkey-p", Fossl_pkey_p, 1, 1, 0, /*
1961 Return t iff OBJECT is a pkey, nil otherwise.
1962 */
1963       (object))
1964 {
1965         if (EVPPKEYP(object))
1966                 return Qt;
1967         else
1968                 return Qnil;
1969 }
1970
1971 DEFUN("ossl-pkey-size", Fossl_pkey_size, 1, 1, 0, /*
1972 Return the size a public key PKEY in bits.
1973 */
1974       (pkey))
1975 {
1976         EVP_PKEY *pk;
1977
1978         CHECK_EVPPKEY(pkey);
1979
1980         pk = (XEVPPKEY(pkey))->evp_pkey;
1981
1982         return make_int(EVP_PKEY_size(pk)*8);
1983 }
1984
1985 int
1986 ossl_pkey_has_public_data(EVP_PKEY *pkey)
1987 {
1988         if (rsa_pkey_p(pkey)) {
1989 #ifndef OPENSSL_NO_RSA
1990                 return rsa_pkey_has_public_data((pkey->pkey).rsa);
1991 #else
1992                 return 0;
1993 #endif
1994         } else if (dsa_pkey_p(pkey)) {
1995 #ifndef OPENSSL_NO_DSA
1996                 return dsa_pkey_has_public_data((pkey->pkey).dsa);
1997 #else
1998                 return 0;
1999 #endif
2000         } else if (ec_pkey_p(pkey)) {
2001 #ifndef OPENSSL_NO_EC
2002                 return ec_pkey_has_public_data((pkey->pkey).ec);
2003 #else
2004                 return 0;
2005 #endif
2006         } else if (dh_pkey_p(pkey)) {
2007 #ifndef OPENSSL_NO_DH
2008                 return dh_pkey_has_public_data((pkey->pkey).dh);
2009 #else
2010                 return 0;
2011 #endif
2012         } else
2013                 return 0;
2014 }
2015 int
2016 ossl_pkey_has_private_data(EVP_PKEY *pkey)
2017 {
2018         if (rsa_pkey_p(pkey)) {
2019 #ifndef OPENSSL_NO_RSA
2020                 return rsa_pkey_has_private_data((pkey->pkey).rsa);
2021 #else
2022                 return 0;
2023 #endif
2024         } else if (dsa_pkey_p(pkey)) {
2025 #ifndef OPENSSL_NO_DSA
2026                 return dsa_pkey_has_private_data((pkey->pkey).dsa);
2027 #else
2028                 return 0;
2029 #endif
2030         } else if (ec_pkey_p(pkey)) {
2031 #ifndef OPENSSL_NO_EC
2032                 return ec_pkey_has_private_data((pkey->pkey).ec);
2033 #else
2034                 return 0;
2035 #endif
2036         } else if (dh_pkey_p(pkey)) {
2037 #ifndef OPENSSL_NO_DH
2038                 return dh_pkey_has_private_data((pkey->pkey).dh);
2039 #else
2040                 return 0;
2041 #endif
2042         } else
2043                 return 0;
2044 }
2045
2046 DEFUN("ossl-pkey-private-p", Fossl_pkey_private_p, 1, 1, 0, /*
2047 Return non-nil if PKEY contains private data.
2048
2049 This function is not native OpenSSL.
2050 */
2051       (pkey))
2052 {
2053         EVP_PKEY *pk;
2054
2055         if (!(EVPPKEYP(pkey)))
2056                 return Qnil;
2057
2058         pk = (XEVPPKEY(pkey))->evp_pkey;
2059
2060         if (ossl_pkey_has_private_data(pk))
2061                 return Qt;
2062
2063         return Qnil;
2064 }
2065
2066 DEFUN("ossl-pkey-get-public", Fossl_pkey_get_public, 1, 1, 0, /*
2067 Return a copy of PKEY stripped by the private data.
2068
2069 This function is not native OpenSSL.
2070 */
2071       (pkey))
2072 {
2073         EVP_PKEY *pk;
2074         EVP_PKEY *pkout;
2075
2076         CHECK_EVPPKEY(pkey);
2077
2078         pk = (XEVPPKEY(pkey))->evp_pkey;
2079         if (!(ossl_pkey_has_public_data(pk)))
2080                 error ("key must have public data");
2081
2082         pkout = EVP_PKEY_new();
2083         if (rsa_pkey_p(pk)) {
2084 #ifndef OPENSSL_NO_RSA
2085                 EVP_PKEY_assign_RSA(pkout, RSAPublicKey_dup((pk->pkey).rsa));
2086 #endif
2087         } else if (dsa_pkey_p(pk)) {
2088 #ifndef OPENSSL_NO_DSA
2089                 EVP_PKEY_assign_DSA(pkout, dsa_get_public(pk));
2090 #endif
2091         } else if (ec_pkey_p(pk)) {
2092 #ifndef OPENSSL_NO_EC
2093                 EVP_PKEY_assign_EC_KEY(pkout, ec_get_public(pk));
2094 #endif
2095         } else
2096                 error ("no method to strip private data yet");
2097
2098         return make_evp_pkey_pk(pkout);
2099 }
2100
2101 /* RSA */
2102 int
2103 rsa_pkey_p(EVP_PKEY *pkey)
2104 {
2105         int type;
2106
2107         type = EVP_PKEY_type(pkey->type);
2108
2109 #ifndef OPENSSL_NO_RSA
2110         return ((type == EVP_PKEY_RSA) ||
2111                 (type == EVP_PKEY_RSA2));
2112 #else
2113         return 0;
2114 #endif
2115 }
2116 #ifndef OPENSSL_NO_RSA
2117 int
2118 rsa_pkey_has_public_data(RSA *rsakey)
2119 {
2120         return (!(rsakey->n == NULL) &&
2121                 !(rsakey->e == NULL));
2122 }
2123 int
2124 rsa_pkey_has_private_data(RSA *rsakey)
2125 {
2126         return (rsa_pkey_has_public_data(rsakey) &&
2127                 !(rsakey->d == NULL));
2128 }
2129
2130 DEFUN("ossl-rsa-generate-key", Fossl_rsa_generate_key, 2, 2, 0, /*
2131 Return an RSA public key with of length BITS and exponent EXPO.
2132 */
2133       (bits, expo))
2134 {
2135         EVP_PKEY *pkey;
2136         RSA *rsakey;
2137
2138         CHECK_NATNUM(bits);
2139         CHECK_NATNUM(expo);
2140
2141
2142         if (!XINT(bits))
2143                 error ("modulus size must be a non-zero positive integer");
2144         if (!(XINT(expo) % 2))
2145                 error ("exponent must be an odd positive integer");
2146
2147         pkey = EVP_PKEY_new();
2148         rsakey = RSA_generate_key(XINT(bits), XINT(expo), NULL, NULL);
2149         EVP_PKEY_assign_RSA(pkey, rsakey);
2150
2151         return make_evp_pkey_pk(pkey);
2152 }
2153
2154 DEFUN("ossl-rsa-pkey-p", Fossl_rsa_pkey_p, 1, 1, 0, /*
2155 Return t iff PKEY is of RSA type.
2156 */
2157       (pkey))
2158 {
2159         EVP_PKEY *pk;
2160
2161         if (!EVPPKEYP(pkey))
2162                 return Qnil;
2163
2164         pk = (XEVPPKEY(pkey))->evp_pkey;
2165
2166         if (rsa_pkey_p(pk))
2167                 return Qt;
2168         else
2169                 return Qnil;
2170 }
2171
2172 DEFUN("ossl-rsa-subkey-p", Fossl_rsa_subkey_p, 2, 2, 0, /*
2173 Return t iff PKEY1 is a subkey of PKEY2.
2174 I.e. if PKEY1 has the same public key data as PKEY2 and
2175 PKEY2 has all private data.
2176
2177 This function is not native OpenSSL.
2178 */
2179       (pkey1, pkey2))
2180 {
2181         EVP_PKEY *pk1;
2182         EVP_PKEY *pk2;
2183         RSA *rk1;
2184         RSA *rk2;
2185
2186         CHECK_EVPPKEY(pkey1);
2187         CHECK_EVPPKEY(pkey2);
2188
2189         pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2190         pk2 = (XEVPPKEY(pkey2))->evp_pkey;
2191
2192         /* perform a type check first */
2193         if (!rsa_pkey_p(pk1))
2194                 error ("pkey1 must be of RSA type");
2195         if (!rsa_pkey_p(pk2))
2196                 error ("pkey2 must be of RSA type");
2197
2198         rk1 = (pk1->pkey).rsa;
2199         rk2 = (pk2->pkey).rsa;
2200
2201         if (rsa_pkey_has_private_data(rk2) &&
2202             rsa_pkey_has_public_data(rk1) &&
2203             (!BN_cmp(rk1->n, rk2->n)) &&
2204             (!BN_cmp(rk1->e, rk2->e)))
2205                 return Qt;
2206         else
2207                 return Qnil;
2208 }
2209 #endif /* OPENSSL_NO_RSA */
2210
2211
2212 /* DSA */
2213 int
2214 dsa_pkey_p(EVP_PKEY *pkey)
2215 {
2216         int type;
2217
2218         type = EVP_PKEY_type(pkey->type);
2219
2220 #ifndef OPENSSL_NO_DSA
2221         return ((type == EVP_PKEY_DSA) ||
2222                 (type == EVP_PKEY_DSA1) ||
2223                 (type == EVP_PKEY_DSA2) ||
2224                 (type == EVP_PKEY_DSA3) ||
2225                 (type == EVP_PKEY_DSA4));
2226 #else
2227         return 0;
2228 #endif
2229 }
2230 #ifndef OPENSSL_NO_DSA
2231 int
2232 dsa_pkey_has_public_data(DSA *dsakey)
2233 {
2234         return (!(dsakey->p == NULL) &&
2235                 !(dsakey->q == NULL) &&
2236                 !(dsakey->g == NULL) &&
2237                 !(dsakey->pub_key == NULL));
2238 }
2239 int
2240 dsa_pkey_has_private_data(DSA *dsakey)
2241 {
2242         return (dsa_pkey_has_public_data(dsakey) &&
2243                 !(dsakey->priv_key == NULL));
2244 }
2245
2246 DEFUN("ossl-dsa-generate-key", Fossl_dsa_generate_key, 1, 2, 0, /*
2247 Return a DSA public key with of length BITS seeded with (optional) SEED.
2248 */
2249       (bits, seed))
2250 {
2251         EVP_PKEY *pkey;
2252         DSA *dsakey;
2253         char *seed_ext;
2254         int seed_len;
2255         int counter_ret;
2256         unsigned_long h_ret;
2257
2258
2259         CHECK_NATNUM(bits);
2260
2261
2262         if (!XINT(bits))
2263                 error ("prime number size must be a non-zero positive integer");
2264
2265         if (NILP(seed)) {
2266                 seed_ext = NULL;
2267                 seed_len = 0;
2268         } else {
2269                 CHECK_STRING(seed);
2270                 TO_EXTERNAL_FORMAT (LISP_STRING, seed,
2271                                     C_STRING_ALLOCA, seed_ext, OSSL_CODING);
2272                 seed_len = OSSL_STRING_LENGTH(seed);
2273         }
2274
2275         pkey = EVP_PKEY_new();
2276         dsakey = DSA_generate_parameters(XINT(bits),
2277                                          (unsigned char*)seed_ext, seed_len,
2278                                          &counter_ret, &h_ret,
2279                                          NULL, NULL);
2280         if (!DSA_generate_key(dsakey))
2281                 error ("error during generation of DSA key");
2282
2283         EVP_PKEY_assign_DSA(pkey, dsakey);
2284
2285         return make_evp_pkey_pk(pkey);
2286 }
2287
2288 DEFUN("ossl-dsa-pkey-p", Fossl_dsa_pkey_p, 1, 1, 0, /*
2289 Return t iff PKEY is of DSA type.
2290 */
2291       (pkey))
2292 {
2293         EVP_PKEY *pk;
2294
2295         if (!EVPPKEYP(pkey))
2296                 return Qnil;
2297
2298         pk = (XEVPPKEY(pkey))->evp_pkey;
2299         if (dsa_pkey_p(pk))
2300                 return Qt;
2301         else
2302                 return Qnil;
2303 }
2304
2305 DSA *
2306 dsa_get_public(EVP_PKEY *pk)
2307 {
2308         DSA *key;
2309
2310         key = DSA_new();
2311         memcpy(key, (pk->pkey).dsa, sizeof(DSA));
2312
2313         /* now kill the private data */
2314         key->priv_key = NULL;
2315
2316         return key;
2317 }
2318
2319 DEFUN("ossl-dsa-subkey-p", Fossl_dsa_subkey_p, 2, 2, 0, /*
2320 Return t iff PKEY1 is a subkey of PKEY2.
2321 I.e. if PKEY1 has the same public key data as PKEY2 and
2322 PKEY2 has all private data.
2323
2324 This function is not native OpenSSL.
2325 */
2326       (pkey1, pkey2))
2327 {
2328         EVP_PKEY *pk1;
2329         EVP_PKEY *pk2;
2330         DSA *dk1;
2331         DSA *dk2;
2332
2333         CHECK_EVPPKEY(pkey1);
2334         CHECK_EVPPKEY(pkey2);
2335
2336         pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2337         pk2 = (XEVPPKEY(pkey2))->evp_pkey;
2338
2339         /* perform a type check first */
2340         if (!dsa_pkey_p(pk1))
2341                 error ("pkey1 must be of DSA type");
2342         if (!dsa_pkey_p(pk2))
2343                 error ("pkey2 must be of DSA type");
2344
2345         dk1 = (pk1->pkey).dsa;
2346         dk2 = (pk2->pkey).dsa;
2347
2348         if (dsa_pkey_has_private_data(dk2) &&
2349             dsa_pkey_has_public_data(dk1) &&
2350             (!BN_cmp(dk1->p, dk2->p)) &&
2351             (!BN_cmp(dk1->q, dk2->q)) &&
2352             (!BN_cmp(dk1->g, dk2->g)) &&
2353             (!BN_cmp(dk1->pub_key, dk2->pub_key)))
2354                 return Qt;
2355         else
2356                 return Qnil;
2357 }
2358 #endif /* OPENSSL_NO_DSA */
2359
2360
2361 /* EC */
2362 int
2363 ec_pkey_p(EVP_PKEY *pkey)
2364 {
2365         int type;
2366
2367         type = EVP_PKEY_type(pkey->type);
2368
2369 #ifndef OPENSSL_NO_EC
2370         return (type == EVP_PKEY_EC);
2371 #else
2372         return 0;
2373 #endif
2374 }
2375 #ifndef OPENSSL_NO_EC
2376 int
2377 ec_pkey_has_public_data(EC_KEY *ec_key)
2378 {
2379         return (!(EC_KEY_get0_group(ec_key) == NULL) &&
2380                 !(EC_KEY_get0_public_key(ec_key) == NULL));
2381 }
2382 int
2383 ec_pkey_has_private_data(EC_KEY *ec_key)
2384 {
2385         return (ec_pkey_has_public_data(ec_key) &&
2386                 !(EC_KEY_get0_private_key(ec_key) == NULL));
2387 }
2388
2389 DEFUN("ossl-ec-available-curves", Fossl_ec_available_curves, 0, 0, 0, /*
2390 Return a list of builtin elliptic curves.
2391 */
2392       ())
2393 {
2394         EC_builtin_curve *curves = NULL;
2395         size_t crv_len = 0, n = 0;
2396         Lisp_Object lcurves;
2397
2398         lcurves = Qnil;
2399
2400         crv_len = EC_get_builtin_curves(NULL, 0);
2401         curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
2402
2403         if (curves == NULL)
2404                 error ("no curves defined");
2405
2406         if (!EC_get_builtin_curves(curves, crv_len)) {
2407                 OPENSSL_free(curves);
2408                 error ("error during initialisation of curves");
2409         }
2410
2411         for (n = 0; n < crv_len; n++) {
2412                 int nid = curves[n].nid;
2413                 lcurves = Fcons(intern(OBJ_nid2sn(nid)), lcurves);
2414         }
2415
2416         OPENSSL_free(curves);
2417
2418         return lcurves;
2419 }
2420
2421 int
2422 ec_curve_by_name(char *name)
2423 {
2424         return OBJ_sn2nid(name);
2425 }
2426
2427 DEFUN("ossl-ec-generate-key", Fossl_ec_generate_key, 1, 1, 0, /*
2428 Return a EC public key on CURVE.
2429 CURVE may be any symbol from `ossl-ec-available-curves'.
2430
2431 At the moment we do not support creating custom curves.
2432 */
2433       (curve))
2434 {
2435         EVP_PKEY *pkey;
2436         EC_KEY *eckey;
2437
2438         CHECK_SYMBOL(curve);
2439
2440         pkey = EVP_PKEY_new();
2441         eckey = EC_KEY_new_by_curve_name(
2442                 ec_curve_by_name((char *)string_data(XSYMBOL(curve)->name)));
2443
2444         if (eckey == NULL) {
2445                 error ("no such curve");
2446         }
2447
2448         if (!EC_KEY_generate_key(eckey))
2449                 error ("error during generation of EC key");
2450
2451         EVP_PKEY_assign_EC_KEY(pkey, eckey);
2452
2453         return make_evp_pkey_pk(pkey);
2454 }
2455
2456 DEFUN("ossl-ec-pkey-p", Fossl_ec_pkey_p, 1, 1, 0, /*
2457 Return t iff PKEY is of EC type.
2458 */
2459       (pkey))
2460 {
2461         EVP_PKEY *pk;
2462         int type;
2463
2464         if (!EVPPKEYP(pkey))
2465                 return Qnil;
2466
2467         pk = (XEVPPKEY(pkey))->evp_pkey;
2468         type = EVP_PKEY_type(pk->type);
2469         if (type == EVP_PKEY_EC)
2470                 return Qt;
2471         else
2472                 return Qnil;
2473 }
2474
2475 EC_KEY *
2476 ec_get_public(EVP_PKEY *pk)
2477 {
2478         EC_KEY *key;
2479
2480         key = EC_KEY_dup((pk->pkey).ec);
2481
2482         /* now kill the private data */
2483         EC_KEY_set_private_key(key, NULL);
2484
2485         return key;
2486 }
2487 #endif /* OPENSSL_NO_EC */
2488
2489
2490 /* DH */
2491 int
2492 dh_pkey_p(EVP_PKEY *pkey)
2493 {
2494         int type;
2495
2496         type = EVP_PKEY_type(pkey->type);
2497
2498 #ifndef OPENSSL_NO_DH
2499         return (type == EVP_PKEY_DH);
2500 #else
2501         return 0;
2502 #endif
2503 }
2504 #ifndef OPENSSL_NO_DH
2505 int
2506 dh_pkey_has_public_data(DH *dhkey)
2507 {
2508         return (!(dhkey->p == NULL) &&
2509                 !(dhkey->g == NULL) &&
2510                 !(dhkey->pub_key == NULL));
2511 }
2512 int
2513 dh_pkey_has_private_data(DH *dhkey)
2514 {
2515         return (dh_pkey_has_public_data(dhkey) &&
2516                 !(dhkey->priv_key == NULL));
2517 }
2518
2519 DEFUN("ossl-dh-pkey-p", Fossl_dh_pkey_p, 1, 1, 0, /*
2520 Return t iff PKEY is of DH type.
2521 */
2522       (pkey))
2523 {
2524         EVP_PKEY *pk;
2525
2526         if (!EVPPKEYP(pkey))
2527                 return Qnil;
2528
2529         pk = (XEVPPKEY(pkey))->evp_pkey;
2530
2531         if (dh_pkey_p(pk))
2532                 return Qt;
2533         else
2534                 return Qnil;
2535 }
2536
2537 #endif /* OPENSSL_NO_DH */
2538
2539
2540 /* more general access functions */
2541 DEFUN("ossl-seal", Fossl_seal, 3, 3, 0, /*
2542 Return an envelope derived from encrypting STRING by CIPHER under PKEY
2543 with the hybrid technique.
2544
2545 That is, create a random key/iv pair for the symmetric encryption with
2546 CIPHER and encrypt that key/iv asymmetrically with the provided public
2547 key.
2548
2549 The envelope returned is a list
2550 \(encrypted_string encrypted_key encrypted_iv\)
2551 where
2552 `encrypted_string' is the (symmetrically) encrypted message
2553 `encrypted_key' is the (asymmetrically) encrypted random key
2554 `encrypted_iv' is the (asymmetrically) encrypted random iv
2555
2556 Note: You probably want to put a wrapping encoder function
2557 (like `base16-encode-string') around it, since this function
2558 returns binary string data.
2559 */
2560       (cipher, string, pkey))
2561 {
2562         /* declarations for the cipher */
2563         const EVP_CIPHER *ciph;
2564         EVP_CIPHER_CTX ciphctx;
2565         /* declarations for the pkey */
2566         EVP_PKEY *pk[1];
2567         int npubk;
2568         unsigned char *ekey;
2569         int ekey_len;
2570         Lisp_Object l_ekey;
2571         /* buffer for the generated IV */
2572         char iv[EVP_MAX_IV_LENGTH];
2573         Lisp_Object l_iv;
2574         /* buffer for output */
2575         unsigned char *outbuf;
2576         unsigned int outlen;
2577         Lisp_Object l_outbuf;
2578         /* buffer for external string data */
2579         char *string_ext;
2580         int string_len;
2581
2582         int tmplen;
2583
2584
2585         CHECK_SYMBOL(cipher);
2586         CHECK_STRING(string);
2587         CHECK_EVPPKEY(pkey);
2588
2589
2590         if (ossl_check_cipher(cipher) != 0)
2591                 error("use of blacklisted cipher prohibited");
2592
2593         pk[0] = (XEVPPKEY(pkey))->evp_pkey;
2594         if (!ossl_pkey_has_public_data(pk[0])) {
2595                 error ("cannot seal, key has no public key data");
2596         }
2597         npubk = 1;
2598
2599         TO_EXTERNAL_FORMAT (LISP_STRING, string,
2600                             C_STRING_ALLOCA, string_ext, OSSL_CODING);
2601         string_len = OSSL_STRING_LENGTH(string);
2602
2603         OpenSSL_add_all_algorithms();
2604         ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2605
2606         if (!ciph) {
2607                 EVP_cleanup();
2608                 error ("no such cipher");
2609                 return Qnil;
2610         }
2611
2612         /* alloc ekey buffer */
2613         ekey = (unsigned char*)xmalloc_atomic(EVP_PKEY_size(pk[0]));
2614
2615         /* now allocate some output buffer externally
2616          * this one has to be at least EVP_CIPHER_block_size bigger
2617          * since block algorithms merely operate blockwise
2618          */
2619         outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string) +
2620                                                  EVP_CIPHER_block_size(ciph));
2621
2622         EVP_CIPHER_CTX_init(&ciphctx);
2623         if (!(EVP_SealInit(&ciphctx, ciph,
2624                            &ekey, &ekey_len,
2625                            (unsigned char *)&iv,
2626                            (EVP_PKEY **)&pk, npubk)==npubk)) {
2627                 EVP_cleanup();
2628                 xfree(outbuf);
2629                 xfree(ekey);
2630                 error ("error in SealInit");
2631                 return Qnil;
2632         }
2633         if (!EVP_SealUpdate(&ciphctx, outbuf, (int *)&outlen,
2634                             (unsigned char*)string_ext, string_len)) {
2635                 EVP_cleanup();
2636                 xfree(outbuf);
2637                 xfree(ekey);
2638                 error ("error in SealUpdate");
2639                 return Qnil;
2640         }
2641         if (!EVP_SealFinal(&ciphctx, (unsigned char*)outbuf+outlen, &tmplen)) {
2642                 EVP_cleanup();
2643                 xfree(outbuf);
2644                 xfree(ekey);
2645                 error ("error in SealFinal");
2646                 return Qnil;
2647         }
2648         /* added probable padding space to the length of the output buffer */
2649         outlen += tmplen;
2650         EVP_CIPHER_CTX_cleanup(&ciphctx);
2651
2652         l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2653         l_ekey = make_ext_string((char *)ekey, ekey_len, OSSL_CODING);
2654         l_iv = make_ext_string(iv,EVP_CIPHER_iv_length(ciph), OSSL_CODING);
2655         xfree(outbuf);
2656         xfree(ekey);
2657         EVP_cleanup();
2658
2659         return list3(l_outbuf, l_ekey, l_iv);
2660 }
2661
2662
2663 DEFUN("ossl-open", Fossl_open, 4, 5, 0, /*
2664 Return the deciphered message STRING from an envelope
2665 obtained by `ossl-seal'.
2666
2667 CIPHER is the cipher to use (the same as in `ossl-seal')
2668 STRING is the encrypted message
2669 PKEY is the private key
2670 EKEY is the encrypted random key
2671 EIV is the encrypted iv
2672 */
2673       (cipher, string, pkey, ekey, eiv))
2674 {
2675         /* declarations for the cipher */
2676         const EVP_CIPHER *ciph;
2677         EVP_CIPHER_CTX ciphctx;
2678         /* declarations for the pkey */
2679         EVP_PKEY *pk;
2680         /* buffer for external ekey data */
2681         char *ekey_ext;
2682         int ekey_len;
2683         /* buffer for external eiv data */
2684         char *eiv_ext;
2685         /* buffer for output */
2686         unsigned char *outbuf;
2687         unsigned int outlen;
2688         Lisp_Object l_outbuf;
2689         /* buffer for external string data */
2690         char *string_ext;
2691         int string_len;
2692
2693         int tmplen;
2694
2695
2696         CHECK_SYMBOL(cipher);
2697         CHECK_STRING(string);
2698         CHECK_EVPPKEY(pkey);
2699         CHECK_STRING(ekey);
2700
2701
2702         if (ossl_check_cipher(cipher) != 0)
2703                 error("use of blacklisted cipher prohibited");
2704
2705         pk = (XEVPPKEY(pkey))->evp_pkey;
2706         if (!ossl_pkey_has_private_data(pk))
2707                 error ("cannot open, key has no private key data");
2708
2709         TO_EXTERNAL_FORMAT (LISP_STRING, string,
2710                             C_STRING_ALLOCA, string_ext, OSSL_CODING);
2711         string_len = OSSL_STRING_LENGTH(string);
2712         TO_EXTERNAL_FORMAT (LISP_STRING, ekey,
2713                             C_STRING_ALLOCA, ekey_ext, OSSL_CODING);
2714         ekey_len = OSSL_STRING_LENGTH(ekey);
2715
2716         OpenSSL_add_all_algorithms();
2717         ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2718
2719         if (!ciph) {
2720                 EVP_cleanup();
2721                 error ("no such cipher");
2722                 return Qnil;
2723         }
2724
2725         if (NILP(eiv)) {
2726                 eiv_ext = NULL;
2727         } else {
2728                 CHECK_STRING(eiv);
2729                 TO_EXTERNAL_FORMAT (LISP_STRING, eiv,
2730                                     C_STRING_ALLOCA, eiv_ext, OSSL_CODING);
2731         }
2732
2733         /* now allocate some output buffer externally */
2734         outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string));
2735
2736         EVP_CIPHER_CTX_init(&ciphctx);
2737         if (!EVP_OpenInit(&ciphctx, ciph,
2738                           (unsigned char*)ekey_ext,
2739                           (unsigned int)ekey_len,
2740                           (unsigned char*)eiv_ext, pk)) {
2741                 EVP_cleanup();
2742                 xfree(outbuf);
2743                 error ("error in OpenInit");
2744                 return Qnil;
2745         }
2746         if (!EVP_OpenUpdate(&ciphctx, outbuf, (int *)&outlen,
2747                             (unsigned char*)string_ext,
2748                             (unsigned int)string_len)) {
2749                 EVP_cleanup();
2750                 xfree(outbuf);
2751                 error ("error in OpenUpdate");
2752                 return Qnil;
2753         }
2754         if (!EVP_OpenFinal(&ciphctx, outbuf+outlen, &tmplen)) {
2755                 EVP_cleanup();
2756                 xfree(outbuf);
2757                 error ("error in OpenFinal");
2758                 return Qnil;
2759         }
2760         /* added probable padding space to the length of the output buffer */
2761         outlen += tmplen;
2762         EVP_CIPHER_CTX_cleanup(&ciphctx);
2763
2764         l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2765         xfree(outbuf);
2766
2767         EVP_cleanup();
2768
2769         return l_outbuf;
2770 }
2771
2772
2773 DEFUN("ossl-sign", Fossl_sign, 3, 3, 0, /*
2774 Return a signature obtained by signing STRING under DIGEST with PKEY.
2775
2776 That is, hash the message STRING with the message digest DIGEST and
2777 encrypt the result with the private key PKEY.
2778
2779 Note: Due to some relationship between the public key system and the
2780 message digest you cannot use every digest algorithm with every
2781 private key type.
2782 The most certain results will be achieved using
2783 RSA keys with RSA-* digests, DSA keys with DSA-* digests.
2784
2785 See `ossl-available-digests'.
2786
2787 Note: You probably want to put a wrapping encoder function
2788 (like `base16-encode-string') around it, since this returns
2789 binary string data.
2790 */
2791       (digest, string, pkey))
2792 {
2793         /* declarations for the cipher */
2794         const EVP_MD *md;
2795         EVP_MD_CTX mdctx;
2796         /* declarations for the pkey */
2797         EVP_PKEY *pk;
2798         /* buffer for output */
2799         unsigned char *outbuf;
2800         unsigned int outlen;
2801         Lisp_Object l_outbuf;
2802         /* buffer for external string data */
2803         char *string_ext;
2804         int string_len;
2805
2806
2807         CHECK_SYMBOL(digest);
2808         CHECK_STRING(string);
2809         CHECK_EVPPKEY(pkey);
2810
2811
2812         pk = (XEVPPKEY(pkey))->evp_pkey;
2813         if (!ossl_pkey_has_private_data(pk)) {
2814                 error ("cannot sign, key has no private key data");
2815         }
2816
2817         TO_EXTERNAL_FORMAT (LISP_STRING, string,
2818                             C_STRING_ALLOCA, string_ext, OSSL_CODING);
2819         string_len = OSSL_STRING_LENGTH(string);
2820
2821         OpenSSL_add_all_algorithms();
2822         md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2823
2824         if (!md) {
2825                 EVP_cleanup();
2826                 error ("no such digest");
2827                 return Qnil;
2828         }
2829
2830         /* now allocate some output buffer externally */
2831         outbuf = (unsigned char *)xmalloc_atomic(EVP_PKEY_size(pk));
2832
2833         EVP_MD_CTX_init(&mdctx);
2834         if (!(EVP_SignInit(&mdctx, md))) {
2835                 EVP_cleanup();
2836                 xfree(outbuf);
2837                 error ("error in SignInit");
2838                 return Qnil;
2839         }
2840         if (!EVP_SignUpdate(&mdctx, string_ext, string_len)) {
2841                 EVP_cleanup();
2842                 xfree(outbuf);
2843                 error ("error in SignUpdate");
2844                 return Qnil;
2845         }
2846         if (!EVP_SignFinal(&mdctx, outbuf, &outlen, pk)) {
2847                 EVP_cleanup();
2848                 xfree(outbuf);
2849                 error ("error in SignFinal");
2850                 return Qnil;
2851         }
2852         EVP_MD_CTX_cleanup(&mdctx);
2853
2854         l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2855         xfree(outbuf);
2856
2857         EVP_cleanup();
2858
2859         return l_outbuf;
2860 }
2861
2862 DEFUN("ossl-verify", Fossl_verify, 4, 4, 0, /*
2863 Return t iff SIG is a valid signature of STRING under DIGEST obtained by PKEY.
2864
2865 That is, hash the message STRING with the message digest DIGEST, then
2866 decrypt the signature SIG with the public key PKEY.
2867 Compare the results and return t iff both hashes are equal.
2868
2869 DIGEST is the digest to use (the same as in `ossl-sign')
2870 STRING is the message
2871 SIG is the signature of message
2872 PKEY is the public key
2873 */
2874       (digest, string, sig, pkey))
2875 {
2876         /* declarations for the cipher */
2877         const EVP_MD *md;
2878         EVP_MD_CTX mdctx;
2879         /* declarations for the pkey */
2880         EVP_PKEY *pk;
2881         /* buffer for external signature data */
2882         char *sig_ext;
2883         int sig_len;
2884         /* buffer for external string data */
2885         char *string_ext;
2886         int string_len;
2887
2888         int result;
2889
2890
2891         CHECK_SYMBOL(digest);
2892         CHECK_STRING(string);
2893         CHECK_STRING(sig);
2894         CHECK_EVPPKEY(pkey);
2895
2896
2897         pk = (XEVPPKEY(pkey))->evp_pkey;
2898         if (!ossl_pkey_has_public_data(pk))
2899                 error ("cannot verify, key has no public key data");
2900
2901         OpenSSL_add_all_algorithms();
2902         md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2903
2904         if (!md) {
2905                 EVP_cleanup();
2906                 error ("no such digest");
2907                 return Qnil;
2908         }
2909
2910         TO_EXTERNAL_FORMAT (LISP_STRING, string,
2911                             C_STRING_ALLOCA, string_ext, OSSL_CODING);
2912         string_len = OSSL_STRING_LENGTH(string);
2913         TO_EXTERNAL_FORMAT (LISP_STRING, sig,
2914                             C_STRING_ALLOCA, sig_ext, OSSL_CODING);
2915         sig_len = OSSL_STRING_LENGTH(sig);
2916
2917         EVP_MD_CTX_init(&mdctx);
2918         if (!EVP_VerifyInit(&mdctx, md)) {
2919                 EVP_cleanup();
2920                 error ("error in VerifyInit");
2921                 return Qnil;
2922         }
2923         if (!EVP_VerifyUpdate(&mdctx, string_ext, string_len)) {
2924                 EVP_cleanup();
2925                 error ("error in VerifyUpdate");
2926                 return Qnil;
2927         }
2928         result = EVP_VerifyFinal(&mdctx, (unsigned char*)sig_ext, sig_len, pk);
2929         if (result == -1) {
2930                 EVP_cleanup();
2931                 error ("error in VerifyFinal");
2932                 return Qnil;
2933         }
2934         EVP_MD_CTX_cleanup(&mdctx);
2935
2936         EVP_cleanup();
2937
2938         return result ? Qt : Qnil;
2939 }
2940
2941
2942 /*
2943  *
2944  * PEM
2945  *
2946  */
2947 DEFUN("ossl-pem-read-public-key", Fossl_pem_read_public_key, 1, 1, 0, /*
2948 Return a key (the public part) stored in a PEM structure from FILE.
2949 */
2950       (file))
2951 {
2952         /* declarations for the pkey */
2953         EVP_PKEY *pk;
2954         X509 *pk509;
2955
2956         /* output file */
2957         FILE *fp;
2958
2959         CHECK_STRING(file);
2960
2961         file = Fexpand_file_name(file, Qnil);
2962
2963         if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2964                 error ("error opening file.");
2965
2966         pk509 = PEM_read_X509(fp, NULL, NULL, NULL);
2967         pk = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
2968
2969         fclose(fp);
2970
2971         return make_evp_pkey(pk, pk509);
2972 }
2973
2974 DEFUN("ossl-pem-read-key", Fossl_pem_read_key, 1, 2, 0, /*
2975 Return a key stored in a PEM structure from FILE.
2976 If the (private part of the) key is protected with a password
2977 provide (optional) PASSWORD.
2978 */
2979       (file, password))
2980 {
2981         /* declarations for the pkey */
2982         EVP_PKEY *pk;
2983         /* output file */
2984         FILE *fp;
2985         /* password pointer */
2986         char *pass;
2987
2988         CHECK_STRING(file);
2989
2990         file = Fexpand_file_name(file, Qnil);
2991
2992         if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2993                 error ("error opening file.");
2994
2995         if (NILP(password)) {
2996                 pass = NULL;
2997         } else {
2998                 CHECK_STRING(password);
2999                 pass = (char *)XSTRING_DATA(password);
3000         }
3001
3002         pk = PEM_read_PrivateKey(fp, NULL, NULL, pass);
3003         fclose(fp);
3004         if (pk == NULL) {
3005                 /* now maybe it is a public key only */
3006                 return Fossl_pem_read_public_key(file);
3007         }
3008
3009         return make_evp_pkey_pk(pk);
3010 }
3011
3012 DEFUN("ossl-pem-write-public-key", Fossl_pem_write_public_key, 2, 2, 0, /*
3013 Write PKEY (the public part) in a PEM structure to FILE.
3014 */
3015       (file, pkey))
3016 {
3017         /* declarations for the pkey */
3018         EVP_PKEY *pk;
3019         X509 *pk509;
3020         /* output file */
3021         FILE *fp;
3022
3023         CHECK_STRING(file);
3024         CHECK_EVPPKEY(pkey);
3025
3026         file = Fexpand_file_name(file, Qnil);
3027
3028         pk = XEVPPKEY(pkey)->evp_pkey;
3029         pk509 = XEVPPKEY(pkey)->x509;
3030         SXE_SET_UNUSED(pk509);
3031
3032         if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL)
3033                 error ("error opening file.");
3034
3035         if (!PEM_write_PUBKEY(fp, pk)) {
3036                 fclose(fp);
3037                 error ("error writing PEM file.");
3038         }
3039
3040         fclose(fp);
3041
3042         return file;
3043 }
3044
3045 DEFUN("ossl-pem-write-key", Fossl_pem_write_key, 2, 4, 0, /*
3046 Write PKEY in a PEM structure to FILE. The key itself is
3047 protected by (optional) CIPHER with PASSWORD.
3048
3049 CIPHER can be set to nil and the key will not be encrypted.
3050 PASSWORD is ignored in this case.
3051 */
3052       (file, pkey, cipher, password))
3053 {
3054         const EVP_CIPHER *ciph;
3055         /* declarations for the pkey */
3056         EVP_PKEY *pk;
3057         X509 *pk509;
3058         /* output file */
3059         FILE *fp;
3060         /* password pointer */
3061         char *pass;
3062
3063         CHECK_STRING(file);
3064         CHECK_EVPPKEY(pkey);
3065
3066         file = Fexpand_file_name(file, Qnil);
3067
3068         pk = XEVPPKEY(pkey)->evp_pkey;
3069         pk509 = XEVPPKEY(pkey)->x509;
3070         SXE_SET_UNUSED(pk509);
3071
3072         if (!ossl_pkey_has_private_data(pk))
3073                 return Fossl_pem_write_public_key(file, pkey);
3074
3075         CHECK_SYMBOL(cipher);
3076
3077         if (ossl_check_cipher(cipher) != 0)
3078                 error("use of blacklisted cipher prohibited");
3079
3080         OpenSSL_add_all_algorithms();
3081
3082         if (NILP(cipher)) {
3083                 ciph = NULL;
3084                 pass = NULL;
3085         } else {
3086                 ciph = EVP_get_cipherbyname(
3087                         (char *)string_data(XSYMBOL(cipher)->name));
3088                 if (!ciph) {
3089                         EVP_cleanup();
3090                         error ("no such cipher");
3091                 }
3092         }
3093
3094         if (NILP(password)) {
3095                 ciph = NULL;
3096                 pass = NULL;
3097         } else {
3098                 CHECK_STRING(password);
3099                 pass = (char *)XSTRING_DATA(password);
3100         }
3101
3102         if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL) {
3103                 EVP_cleanup();
3104                 error ("error opening file.");
3105         }
3106
3107         if (!PEM_write_PKCS8PrivateKey(fp, pk, ciph, NULL, 0, NULL, pass)) {
3108                 EVP_cleanup();
3109                 fclose(fp);
3110                 error ("error writing PEM file.");
3111         }
3112
3113         EVP_cleanup();
3114         fclose(fp);
3115
3116         return file;
3117 }
3118
3119 static long
3120 ossl_pem_pkey_cb(BIO *bio, int cmd, const char *argp,
3121                  int argi, long argl, long ret)
3122 {
3123         Lisp_Object key;
3124         void *foo = BIO_get_callback_arg(bio);
3125
3126         if (!(key = (Lisp_Object)foo)) {
3127                 return ret;
3128         }
3129
3130         if (BIO_CB_RETURN & cmd) {
3131                 return ret;
3132         }
3133
3134         switch (cmd) {
3135         case BIO_CB_WRITE:
3136                 key = concat2(key, make_ext_string(argp, argi, OSSL_CODING));
3137                 BIO_set_callback_arg(bio, (void*)key);
3138                 break;
3139         default:
3140                 return ret;
3141         }
3142         return ret;
3143 }
3144
3145 DEFUN("ossl-pem-public-key",Fossl_pem_public_key, 1, 1, 0, /*
3146 Return PKEY as PEM encoded string.
3147 */
3148       (pkey))
3149 {
3150         /* This function can GC */
3151         /* declarations for the pkey */
3152         EVP_PKEY *pk;
3153         Lisp_Object result;
3154         /* bio stuff */
3155         BIO *b;
3156         /* gc stuff */
3157         struct gcpro gcpro1;
3158
3159         GCPRO1(pkey);
3160
3161         CHECK_EVPPKEY(pkey);
3162
3163         pk = (XEVPPKEY(pkey))->evp_pkey;
3164
3165         if (!(b = BIO_new(BIO_s_null()))) {
3166                 UNGCPRO;
3167                 error("cannot open memory buffer");
3168                 return Qnil;
3169         }
3170
3171         result = build_string("");
3172         BIO_set_callback(b, ossl_pem_pkey_cb);
3173         BIO_set_callback_arg(b, (void*)result);
3174
3175         if (!PEM_write_bio_PUBKEY(b, pk)) {
3176                 EVP_cleanup();
3177                 BIO_free(b);
3178                 UNGCPRO;
3179                 error ("error creating PEM string");
3180                 return Qnil;
3181         }
3182
3183         {
3184                 void *foo = BIO_get_callback_arg(b);
3185                 if (!(result = (Lisp_Object)foo)) {
3186                         result = Qnil;
3187                 }
3188         }
3189
3190         BIO_free(b);
3191
3192         UNGCPRO;
3193         return result;
3194 }
3195
3196 DEFUN("ossl-pem-key",Fossl_pem_key, 1, 3, 0, /*
3197 Return PKEY as PEM encoded string.   The key itself is
3198 protected by (optional) CIPHER with PASSWORD.
3199
3200 CIPHER can be set to nil and the key will not be encrypted.
3201 PASSWORD is ignored in this case.
3202 */
3203       (pkey, cipher, password))
3204 {
3205         /* This function can GC */
3206         /* declarations for the pkey */
3207         EVP_PKEY *pk;
3208         Lisp_Object result;
3209         const EVP_CIPHER *ciph;
3210         char *pass;
3211         /* bio stuff */
3212         BIO *b;
3213         struct gcpro gcpro1, gcpro2, gcpro3;
3214
3215         GCPRO3(pkey, cipher, password);
3216
3217         CHECK_EVPPKEY(pkey);
3218
3219         pk = (XEVPPKEY(pkey))->evp_pkey;
3220
3221         if (!ossl_pkey_has_private_data(pk)) {
3222                 UNGCPRO;
3223                 return Fossl_pem_public_key(pkey);
3224         }
3225
3226         CHECK_SYMBOL(cipher);
3227
3228         if (ossl_check_cipher(cipher) != 0)
3229                 error("use of blacklisted cipher prohibited");
3230
3231         OpenSSL_add_all_algorithms();
3232
3233         if (NILP(cipher)) {
3234                 ciph = NULL;
3235                 pass = NULL;
3236         } else {
3237                 ciph = EVP_get_cipherbyname(
3238                         (char *)string_data(XSYMBOL(cipher)->name));
3239                 if (!ciph) {
3240                         EVP_cleanup();
3241                         UNGCPRO;
3242                         error ("no such cipher");
3243                         return Qnil;
3244                 }
3245         }
3246
3247         if (NILP(password)) {
3248                 ciph = NULL;
3249                 pass = NULL;
3250         } else {
3251                 CHECK_STRING(password);
3252                 pass = (char *)XSTRING_DATA(password);
3253         }
3254
3255         if (!(b = BIO_new(BIO_s_null()))) {
3256                 UNGCPRO;
3257                 error("cannot open memory buffer");
3258                 return Qnil;
3259         }
3260
3261         result = build_string("");
3262         BIO_set_callback(b, ossl_pem_pkey_cb);
3263         BIO_set_callback_arg(b, (void*)result);
3264
3265         if (!PEM_write_bio_PKCS8PrivateKey(b, pk, ciph, NULL, 0, NULL, pass)) {
3266                 EVP_cleanup();
3267                 BIO_free(b);
3268                 UNGCPRO;
3269                 error ("error creating PEM string");
3270                 return Qnil;
3271         }
3272
3273         {
3274                 void *foo = BIO_get_callback_arg(b);
3275
3276                 if (!(result = (Lisp_Object)foo)) {
3277                         result = Qnil;
3278                 }
3279         }
3280
3281         BIO_free(b);
3282
3283         UNGCPRO;
3284         return result;
3285 }
3286
3287 \f
3288 /*
3289  *
3290  * SSL
3291  * The SSL support in this API is sorta high level since having
3292  * server hellos, handshakes and stuff like that is not what you want
3293  * to do in elisp.
3294  *
3295  */
3296 /* This is an opaque object for storing PKEYs in lisp */
3297 Lisp_Object Qssl_connp;
3298
3299 Lisp_Object
3300 make_ssl_conn(Lisp_SSL_CONN *ssl_conn)
3301 {
3302         Lisp_Object lisp_ssl_conn;
3303         XSETSSLCONN(lisp_ssl_conn, ssl_conn);
3304         return lisp_ssl_conn;
3305 }
3306
3307 static Lisp_Object
3308 mark_ssl_conn(Lisp_Object obj)
3309 {
3310         mark_object(XSSLCONN(obj)->parent);
3311         mark_object(XSSLCONN(obj)->pipe_instream);
3312         mark_object(XSSLCONN(obj)->pipe_outstream);
3313 #ifdef FILE_CODING
3314         mark_object(XSSLCONN(obj)->coding_instream);
3315         mark_object(XSSLCONN(obj)->coding_outstream);
3316 #endif
3317
3318         return Qnil;
3319 }
3320
3321 static void
3322 print_ssl_conn(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3323 {
3324         SSL *conn;
3325         Lisp_Object parent;
3326
3327         conn = XSSLCONN(obj)->ssl_conn;
3328         parent = XSSLCONN(obj)->parent;
3329
3330         write_c_string("#<OpenSSL socket layer: ", printcharfun);
3331         if (conn == NULL)
3332                 write_c_string("dead", printcharfun);
3333         else
3334                 write_c_string(SSL_get_version(conn), printcharfun);
3335
3336 #ifdef HAVE_SOCKETS
3337         if (PROCESSP(parent)) {
3338                 write_c_string(" on top of ", printcharfun);
3339                 print_internal(parent, printcharfun, escapeflag);
3340         }
3341 #endif  /* HAVE_SOCKETS */
3342
3343 #ifdef HAVE_POSTGRESQL
3344         if (PGCONNP(parent) &&
3345             PQstatus(XPGCONN(parent)->pgconn) == CONNECTION_OK) {
3346                 write_c_string(" on top of ", printcharfun);
3347                 print_internal(parent, printcharfun, escapeflag);
3348         }
3349 #endif  /* HAVE_POSTGRESQL */
3350         write_c_string(">", printcharfun);
3351 }
3352
3353 Lisp_SSL_CONN *
3354 allocate_ssl_conn(void)
3355 {
3356         Lisp_SSL_CONN *ssl_conn =
3357                 alloc_lcrecord_type(Lisp_SSL_CONN, &lrecord_ssl_conn);
3358
3359         /* the network process stuff */
3360         ssl_conn->parent = Qnil;
3361         ssl_conn->infd = -1;
3362         ssl_conn->outfd = -1;
3363
3364         ssl_conn->connected_p = 0;
3365         ssl_conn->protected_p = 0;
3366
3367         ssl_conn->pipe_instream = Qnil;
3368         ssl_conn->pipe_outstream = Qnil;
3369 #if FILE_CODING
3370         ssl_conn->coding_instream = Qnil;
3371         ssl_conn->coding_outstream = Qnil;
3372 #endif
3373
3374         return ssl_conn;
3375 }
3376
3377 static void
3378 finalise_ssl_conn(void *header, int for_disksave)
3379 {
3380         Lisp_SSL_CONN *ssl_conn = (Lisp_SSL_CONN *) header;
3381
3382         if (!(ssl_conn->ssl_conn == NULL)) {
3383                 if (ssl_conn->connected_p)
3384                         SSL_shutdown(ssl_conn->ssl_conn);
3385                 SSL_free(ssl_conn->ssl_conn);
3386                 ssl_conn->ssl_conn = NULL;
3387         }
3388         if (!(ssl_conn->ssl_ctx == NULL)) {
3389                 SSL_CTX_free(ssl_conn->ssl_ctx);
3390                 ssl_conn->ssl_ctx = NULL;
3391         }
3392         ssl_conn->ssl_bio = NULL;
3393
3394         if (PROCESSP(ssl_conn->parent)) {
3395                 XPROCESS(ssl_conn->parent)->process_type = PROCESS_TYPE_NETWORK;
3396                 XPROCESS(ssl_conn->parent)->process_type_data = Qnil;
3397         }
3398         /* we leave the process alive, it's not our fault, but
3399          * we nullify its pointer
3400          */
3401         ssl_conn->parent = Qnil;
3402         ssl_conn->infd = -1;
3403         ssl_conn->outfd = -1;
3404
3405         ssl_conn->connected_p = 0;
3406         ssl_conn->protected_p = 0;
3407
3408         /* free the lstream resources */
3409 #if 0                           /* will lead to problems */
3410         if (LSTREAMP(ssl_conn->pipe_instream))
3411                 Lstream_delete(XLSTREAM(ssl_conn->pipe_instream));
3412         if (LSTREAMP(ssl_conn->pipe_outstream))
3413                 Lstream_delete(XLSTREAM(ssl_conn->pipe_outstream));
3414 #endif
3415         ssl_conn->pipe_instream = Qnil;
3416         ssl_conn->pipe_outstream = Qnil;
3417 #if FILE_CODING
3418 #if 0                           /* will lead to problems */
3419         if (LSTREAMP(ssl_conn->coding_instream))
3420                 Lstream_delete(XLSTREAM(ssl_conn->coding_instream));
3421         if (LSTREAMP(ssl_conn->coding_outstream))
3422                 Lstream_delete(XLSTREAM(ssl_conn->coding_outstream));
3423 #endif
3424         ssl_conn->coding_instream = Qnil;
3425         ssl_conn->coding_outstream = Qnil;
3426 #endif
3427
3428         /* avoid some warning */
3429         if (for_disksave);
3430 }
3431
3432 DEFINE_LRECORD_IMPLEMENTATION("ssl_conn", ssl_conn,
3433                               mark_ssl_conn, print_ssl_conn,
3434                               finalise_ssl_conn,
3435                               NULL, NULL, 0, Lisp_SSL_CONN);
3436
3437 static int
3438 ssl_conn_alive_p(Lisp_SSL_CONN *ssl_conn)
3439 {
3440         return ssl_conn->connected_p;
3441 }
3442
3443 static int
3444 get_process_infd(Lisp_Process * p)
3445 {
3446         Lisp_Object instr, outstr;
3447         get_process_streams(p, &instr, &outstr);
3448         return Lstream_get_fd(XLSTREAM(instr));
3449 }
3450 static int
3451 get_process_outfd(Lisp_Process * p)
3452 {
3453         Lisp_Object instr, outstr;
3454         get_process_streams(p, &instr, &outstr);
3455         return Lstream_get_fd(XLSTREAM(outstr));
3456 }
3457
3458 static int
3459 event_stream_ssl_create_stream_pair(
3460         SSL *conn,
3461         Lisp_Object *instream, Lisp_Object *outstream, int flags)
3462 {
3463         *instream = make_ssl_input_stream(conn, flags);
3464         *outstream = make_ssl_output_stream(conn, flags);
3465
3466         return 0;
3467 }
3468
3469 static void
3470 init_ssl_io_handles(Lisp_SSL_CONN *s, int flags)
3471 {
3472         event_stream_ssl_create_stream_pair(
3473                 s->ssl_conn, &s->pipe_instream, &s->pipe_outstream, flags);
3474
3475 #ifdef FILE_CODING
3476         s->coding_instream = make_decoding_input_stream(
3477                 XLSTREAM(s->pipe_instream), Fget_coding_system(
3478                         Vcoding_system_for_read));
3479         Lstream_set_character_mode(XLSTREAM(s->coding_instream));
3480         s->coding_outstream = make_encoding_output_stream(
3481                 XLSTREAM(s->pipe_outstream), Fget_coding_system(
3482                         Vcoding_system_for_write));
3483 #endif /* FILE_CODING */
3484 }
3485
3486 /* Advanced step-by-step initialisation */
3487 #define OSSL_CHECK_PROCESS(process)                                     \
3488 do {                                                                    \
3489         /* Make sure the process is really alive.  */                   \
3490         if (!EQ(XPROCESS(process)->status_symbol, Qrun))                \
3491                 error("Network stream %s not alive",                    \
3492                       XSTRING_DATA(XPROCESS(process)->name));           \
3493         /* Make sure the process is a network stream. */                \
3494         if (!network_connection_p(process))                             \
3495                 error("Process %s is not a network stream",             \
3496                       XSTRING_DATA(XPROCESS(process)->name));           \
3497 } while (0);
3498
3499 #ifdef OSSL_DEBUG_FLAG
3500 static long
3501 ossl_bio_dump_callback(BIO *bio, int cmd, const char *argp,
3502                   int argi, long argl, long ret)
3503 {
3504         BIO *out;
3505
3506         out=(BIO *)BIO_get_callback_arg(bio);
3507         if (out == NULL) return(ret);
3508
3509         if (cmd == (BIO_CB_READ|BIO_CB_RETURN))
3510         {
3511                 BIO_printf(out,"read from %p [%p] (%d bytes => %ld (0x%lX))\n",
3512                            (void *)bio,argp,argi,ret,ret);
3513                 BIO_dump(out,argp,(int)ret);
3514                 return(ret);
3515         }
3516         else if (cmd == (BIO_CB_WRITE|BIO_CB_RETURN))
3517         {
3518                 BIO_printf(out,"write to %p [%p] (%d bytes => %ld (0x%lX))\n",
3519                            (void *)bio,argp,argi,ret,ret);
3520                 BIO_dump(out,argp,(int)ret);
3521         }
3522         return(ret);
3523 }
3524 #endif
3525
3526 static Lisp_Object
3527 ossl_ssl_prepare_cmeth(Lisp_Object method)
3528 {
3529         SSL_METHOD *meth = NULL;
3530         Lisp_SSL_CONN *lisp_ssl_conn;
3531
3532         /* start preparing the conn object */
3533         SSL_library_init();
3534         SSL_load_error_strings();
3535
3536         /* I would love to make 'meth' const SSL_METHOD* as well as the
3537            'ssl_meth' member of 'Lisp_SSL_CONN' unfortunately not all
3538            supported versions of OpenSSL then take const SSL_METHOD*
3539            as arguments, so turning off the cast qualifier warning and
3540            store non-const is a more reasonable solution.
3541         */
3542 #pragma GCC diagnostic push
3543 #pragma GCC diagnostic ignored "-Wcast-qual"
3544         if (0) {
3545         } else if (EQ(method, Qssl2)) {
3546 #if HAVE_SSLV2_CLIENT_METHOD
3547                 meth = (SSL_METHOD *)SSLv2_client_method();
3548 #else
3549                 error("sslv2 client method not supported");
3550 #endif
3551         } else if (EQ(method, Qssl3)) {
3552 #if HAVE_SSLV3_CLIENT_METHOD
3553                 meth = (SSL_METHOD *)SSLv3_client_method();
3554 #else
3555                 error("sslv3 client method not supported");
3556 #endif
3557         } else if (EQ(method, Qssl23)) {
3558 #if HAVE_SSLV23_CLIENT_METHOD
3559                 meth = (SSL_METHOD *)SSLv23_client_method();
3560 #else
3561                 error("sslv23 client method not supported");
3562 #endif
3563         } else if (EQ(method, Qtls1)) {
3564 #if HAVE_TLSV1_CLIENT_METHOD
3565                 meth = (SSL_METHOD *)TLSv1_client_method();
3566 #else
3567                 error("tlsv1 client method not supported");
3568 #endif
3569         } else {
3570 #if HAVE_TLSV1_CLIENT_METHOD
3571                 meth = (SSL_METHOD *)TLSv1_client_method();
3572 #else
3573                 error("default tlsv1 client method not supported");
3574 #endif
3575         }
3576 #pragma GCC diagnostic pop
3577         if (!RAND_status())
3578                 error("OSSL: not enough random data");
3579
3580         /* now allocate this stuff, pump it and return */
3581         lisp_ssl_conn = allocate_ssl_conn();
3582         lisp_ssl_conn->ssl_meth = meth;
3583         lisp_ssl_conn->ssl_ctx = NULL;
3584         lisp_ssl_conn->ssl_conn = NULL;
3585         lisp_ssl_conn->ssl_bio = NULL;
3586
3587         return make_ssl_conn(lisp_ssl_conn);
3588 }
3589
3590 static Lisp_Object
3591 ossl_ssl_prepare_smeth(Lisp_Object method)
3592 {
3593         SSL_METHOD *meth = NULL;
3594         Lisp_SSL_CONN *lisp_ssl_conn;
3595
3596         /* start preparing the conn object */
3597         SSL_library_init();
3598         SSL_load_error_strings();
3599
3600         /* I would love to make 'meth' const SSL_METHOD* as well as the
3601            'ssl_meth' member of 'Lisp_SSL_CONN' unfortunately not all
3602            supported versions of OpenSSL then take const SSL_METHOD*
3603            as arguments, so turning off the cast qualifier warning and
3604            store non-const is a more reasonable solution. 
3605         */
3606 #pragma GCC diagnostic push
3607 #pragma GCC diagnostic ignored "-Wcast-qual"
3608         if (0) {
3609         } else if (EQ(method, Qssl2)) {
3610 #if HAVE_SSLV2_SERVER_METHOD
3611                 meth = (SSL_METHOD *)SSLv2_server_method();
3612 #else
3613                 error("sslv2 client method not supported");
3614 #endif
3615         } else if (EQ(method, Qssl3)) {
3616 #if HAVE_SSLV3_SERVER_METHOD
3617                 meth = (SSL_METHOD *)SSLv3_server_method();
3618 #else
3619                 error("sslv3 client method not supported");
3620 #endif
3621         } else if (EQ(method, Qssl23)) {
3622 #if HAVE_SSLV23_SERVER_METHOD
3623                 meth = (SSL_METHOD *)SSLv23_server_method();
3624 #else
3625                 error("sslv23 client method not supported");
3626 #endif
3627         } else if (EQ(method, Qtls1)) {
3628 #if HAVE_TLSV1_SERVER_METHOD
3629                 meth = (SSL_METHOD *)TLSv1_server_method();
3630 #else
3631                 error("tlsv1 client method not supported");
3632 #endif
3633         } else {
3634 #if HAVE_SSLV23_SERVER_METHOD
3635                 meth = (SSL_METHOD *)SSLv23_server_method();
3636 #else
3637                 error("default sslv23 client method not supported");
3638 #endif
3639         }
3640 #pragma GCC diagnostic pop
3641         if (!RAND_status())
3642                 error("OSSL: not enough random data");
3643
3644         /* now allocate this stuff, pump it and return */
3645         lisp_ssl_conn = allocate_ssl_conn();
3646         lisp_ssl_conn->ssl_meth = meth;
3647         lisp_ssl_conn->ssl_ctx = NULL;
3648         lisp_ssl_conn->ssl_conn = NULL;
3649         lisp_ssl_conn->ssl_bio = NULL;
3650
3651         return make_ssl_conn(lisp_ssl_conn);
3652 }
3653
3654 static Lisp_Object
3655 ossl_ssl_prepare_ctx(Lisp_Object ssl_conn)
3656 {
3657         /* SSL connection stuff */
3658         SSL_CTX *ctx = NULL;
3659         Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3660
3661         ctx = SSL_CTX_new(lisp_ssl_conn->ssl_meth);
3662         if (ctx == NULL)
3663                 error("OSSL: context initialisation failed");
3664
3665         /* OpenSSL contains code to work-around lots of bugs and flaws in
3666          * various SSL-implementations. SSL_CTX_set_options() is used to enabled
3667          * those work-arounds. The man page for this option states that
3668          * SSL_OP_ALL enables all the work-arounds and that "It is usually safe
3669          * to use SSL_OP_ALL to enable the bug workaround options if
3670          * compatibility with somewhat broken implementations is desired."
3671          */
3672         SSL_CTX_set_options(ctx, SSL_OP_ALL);
3673
3674         lisp_ssl_conn->ssl_ctx = ctx;
3675
3676         return ssl_conn;
3677 }
3678
3679 static Lisp_Object
3680 ossl_ssl_prepare(Lisp_Object ssl_conn, void(*fun)(SSL*))
3681 {
3682         /* SSL connection stuff */
3683         SSL *conn = NULL;
3684         BIO *bio = NULL;
3685 #ifdef OSSL_DEBUG_FLAG
3686         BIO *bio_c_out = NULL;
3687 #endif
3688         Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3689
3690         /* now initialise a new connection context */
3691         conn = SSL_new(lisp_ssl_conn->ssl_ctx);
3692         if (conn == NULL || fun == NULL)
3693                 error("OSSL: connection initialisation failed");
3694
3695         /* always renegotiate */
3696         SSL_set_mode(conn, SSL_MODE_AUTO_RETRY);
3697
3698         /* initialise the main connection BIO */
3699         bio = BIO_new(BIO_s_socket());
3700
3701 #ifdef OSSL_DEBUG_FLAG
3702         /* this is a debug BIO which pukes tons of stuff to stderr */
3703         bio_c_out = BIO_new_fp(stderr, BIO_NOCLOSE);
3704         BIO_set_callback(bio, ossl_bio_dump_callback);
3705         BIO_set_callback_arg(bio, bio_c_out);
3706 #endif
3707
3708         /* connect SSL with the bio */
3709         SSL_set_bio(conn, bio, bio);
3710         /* turn into client or server */
3711         fun(conn);
3712
3713         /* now allocate this stuff, pump it and return */
3714         lisp_ssl_conn->ssl_conn = conn;
3715         lisp_ssl_conn->ssl_bio = bio;
3716
3717         /* create lstream handles */
3718         init_ssl_io_handles(lisp_ssl_conn, STREAM_NETWORK_CONNECTION);
3719
3720         return ssl_conn;
3721 }
3722
3723 /* Injection of CA certificates */
3724 int ossl_ssl_inject_ca(Lisp_Object ssl_conn, Lisp_Object cacert)
3725 {
3726         SSL_CTX *ctx;
3727         EVP_PKEY *cert;
3728         X509 *xc509;
3729
3730         ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3731         cert = XEVPPKEY(cacert)->evp_pkey;
3732         xc509 = XEVPPKEY(cacert)->x509;
3733
3734         if (cert && !xc509) {
3735                 xc509 = X509_new();
3736                 X509_set_pubkey(xc509, cert);
3737                 XEVPPKEY(cacert)->x509 = xc509;
3738         } else if (xc509);
3739         else
3740                 return 0;
3741
3742         /* what about coding system issues? */
3743         if (!SSL_CTX_add_client_CA(ctx, xc509))
3744                 return 0;
3745         else
3746                 return -1;
3747 }
3748
3749 int ossl_ssl_inject_ca_file(Lisp_Object ssl_conn, Lisp_Object cafile)
3750 {
3751         SSL_CTX *ctx;
3752
3753         ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3754
3755         /* what about coding system issues? */
3756         if (!SSL_CTX_load_verify_locations(
3757                     ctx, (char*)XSTRING_DATA(cafile), NULL))
3758                 return 0;
3759         else
3760                 return -1;
3761 }
3762
3763 int ossl_ssl_inject_ca_path(Lisp_Object ssl_conn, Lisp_Object capath)
3764 {
3765         SSL_CTX *ctx;
3766
3767         ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3768
3769         /* what about coding system issues? */
3770         if (!SSL_CTX_load_verify_locations(
3771                     ctx, NULL, (char*)XSTRING_DATA(capath)))
3772                 return 0;
3773         else
3774                 return -1;
3775 }
3776
3777 int ossl_ssl_inject_cert(Lisp_Object ssl_conn,
3778                          Lisp_Object cert, Lisp_Object key)
3779 {
3780         SSL_CTX *ctx;
3781         EVP_PKEY *pkey;
3782         EVP_PKEY *xcert;
3783         X509 *xc509;
3784
3785         ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3786         pkey = XEVPPKEY(key)->evp_pkey;
3787         xcert = XEVPPKEY(cert)->evp_pkey;
3788         xc509 = XEVPPKEY(cert)->x509;
3789
3790         if (xcert && !xc509) {
3791                 xc509 = X509_new();
3792                 X509_set_pubkey(xc509, xcert);
3793                 XEVPPKEY(cert)->x509 = xc509;
3794         } else if (xc509);
3795         else
3796                 return 0;
3797
3798         if (SSL_CTX_use_certificate(ctx, xc509) <= 0)
3799                 return 0;
3800
3801         if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
3802                 return 0;
3803         if (!SSL_CTX_check_private_key(ctx))
3804                 return 0;
3805
3806         return -1;
3807 }
3808
3809 int ossl_ssl_inject_cert_file(Lisp_Object ssl_conn,
3810                               Lisp_Object cert, Lisp_Object key)
3811 {
3812         SSL_CTX *ctx;
3813
3814         ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3815
3816         if (SSL_CTX_use_certificate_file(
3817                     ctx, (char*)XSTRING_DATA(cert), SSL_FILETYPE_PEM) <= 0)
3818                 return 0;
3819         if (SSL_CTX_use_PrivateKey_file(
3820                     ctx, (char*)XSTRING_DATA(key), SSL_FILETYPE_PEM) <= 0)
3821                 return 0;
3822         if (!SSL_CTX_check_private_key(ctx))
3823                 return 0;
3824
3825         return -1;
3826 }
3827
3828 Lisp_Object ossl_ssl_handshake(Lisp_Object ssl_conn, Lisp_Object process)
3829 {
3830         /* This function can GC */
3831         /* SSL connection stuff */
3832         SSL *conn = NULL;
3833         BIO *bio = NULL;
3834 #if 0 && defined(OSSL_DEBUG_FLAG)
3835         BIO *bio_c_out = NULL;
3836 #endif
3837         int ret, err, infd, outfd;
3838
3839         struct gcpro gcpro1, gcpro2;
3840
3841         /* Make sure we have a process, the alive check should be done in the
3842            function calling this here */
3843         CHECK_PROCESS(process);
3844
3845         GCPRO2(ssl_conn, process);
3846
3847         /* set the alternate one */
3848         event_stream_unselect_process(XPROCESS(process));
3849
3850 #ifdef HAVE_MULE
3851         /* just announce that we are very binary */
3852         Fset_process_coding_system(process, Qbinary, Qbinary);
3853 #endif
3854
3855         /* initialise the process' buffer for type-specific data,
3856          * we will store process input there */
3857         XPROCESS(process)->process_type_data = Qnil;
3858
3859         /* retrieve the sockets of the process */
3860         infd = get_process_infd(XPROCESS(process));
3861         outfd = get_process_outfd(XPROCESS(process));
3862
3863         /* push data to ssl_conn */
3864         XSSLCONN(ssl_conn)->parent = process;
3865         XSSLCONN(ssl_conn)->infd = infd;
3866         XSSLCONN(ssl_conn)->outfd = outfd;
3867
3868         /* frob vars from ssl_conn */
3869         conn = XSSLCONN(ssl_conn)->ssl_conn;
3870         bio = XSSLCONN(ssl_conn)->ssl_bio;
3871
3872         /* initialise the main connection BIO */
3873         BIO_set_fd(bio, infd, 0);
3874
3875         /* now perform the actual handshake
3876          * this is a loop because of the genuine openssl concept to not handle
3877          * non-blocking I/O correctly */
3878         for (;;) {
3879                 struct timeval to;
3880
3881                 ret = SSL_do_handshake(conn);
3882                 err = SSL_get_error(conn, ret);
3883
3884                 /* perform select() with timeout
3885                  * 1 second at the moment */
3886                 to.tv_sec = 1;
3887                 to.tv_usec = 0;
3888
3889                 if (err == SSL_ERROR_NONE) {
3890                         break;
3891                 } else if (err == SSL_ERROR_WANT_READ) {
3892                         fd_set read_fds;
3893                         OSSL_DEBUG("WANT_READ\n");
3894
3895                         FD_ZERO(&read_fds);
3896                         FD_SET(infd, &read_fds);
3897
3898                         /* wait for socket to be readable */
3899                         if (!(ret = select(infd+1, &read_fds, 0, NULL, &to))) {
3900                                 UNGCPRO;
3901                                 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3902                                 error("timeout during handshake");
3903                                 return Qnil;
3904                         }
3905                 } else if (err == SSL_ERROR_WANT_WRITE) {
3906                         fd_set write_fds;
3907                         OSSL_DEBUG("WANT_WRITE\n");
3908                         FD_ZERO(&write_fds);
3909                         FD_SET(outfd, &write_fds);
3910
3911                         /* wait for socket to be writable */
3912                         if (!(ret = select(infd+1, &write_fds, 0, NULL, &to))) {
3913                                 UNGCPRO;
3914                                 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3915                                 error("timeout during handshake");
3916                                 return Qnil;
3917                         }
3918                 } else if (err == SSL_ERROR_SSL) {
3919                         /* close down the process object */
3920                         Fdelete_process(process);
3921
3922                         UNGCPRO;
3923                         finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3924                         error("handshake failed");
3925                         return Qnil;
3926                 } else {
3927                         OSSL_CRITICAL("\nUnknown error: %d\n"
3928                                       "Please report: "
3929                                       "sxemacs-devel@sxemacs.org\n\n", err);
3930
3931 #if 0
3932                         /* we used to check whether the connection is
3933                            still alive, but this was perhaps a bad idea */
3934                         try = BIO_read(bio, buf, 2);
3935                         if ((try == 0) ||
3936                             (try < 0 && !BIO_should_retry(bio))) {
3937                                 /* Handle closed connection */
3938                                 XPROCESS(process)->exit_code = 256;
3939                                 XPROCESS(process)->status_symbol = Qexit;
3940                         }
3941 #else
3942                         /* close down the process object */
3943                         Fdelete_process(process);
3944 #endif
3945
3946                         UNGCPRO;
3947                         finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3948                         error("unknown handshake error");
3949                         return Qnil;
3950                 }
3951         }
3952
3953         /* marry the socket layer now */
3954         ossl_ssl_proselytise_process(ssl_conn, process);
3955
3956         /* declare the whole pig connected */
3957         XSSLCONN(ssl_conn)->connected_p = 1;
3958
3959         event_stream_select_process(XPROCESS(process));
3960
3961         UNGCPRO;
3962         return ssl_conn;
3963 }
3964
3965 DEFUN("ossl-ssl-inject-cert", Fossl_ssl_inject_cert, 2, 3, 0, /*
3966 Add CERT as the local certificate of SSL-CONN.
3967 Optional argument KEY specifies a key file or evp-pkey, if
3968 CERT does not contain it.
3969
3970 Both, CERT and KEY may be either a filename pointing to a
3971 PEM-encoded certificate and key respectively, or may be an
3972 evp-pkey object.
3973 */
3974       (ssl_conn, cert, key))
3975 {
3976         /* This function can GC */
3977         int (*fun)(Lisp_Object, Lisp_Object, Lisp_Object) = NULL;
3978         struct gcpro gcpro1, gcpro2, gcpro3;
3979
3980         GCPRO3(ssl_conn, cert, key);
3981
3982         CHECK_SSLCONN(ssl_conn);
3983         if (!NILP(cert))
3984                 if (!STRINGP(cert))
3985                         CHECK_EVPPKEY(cert);
3986         if (!NILP(key))
3987                 if (!STRINGP(key))
3988                         CHECK_EVPPKEY(key);
3989
3990         /* certificate and key preparation */
3991         if (STRINGP(cert)) {
3992                 cert = Fexpand_file_name(cert, Qnil);
3993                 if (NILP(Ffile_readable_p(cert)))
3994                         cert = Qnil;
3995         }
3996
3997         if (STRINGP(key)) {
3998                 key = Fexpand_file_name(key, Qnil);
3999                 if (NILP(Ffile_readable_p(key)))
4000                         key = Qnil;
4001         }
4002
4003         if (STRINGP(cert) && NILP(key))
4004                 key = cert;
4005         else if (EVPPKEYP(cert) && NILP(key))
4006                 key = cert;
4007
4008         /* certificate and key injection */
4009         if (!NILP(cert) && !NILP(key) &&
4010             STRINGP(cert) && STRINGP(key))
4011                 fun = ossl_ssl_inject_cert_file;
4012         else if (!NILP(cert) && !NILP(key) &&
4013                  EVPPKEYP(cert) && EVPPKEYP(key))
4014                 fun = ossl_ssl_inject_cert;
4015
4016         if (fun && fun(ssl_conn, cert, key)) {
4017                 UNGCPRO;
4018                 return Qt;
4019         } else {
4020                 UNGCPRO;
4021                 return Qnil;
4022         }
4023 }
4024
4025 DEFUN("ossl-ssl-inject-ca", Fossl_ssl_inject_ca, 2, 2, 0, /*
4026 Add CA to the pile of certificate authorities of SSL-CONN.
4027 Also force a \(re\)verification of the remote peer certificate
4028 against CA.  Return `t' if the injection was successful,
4029 `nil' otherwise.
4030
4031 CA may be either a file name pointing to a PEM-encoded
4032 CA certificate, or may be a directory containing a valid
4033 bunch of CA certificates according to OpenSSL's CA path
4034 layout, or may also be an evp-pkey object.
4035 */
4036       (ssl_conn, ca))
4037 {
4038         /* This function can GC */
4039         int (*fun)(Lisp_Object, Lisp_Object) = NULL;
4040         SSL *conn = NULL;
4041         struct gcpro gcpro1, gcpro2;
4042
4043         GCPRO2(ssl_conn, ca);
4044
4045         CHECK_SSLCONN(ssl_conn);
4046         if (!NILP(ca))
4047                 if (!STRINGP(ca))
4048                         CHECK_EVPPKEY(ca);
4049
4050         if (STRINGP(ca)) {
4051                 ca = Fexpand_file_name(ca, Qnil);
4052                 if (NILP(Ffile_readable_p(ca)))
4053                         ca = Qnil;
4054         }
4055
4056         if (!NILP(ca) && STRINGP(ca)) {
4057                 if (NILP(Ffile_directory_p(ca)))
4058                         fun = ossl_ssl_inject_ca_file;
4059                 else
4060                         fun = ossl_ssl_inject_ca_path;
4061         } else if (!NILP(ca) && EVPPKEYP(ca))
4062                 fun = ossl_ssl_inject_ca;
4063
4064         if (fun && fun(ssl_conn, ca) &&
4065             (conn = XSSLCONN(ssl_conn)->ssl_conn)) {
4066 #if HAVE_SSL_VERIFY_CERT_CHAIN
4067                 ssl_verify_cert_chain(conn, SSL_get_peer_cert_chain(conn));
4068 #else
4069                 error("SSL certificate chain verification not supported");
4070 #endif
4071                 UNGCPRO;
4072                 return Qt;
4073         }
4074
4075         UNGCPRO;
4076         return Qnil;
4077 }
4078
4079 DEFUN("ossl-ssl-handshake", Fossl_ssl_handshake, 1, 6, 0, /*
4080 Perform a handshake on the network connection PROCESS.
4081
4082 Return a ssl-conn object, or `nil' if the handshake failed.
4083 In the latter case, most likely the remote site cannot handle
4084 the specified method, requires a client certificate, or cannot
4085 handle ssl at all.
4086
4087 Optional argument METHOD indicates the SSL connection method,
4088 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
4089
4090 Optional argument CA indicates a CA certificate.
4091 See `ossl-ssl-inject-ca'.
4092
4093 Optional arguments CERT and KEY indicate a peer certificate
4094 and possibly a separate key file respectively.
4095 See `ossl-ssl-inject-peer-cert'.
4096
4097 Optional argument SERVERP indicates whether to perform the
4098 handshake as a server if non-nil, and as a client otherwise.
4099 Note: In case of a handshake as server it is mandatory to provide
4100 a valid certificate and a corresponding key.
4101 */
4102       (process, method, ca, cert, key, serverp))
4103 {
4104         /* This function can GC */
4105         /* the result(s) */
4106         Lisp_Object ssl_conn, result;
4107
4108         struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
4109
4110         GCPRO6(process, method, ca, cert, key, serverp);
4111
4112         /* Make sure the process is really alive.  */
4113         CHECK_PROCESS(process);
4114         OSSL_CHECK_PROCESS(process);
4115
4116         /* create a ssl_conn object first */
4117         if (NILP(serverp))
4118                 ssl_conn = ossl_ssl_prepare_cmeth(method);
4119         else
4120                 ssl_conn = ossl_ssl_prepare_smeth(method);
4121
4122         /* create the context */
4123         ossl_ssl_prepare_ctx(ssl_conn);
4124
4125         /* certificate and key preparation */
4126         Fossl_ssl_inject_cert(ssl_conn, cert, key);
4127         /* certificate authority preparation */
4128         Fossl_ssl_inject_ca(ssl_conn, ca);
4129
4130         /* prepare for handshake */
4131         if (NILP(serverp))
4132                 ossl_ssl_prepare(ssl_conn, SSL_set_connect_state);
4133         else
4134                 ossl_ssl_prepare(ssl_conn, SSL_set_accept_state);
4135
4136         result = ossl_ssl_handshake(ssl_conn, process);
4137
4138         UNGCPRO;
4139         return result;
4140 }
4141
4142 DEFUN("ossl-ssl-connect", Fossl_ssl_connect, 0, MANY, 0, /*
4143 Perform a TLS or SSL handshake, return a ssl-conn object on
4144 success, or `nil' if the handshake failed.
4145 In the latter case, most likely the remote site cannot handle
4146 the specified method, requires a client certificate, or cannot
4147 handle ssl at all.
4148
4149 :process
4150 :method
4151 :cafile
4152 :capath
4153 :key
4154 :cert
4155
4156  PROCESS.
4157 Optional argument METHOD indicates the SSL connection method,
4158 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
4159 */
4160       (int nargs, Lisp_Object *args))
4161 {
4162         int i;
4163
4164         for (i = 0; i < nargs; i++);
4165
4166         return Qnil;
4167 }
4168
4169 static void
4170 ossl_swap_process_streams(Lisp_SSL_CONN *s, Lisp_Process *p)
4171 {
4172         Lisp_Object in, out;
4173
4174         in = p->pipe_instream;
4175         out = p->pipe_outstream;
4176
4177         p->pipe_instream = s->pipe_instream;
4178         p->pipe_outstream = s->pipe_outstream;
4179
4180         s->pipe_instream = in;
4181         s->pipe_outstream = out;
4182
4183 #ifdef FILE_CODING
4184         in = p->coding_instream;
4185         out = p->coding_outstream;
4186
4187         p->coding_instream = s->coding_instream;
4188         p->coding_outstream = s->coding_outstream;
4189
4190         s->coding_instream = in;
4191         s->coding_outstream = out;
4192 #endif
4193 }
4194
4195 static int
4196 ossl_ssl_proselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4197 {
4198         Lisp_Process *p = XPROCESS(process);
4199         Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4200
4201         event_stream_unselect_process(p);
4202
4203         /* put the streams we have in the ssl-conn object into the process
4204            object; actually these swap their places */
4205         if (p->process_type != PROCESS_TYPE_SSL)
4206                 ossl_swap_process_streams(s, p);
4207
4208         /* somehow we gotta link the network-process with the ss-layer
4209          * otherwise it'd be easy to open a network stream then
4210          * a ss-layer on top of it and then via `delete-process'
4211          * all the work is void while the ss-layer still exists
4212          */
4213         p->process_type = PROCESS_TYPE_SSL;
4214         p->process_type_data = ssl_conn;
4215
4216         event_stream_select_process(p);
4217
4218         return 0;
4219 }
4220
4221 static int
4222 ossl_ssl_unproselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4223 {
4224         Lisp_Process *p = XPROCESS(process);
4225         Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4226
4227         /* put the streams we have in the ssl-conn object into the process
4228            object (they should be the former process streams) */
4229         if (p->process_type == PROCESS_TYPE_SSL)
4230                 ossl_swap_process_streams(s, p);
4231
4232         /* somehow we gotta link the network-process with the ss-layer
4233          * otherwise it'd be easy to open a network stream then
4234          * a ss-layer on top of it and then via `delete-process'
4235          * all the work is void while the ss-layer still exists
4236          */
4237         XPROCESS(process)->process_type = PROCESS_TYPE_NETWORK;
4238         XPROCESS(process)->process_type_data = Qnil;
4239
4240         return 0;
4241 }
4242
4243 DEFUN("ossl-ssl-proselytise-process", Fossl_ssl_proselytise_process,
4244       1, 1, 0, /*
4245 Convert the underlying process of SSL-CONN into a secure
4246 network connection object.
4247 */
4248       (ssl_conn))
4249 {
4250         Lisp_Object process;
4251
4252         CHECK_SSLCONN(ssl_conn);
4253
4254         process = XSSLCONN(ssl_conn)->parent;
4255         if (!PROCESSP(process)) {
4256                 error("no process associated with this connection");
4257                 return Qnil;
4258         }
4259
4260         /* Make sure the process is really alive.  */
4261         OSSL_CHECK_PROCESS(process);
4262
4263         ossl_ssl_proselytise_process(ssl_conn, process);
4264
4265         return process;
4266 }
4267
4268 DEFUN("ossl-ssl-unproselytise-process", Fossl_ssl_unproselytise_process,
4269       1, 1, 0, /*
4270 Convert the underlying process of SSL-CONN into an ordinary
4271 network connection object.
4272 */
4273       (ssl_conn))
4274 {
4275         Lisp_Object process;
4276
4277         CHECK_SSLCONN(ssl_conn);
4278
4279         process = XSSLCONN(ssl_conn)->parent;
4280         if (!PROCESSP(process)) {
4281                 error("no process associated with this connection");
4282                 return Qnil;
4283         }
4284
4285         /* Make sure the process is really alive.  */
4286         OSSL_CHECK_PROCESS(process);
4287
4288         /* Castrate the process and make it a network process again */
4289         ossl_ssl_unproselytise_process(ssl_conn, process);
4290
4291         return process;
4292 }
4293
4294 DEFUN("ossl-ssl-finish", Fossl_ssl_finish, 1, 1, 0, /*
4295 Finish an SSL connection SSL-CONN.
4296
4297 Note: This may also finish the network connection.
4298 */
4299       (ssl_conn))
4300 {
4301         Lisp_Object process;
4302
4303         CHECK_SSLCONN(ssl_conn);
4304
4305         if (XSSLCONN(ssl_conn)->protected_p)
4306                 error ("Cannot finish protected SSL connection");
4307
4308         process = XSSLCONN(ssl_conn)->parent;
4309         if (PROCESSP(process))
4310                 ossl_ssl_unproselytise_process(ssl_conn, process);
4311
4312         finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
4313         return ssl_conn;
4314 }
4315
4316 DEFUN("ossl-ssl-read", Fossl_ssl_read, 2, 2, 0, /*
4317 Return the cleartext of STRING which is assumed to be a complete
4318 block of data sent through SSL-CONN.
4319 */
4320       (ssl_conn, string))
4321 {
4322         /* network stream stuff */
4323         SSL *conn;
4324         Lisp_Object process;
4325         /* the result */
4326         Lisp_Object result = Qnil;
4327
4328         CHECK_SSLCONN(ssl_conn);
4329         CHECK_STRING(string);
4330
4331         if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4332                 error("SSL connection dead");
4333
4334         conn = XSSLCONN(ssl_conn)->ssl_conn;
4335         SXE_SET_UNUSED(conn);
4336
4337         process = XSSLCONN(ssl_conn)->parent;
4338
4339         /* Make sure the process is really alive.  */
4340         OSSL_CHECK_PROCESS(process);
4341
4342         return result;
4343 }
4344
4345 DEFUN("ossl-ssl-write", Fossl_ssl_write, 2, 2, 0, /*
4346 Send STRING to the tunnel SSL-CONN.
4347 */
4348       (ssl_conn, string))
4349 {
4350         /* network stream stuff */
4351         SSL *conn;
4352         Lisp_Object process, proc_filter;
4353         Lstream *out;
4354         /* aux */
4355         int ret;
4356
4357         CHECK_SSLCONN(ssl_conn);
4358         CHECK_STRING(string);
4359
4360         if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4361                 error("SSL connection dead");
4362
4363         conn = XSSLCONN(ssl_conn)->ssl_conn;
4364         process = XSSLCONN(ssl_conn)->parent;
4365
4366         /* Make sure the process is really alive.  */
4367         OSSL_CHECK_PROCESS(process);
4368
4369         switch (XPROCESS(process)->process_type) {
4370         case PROCESS_TYPE_NETWORK:
4371                 /* ssl streams reside in ssl-conn object atm */
4372                 out = XLSTREAM(DATA_OUTSTREAM(XSSLCONN(ssl_conn)));
4373                 break;
4374         case PROCESS_TYPE_SSL:
4375                 /* ssl streams reside in process object, snarf from there */
4376                 out = XLSTREAM(DATA_OUTSTREAM(XPROCESS(process)));
4377                 break;
4378         default:
4379                 out = NULL;
4380                 error("unable to write");
4381         }
4382
4383         /* store the original process filter */
4384         proc_filter = XPROCESS(process)->filter;
4385         SXE_SET_UNUSED(proc_filter);
4386
4387         ret = Lstream_write(out, XSTRING_DATA(string), XSTRING_LENGTH(string));
4388         Lstream_flush(out);
4389
4390         switch (SSL_get_error(conn, ret)) {
4391         case SSL_ERROR_NONE:
4392                 break;
4393         case SSL_ERROR_WANT_WRITE:
4394                 error("Connection wants write");
4395         case SSL_ERROR_WANT_READ:
4396                 error("Connection wants read");
4397         default:
4398                 error("Severe SSL connection error");
4399         }
4400
4401         /* restore the original process filter */
4402         return (SSL_pending(conn) == 0) ? Qt : Qnil;
4403 }
4404
4405 /* convenience functions */
4406 DEFUN("ossl-ssl-parent", Fossl_ssl_parent, 1, 1, 0, /*
4407 Return the underlying parent layer of SSL-CONN.
4408 */
4409       (ssl_conn))
4410 {
4411         CHECK_SSLCONN(ssl_conn);
4412
4413         return XSSLCONN(ssl_conn)->parent;
4414 }
4415
4416 DEFUN("ossl-ssl-cert", Fossl_ssl_cert, 1, 1, 0, /*
4417 Return the local peer's certificate of SSL-CONN if present,
4418 `nil' otherwise.
4419 */
4420       (ssl_conn))
4421 {
4422         /* SSL connection stuff */
4423         SSL *conn = NULL;
4424         X509 *cert = NULL;
4425
4426         CHECK_SSLCONN(ssl_conn);
4427
4428         conn = XSSLCONN(ssl_conn)->ssl_conn;
4429         cert = SSL_get_certificate(conn);
4430
4431         if (cert)
4432                 return make_evp_pkey_x509(cert);
4433         else
4434                 return Qnil;
4435 }
4436
4437 DEFUN("ossl-ssl-peer-cert", Fossl_ssl_peer_cert, 1, 1, 0, /*
4438 Return the remote peer's certificate of SSL-CONN if present,
4439 `nil' otherwise.
4440 */
4441       (ssl_conn))
4442 {
4443         /* SSL connection stuff */
4444         SSL *conn = NULL;
4445         X509 *cert = NULL;
4446
4447         CHECK_SSLCONN(ssl_conn);
4448
4449         conn = XSSLCONN(ssl_conn)->ssl_conn;
4450         cert = SSL_get_peer_certificate(conn);
4451
4452         if (cert)
4453                 return make_evp_pkey_x509(cert);
4454         else
4455                 return Qnil;
4456 }
4457
4458 DEFUN("ossl-ssl-peer-cert-chain", Fossl_ssl_peer_cert_chain, 1, 1, 0, /*
4459 Return the certificate chain of SSL-CONN as a list of
4460 evp-pkey objects.
4461 */
4462       (ssl_conn))
4463 {
4464         int i;
4465         /* SSL connection stuff */
4466         SSL *conn = NULL;
4467         STACK_OF(X509) *sk;
4468         /* result cruft */
4469         Lisp_Object result = Qnil;
4470
4471         CHECK_SSLCONN(ssl_conn);
4472
4473         conn = XSSLCONN(ssl_conn)->ssl_conn;
4474         sk = SSL_get_peer_cert_chain(conn);
4475
4476         if (sk == NULL)
4477                 return result;
4478
4479         for (i=0; i<sk_X509_num(sk); i++) {
4480                 X509 *cert = sk_X509_value(sk, i);
4481
4482                 result = Fcons(make_evp_pkey_x509(cert), result);
4483         }
4484
4485         return result;
4486 }
4487
4488 #if 0
4489 DEFUN("ossl-ssl-cert-store", Fossl_ssl_cert_store, 1, 1, 0, /*
4490 Return the X509 cert store of SSL-CONN.
4491 */
4492       (ssl_conn))
4493 {
4494         X509_STORE *sto = NULL;
4495
4496         return Qnil;
4497 }
4498 #endif
4499
4500 #if 0                           /* just thoughts */
4501 int     SSL_get_verify_mode(const SSL *s);
4502 int     SSL_get_verify_depth(const SSL *s);
4503 #endif
4504
4505 DEFUN("ossl-ssl-verify-certificate", Fossl_ssl_verify_certificate,
4506       1, 1, 0, /*
4507 Return a verify code of SSL-CONN.
4508
4509 The result is a cons cell with the numeric verify code in
4510 the car and a verbose string in the cdr.
4511 */
4512       (ssl_conn))
4513 {
4514         int vrc;
4515         /* SSL connection stuff */
4516         SSL *conn = NULL;
4517         /* result cruft */
4518         Lisp_Object result = Qnil;
4519
4520         CHECK_SSLCONN(ssl_conn);
4521
4522         conn = XSSLCONN(ssl_conn)->ssl_conn;
4523         vrc = SSL_get_verify_result(conn);
4524
4525         result = Fcons(
4526                 make_int(vrc),
4527                 build_string(X509_verify_cert_error_string(vrc)));
4528
4529         return result;
4530 }
4531
4532 DEFUN("ossl-ssl-cipher-version", Fossl_ssl_cipher_version, 1, 1, 0, /*
4533 Return the protocol version of the tunnel SSL-CONN.
4534 */
4535       (ssl_conn))
4536 {
4537         /* SSL connection stuff */
4538         SSL *conn=NULL;
4539         const SSL_CIPHER *ciph;
4540         /* network stream stuff */
4541         Lisp_SSL_CONN *lisp_ssl_conn;
4542
4543         CHECK_SSLCONN(ssl_conn);
4544         lisp_ssl_conn = XSSLCONN(ssl_conn);
4545
4546         conn = lisp_ssl_conn->ssl_conn;
4547         if (conn == NULL)
4548                 return Qnil;
4549
4550         ciph = SSL_get_current_cipher(conn);
4551
4552         if (!(ciph == NULL))
4553                 return Fmake_symbol(
4554                         build_string(SSL_CIPHER_get_version(ciph)));
4555         else
4556                 return Qnil;
4557 }
4558
4559 DEFUN("ossl-ssl-cipher-name", Fossl_ssl_cipher_name, 1, 1, 0, /*
4560 Return the name of the current cipher used in the tunnel SSL-CONN.
4561 */
4562       (ssl_conn))
4563 {
4564         /* SSL connection stuff */
4565         SSL *conn=NULL;
4566         const SSL_CIPHER *ciph;
4567         /* network stream stuff */
4568         Lisp_SSL_CONN *lisp_ssl_conn;
4569
4570         CHECK_SSLCONN(ssl_conn);
4571         lisp_ssl_conn = XSSLCONN(ssl_conn);
4572
4573         conn = lisp_ssl_conn->ssl_conn;
4574         if (conn == NULL)
4575                 return Qnil;
4576
4577         ciph = SSL_get_current_cipher(conn);
4578
4579         if (!(ciph == NULL))
4580                 return intern(SSL_CIPHER_get_name(ciph));
4581         else
4582                 return Qnil;
4583 }
4584
4585 DEFUN("ossl-ssl-cipher-names", Fossl_ssl_cipher_names, 1, 1, 0, /*
4586 Return the names of all supported ciphers in the tunnel SSL-CONN.
4587 */
4588       (ssl_conn))
4589 {
4590         int i;
4591         /* SSL connection stuff */
4592         SSL *conn=NULL;
4593         STACK_OF(SSL_CIPHER) *ciphs;
4594         Lisp_Object result = Qnil;
4595
4596         CHECK_SSLCONN(ssl_conn);
4597
4598         conn = XSSLCONN(ssl_conn)->ssl_conn;
4599         if (conn == NULL)
4600                 return Qnil;
4601
4602         ciphs = SSL_get_ciphers(conn);
4603
4604         for (i=sk_SSL_CIPHER_num(ciphs)-1; i>=0; i--) {
4605                 SSL_CIPHER *ciph = sk_SSL_CIPHER_value(ciphs, i);
4606
4607                 result = Fcons(intern(SSL_CIPHER_get_name(ciph)), result);
4608         }
4609
4610         return result;
4611 }
4612
4613 DEFUN("ossl-ssl-cipher-bits", Fossl_ssl_cipher_bits, 1, 1, 0, /*
4614 Return the number of effective bits of the current cipher in SSL-CONN.
4615 */
4616       (ssl_conn))
4617 {
4618         /* SSL connection stuff */
4619         SSL *conn=NULL;
4620         const SSL_CIPHER *ciph;
4621         int alg_bits, strength_bits;
4622         /* network stream stuff */
4623         Lisp_SSL_CONN *lisp_ssl_conn;
4624
4625         CHECK_SSLCONN(ssl_conn);
4626         lisp_ssl_conn = XSSLCONN(ssl_conn);
4627
4628         conn = lisp_ssl_conn->ssl_conn;
4629         if (conn == NULL)
4630                 return Qnil;
4631
4632         ciph = SSL_get_current_cipher(conn);
4633
4634         if (!(ciph == NULL)) {
4635                 strength_bits = SSL_CIPHER_get_bits(ciph, &alg_bits);
4636                 /* what do we want to do with alg_bits? */
4637                 return make_int(strength_bits);
4638         } else
4639                 return Qnil;
4640 }
4641
4642 DEFUN("ossl-ssl-cipher-description", Fossl_ssl_cipher_description, 1, 1, 0, /*
4643 Return a description of the current cipher used in the tunnel SSL-CONN.
4644 */
4645       (ssl_conn))
4646 {
4647         /* SSL connection stuff */
4648         SSL *conn=NULL;
4649         const SSL_CIPHER *ciph;
4650         /* network stream stuff */
4651         Lisp_SSL_CONN *lisp_ssl_conn;
4652
4653         CHECK_SSLCONN(ssl_conn);
4654         lisp_ssl_conn = XSSLCONN(ssl_conn);
4655
4656         conn = lisp_ssl_conn->ssl_conn;
4657         if (conn == NULL)
4658                 return Qnil;
4659
4660         ciph = SSL_get_current_cipher(conn);
4661
4662         if (!(ciph == NULL))
4663                 return build_string(SSL_CIPHER_description(ciph, NULL, 0));
4664         else
4665                 return Qnil;
4666 }
4667
4668
4669 /* X509 cert handling */
4670 DEFUN("ossl-x509-subject", Fossl_x509_subject, 1, 1, 0, /*
4671 Return the certificate subject of CERT (an evp-pkey object).
4672
4673 This will return a string in LDAP syntax.
4674 */
4675       (cert))
4676 {
4677         X509 *pk509;
4678
4679         CHECK_EVPPKEY(cert);
4680
4681         pk509 = XEVPPKEY(cert)->x509;
4682
4683         if (pk509) {
4684                 X509_NAME *sub = X509_get_subject_name(pk509);
4685                 return build_string(X509_NAME_oneline(sub, NULL, 0));
4686         } else
4687                 return Qnil;
4688 }
4689
4690 DEFUN("ossl-x509-issuer", Fossl_x509_issuer, 1, 1, 0, /*
4691 Return the certificate issuer of CERT (an evp-pkey object),
4692 that is the organisation which signed the certificate.
4693
4694 This will return a string in LDAP syntax.
4695 */
4696       (cert))
4697 {
4698         X509 *pk509;
4699
4700         CHECK_EVPPKEY(cert);
4701
4702         pk509 = XEVPPKEY(cert)->x509;
4703
4704         if (pk509) {
4705                 X509_NAME *iss = X509_get_issuer_name(pk509);
4706                 return build_string(X509_NAME_oneline(iss, NULL, 0));
4707         } else
4708                 return Qnil;
4709 }
4710
4711 DEFUN("ossl-x509-serial", Fossl_x509_serial, 1, 1, 0, /*
4712 Return the certificate serial of CERT (an evp-pkey object).
4713 */
4714       (cert))
4715 {
4716         X509 *pk509;
4717
4718         CHECK_EVPPKEY(cert);
4719
4720         pk509 = XEVPPKEY(cert)->x509;
4721
4722         if (pk509) {
4723                 ASN1_INTEGER *ser = X509_get_serialNumber(pk509);
4724                 return make_integer(ASN1_INTEGER_get(ser));
4725         } else
4726                 return Qnil;
4727 }
4728
4729 DEFUN("ossl-x509-not-before", Fossl_x509_not_before, 1, 1, 0, /*
4730 Return the certificate valid-not-before time of CERT.
4731 */
4732       (cert))
4733 {
4734         X509 *pk509;
4735
4736         CHECK_EVPPKEY(cert);
4737
4738         pk509 = XEVPPKEY(cert)->x509;
4739
4740         if (pk509) {
4741                 ASN1_TIME *nbf = X509_get_notBefore(pk509);
4742                 return build_string((char*)nbf->data);
4743         } else
4744                 return Qnil;
4745 }
4746
4747 DEFUN("ossl-x509-not-after", Fossl_x509_not_after, 1, 1, 0, /*
4748 Return the certificate valid-not-after time of CERT.
4749 */
4750       (cert))
4751 {
4752         X509 *pk509;
4753
4754         CHECK_EVPPKEY(cert);
4755
4756         pk509 = XEVPPKEY(cert)->x509;
4757
4758         if (pk509) {
4759                 ASN1_TIME *nbf = X509_get_notAfter(pk509);
4760                 return build_string((char*)nbf->data);
4761         } else
4762                 return Qnil;
4763 }
4764
4765 DEFUN("ossl-x509-signature-type", Fossl_x509_signature_type, 1, 1, 0, /*
4766 Return the signature type of CERT.
4767 */
4768       (cert))
4769 {
4770         X509 *pk509;
4771
4772         CHECK_EVPPKEY(cert);
4773
4774         pk509 = XEVPPKEY(cert)->x509;
4775
4776         if (pk509) {
4777                 int ty = X509_get_signature_type(pk509);
4778                 Lisp_Object result = Qnil;
4779
4780                 switch (ty) {
4781                 case EVP_PKEY_NONE:
4782                         result = intern("none");
4783                         break;
4784 #ifndef OPENSSL_NO_RSA
4785                 case EVP_PKEY_RSA:
4786                         result = intern("rsa");
4787                         break;
4788                 case EVP_PKEY_RSA2:
4789                         result = intern("rsa2");
4790                         break;
4791 #endif
4792 #ifndef OPENSSL_NO_DSA
4793                 case EVP_PKEY_DSA:
4794                         result = intern("dsa");
4795                         break;
4796                 case EVP_PKEY_DSA1:
4797                         result = intern("dsa1");
4798                         break;
4799                 case EVP_PKEY_DSA2:
4800                         result = intern("dsa2");
4801                         break;
4802                 case EVP_PKEY_DSA3:
4803                         result = intern("dsa3");
4804                         break;
4805                 case EVP_PKEY_DSA4:
4806                         result = intern("dsa4");
4807                         break;
4808 #endif
4809 #ifndef OPENSSL_NO_DH
4810                 case EVP_PKEY_DH:
4811                         result = intern("dh");
4812                         break;
4813 #endif
4814 #ifndef OPENSSL_NO_EC
4815                 case EVP_PKEY_EC:
4816                         result = intern("ec");
4817                         break;
4818 #endif
4819                 default:
4820                         result = intern("unknown");
4821                         break;
4822                 }
4823
4824                 return result;
4825         } else
4826                 return Qnil;
4827 }
4828
4829
4830
4831
4832
4833 /*
4834  *
4835  * Initialisation stuff
4836  *
4837  */
4838 void syms_of_openssl(void)
4839 {
4840         INIT_LRECORD_IMPLEMENTATION(evp_pkey);
4841         INIT_LRECORD_IMPLEMENTATION(ssl_conn);
4842
4843         defsymbol(&Qopenssl, "openssl");
4844         defsymbol(&Qevp_pkeyp, "ossl-pkey-p");
4845
4846         DEFSUBR(Fossl_version);
4847         DEFSUBR(Fossl_available_digests);
4848         DEFSUBR(Fossl_available_ciphers);
4849         DEFSUBR(Fossl_digest_size);
4850         DEFSUBR(Fossl_digest_bits);
4851         DEFSUBR(Fossl_digest_block_size);
4852         DEFSUBR(Fossl_cipher_key_length);
4853         DEFSUBR(Fossl_cipher_bits);
4854         DEFSUBR(Fossl_cipher_iv_length);
4855         DEFSUBR(Fossl_cipher_block_size);
4856         DEFSUBR(Fossl_cipher_mode);
4857
4858         DEFSUBR(Fossl_rand_bytes);
4859         DEFSUBR(Fossl_rand_bytes_egd);
4860
4861         DEFSUBR(Fossl_digest);
4862         DEFSUBR(Fossl_digest_file);
4863
4864         DEFSUBR(Fossl_hmac);
4865         DEFSUBR(Fossl_hmac_file);
4866
4867         DEFSUBR(Fossl_bytes_to_key);
4868         DEFSUBR(Fossl_encrypt);
4869         DEFSUBR(Fossl_encrypt_file);
4870         DEFSUBR(Fossl_decrypt);
4871         DEFSUBR(Fossl_decrypt_file);
4872
4873         /* general pkey */
4874         DEFSUBR(Fossl_pkey_p);
4875         DEFSUBR(Fossl_pkey_size);
4876         DEFSUBR(Fossl_pkey_private_p);
4877         DEFSUBR(Fossl_pkey_get_public);
4878
4879 #ifndef OPENSSL_NO_RSA
4880         /* RSA */
4881         DEFSUBR(Fossl_rsa_generate_key);
4882         DEFSUBR(Fossl_rsa_pkey_p);
4883         DEFSUBR(Fossl_rsa_subkey_p);
4884 #endif /* OPENSSL_NO_RSA */
4885 #ifndef OPENSSL_NO_DSA
4886         /* DSA */
4887         DEFSUBR(Fossl_dsa_generate_key);
4888         DEFSUBR(Fossl_dsa_pkey_p);
4889         DEFSUBR(Fossl_dsa_subkey_p);
4890 #endif /* OPENSSL_NO_DSA */
4891 #ifndef OPENSSL_NO_EC
4892         /* EC */
4893         DEFSUBR(Fossl_ec_available_curves);
4894         DEFSUBR(Fossl_ec_generate_key);
4895         DEFSUBR(Fossl_ec_pkey_p);
4896 #endif /* OPENSSL_NO_EC */
4897 #ifndef OPENSSL_NO_DH
4898         /* DH */
4899         /* DEFSUBR(Fossl_ec_generate_key); */
4900         DEFSUBR(Fossl_dh_pkey_p);
4901 #endif
4902         DEFSUBR(Fossl_seal);
4903         DEFSUBR(Fossl_open);
4904
4905         DEFSUBR(Fossl_sign);
4906         DEFSUBR(Fossl_verify);
4907
4908 /* PEM */
4909         DEFSUBR(Fossl_pem_read_public_key);
4910         DEFSUBR(Fossl_pem_read_key);
4911         DEFSUBR(Fossl_pem_write_public_key);
4912         DEFSUBR(Fossl_pem_write_key);
4913         DEFSUBR(Fossl_pem_public_key);
4914         DEFSUBR(Fossl_pem_key);
4915
4916 /* SSL */
4917         defsymbol(&Qssl_connp, "ossl-ssl-conn-p");
4918         defsymbol(&Qssl2, "ssl2");
4919         defsymbol(&Qssl23, "ssl23");
4920         defsymbol(&Qssl3, "ssl3");
4921         defsymbol(&Qtls1, "tls1");
4922 #ifdef HAVE_SOCKETS
4923         DEFSUBR(Fossl_ssl_handshake);
4924         DEFSUBR(Fossl_ssl_inject_ca);
4925         DEFSUBR(Fossl_ssl_inject_cert);
4926         DEFSUBR(Fossl_ssl_proselytise_process);
4927         DEFSUBR(Fossl_ssl_unproselytise_process);
4928         DEFSUBR(Fossl_ssl_connect);
4929         DEFSUBR(Fossl_ssl_finish);
4930         DEFSUBR(Fossl_ssl_read);
4931         DEFSUBR(Fossl_ssl_write);
4932         DEFSUBR(Fossl_ssl_parent);
4933         DEFSUBR(Fossl_ssl_cert);
4934         DEFSUBR(Fossl_ssl_peer_cert);
4935         DEFSUBR(Fossl_ssl_peer_cert_chain);
4936         DEFSUBR(Fossl_ssl_verify_certificate);
4937         DEFSUBR(Fossl_ssl_cipher_version);
4938         DEFSUBR(Fossl_ssl_cipher_name);
4939         DEFSUBR(Fossl_ssl_cipher_names);
4940         DEFSUBR(Fossl_ssl_cipher_bits);
4941         DEFSUBR(Fossl_ssl_cipher_description);
4942 #endif
4943
4944         DEFSUBR(Fossl_x509_subject);
4945         DEFSUBR(Fossl_x509_issuer);
4946         DEFSUBR(Fossl_x509_serial);
4947         DEFSUBR(Fossl_x509_not_before);
4948         DEFSUBR(Fossl_x509_not_after);
4949         DEFSUBR(Fossl_x509_signature_type);
4950
4951 /* Problem ciphers */
4952         defsymbol(&QAES_256_XTS, "AES-256-XTS");
4953         defsymbol(&QAES_128_XTS, "AES-128-XTS");
4954         defsymbol(&Qid_aes256_CCM, "id-aes256-CCM");
4955         defsymbol(&Qid_aes256_GCM, "id-aes256-GCM");
4956         defsymbol(&Qid_aes192_CCM, "id-aes192-CCM");
4957         defsymbol(&Qid_aes192_GCM, "id-aes192-GCM");
4958         defsymbol(&Qid_aes128_CCM, "id-aes128-CCM");
4959         defsymbol(&Qid_aes128_GCM, "id-aes128-GCM");
4960         defsymbol(&Qid_aes256_wrap, "id-aes256-wrap");
4961         defsymbol(&Qid_aes192_wrap, "id-aes192-wrap");
4962         defsymbol(&Qid_aes128_wrap, "id-aes128-wrap");
4963         defsymbol(&QCAMELLIA_256_CFB8, "CAMELLIA-256-CFB8");
4964         defsymbol(&QCAMELLIA_192_CFB8, "CAMELLIA-192-CFB8");
4965         defsymbol(&QCAMELLIA_128_CFB8, "CAMELLIA-128-CFB8");
4966         defsymbol(&QCAMELLIA_256_CFB1, "CAMELLIA-256-CFB1");
4967         defsymbol(&QCAMELLIA_192_CFB1, "CAMELLIA-192-CFB1");
4968         defsymbol(&QCAMELLIA_128_CFB1, "CAMELLIA-128-CFB1");
4969         defsymbol(&QDES_EDE3_CFB8, "DES-EDE3-CFB8");
4970         defsymbol(&QDES_EDE3_CFB1, "DES-EDE3-CFB1");
4971         defsymbol(&QDES_CFB8, "DES-CFB8");
4972         defsymbol(&QDES_CFB1, "DES-CFB1");
4973         defsymbol(&QAES_256_CFB8, "AES-256-CFB8");
4974         defsymbol(&QAES_192_CFB8, "AES-192-CFB8");
4975         defsymbol(&QAES_128_CFB8, "AES-128-CFB8");
4976         defsymbol(&QAES_256_CFB1, "AES-256-CFB1");
4977         defsymbol(&QAES_192_CFB1, "AES-192-CFB1");
4978         defsymbol(&QAES_128_CFB1, "AES-128-CFB1");
4979         defsymbol(&Qid_smime_alg_CMS3DESwrap, "id-smime-alg-CMS3DESwrap");
4980 }
4981
4982 void vars_of_openssl(void)
4983 {
4984         DEFVAR_LISP("ossl-cipher-blacklist", &Vossl_cipher_blacklist /*
4985 A list of ciphers that are blacklisted against use.
4986
4987 These are ciphers that are known to cause problems with the SXEmacs
4988 OpenSSL code that can result in data corruption.  If you find that you
4989 need to use one or more of the ciphers on this list, you can do so by
4990 removing it from this list first.  Do we need to mention that this is 
4991 probably not a good idea and that you are well and truly on your own
4992 here?  But hey, it's your data...
4993                                                                      */);
4994
4995         Lisp_Object badCiphers[28] = {
4996                 QAES_256_XTS, QAES_128_XTS, Qid_aes256_CCM, Qid_aes256_GCM,
4997                 Qid_aes192_CCM, Qid_aes192_GCM, Qid_aes128_CCM, Qid_aes128_GCM,
4998                 Qid_aes256_wrap, Qid_aes192_wrap, Qid_aes128_wrap,
4999                 QCAMELLIA_256_CFB8, QCAMELLIA_192_CFB8, QCAMELLIA_128_CFB8,
5000                 QCAMELLIA_256_CFB1, QCAMELLIA_192_CFB1, QCAMELLIA_128_CFB1,
5001                 QDES_EDE3_CFB8, QDES_EDE3_CFB1, QDES_CFB8, QDES_CFB1,
5002                 QAES_256_CFB8, QAES_192_CFB8, QAES_128_CFB8, QAES_256_CFB1,
5003                 QAES_192_CFB1, QAES_128_CFB1, Qid_smime_alg_CMS3DESwrap };
5004         Vossl_cipher_blacklist = Flist(28, badCiphers);
5005
5006         Fprovide(Qopenssl);
5007
5008 #ifndef OPENSSL_NO_RSA
5009         Fprovide(intern("openssl-rsa"));
5010 #endif
5011 #ifndef OPENSSL_NO_DSA
5012         Fprovide(intern("openssl-dsa"));
5013 #endif
5014 #ifndef OPENSSL_NO_EC
5015         Fprovide(intern("openssl-ec"));
5016 #endif
5017 #ifndef OPENSSL_NO_DH
5018         Fprovide(intern("openssl-dh"));
5019 #endif
5020 #ifdef HAVE_SOCKETS
5021         Fprovide(intern("openssl-ssl"));
5022 #endif
5023 }