2 openssl.c -- Emacs Lisp binding to OpenSSL ciphers and digests
3 Copyright (C) 2005, 2006 Sebastian Freundt
5 Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 This file is part of SXEmacs
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.
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.
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/>. */
23 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
24 * All rights reserved.
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.
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).
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.
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
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)"
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
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.]
81 * openssl provides an assortment of cryptographic routines and interfaces
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.
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
101 * In addition, we are trying hard to provide not only an exact elisp
102 * copy of openssl, but also a _comprehensive_ one
105 * * src/openssl.c: functions overview:
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
115 * ossl-rand-bytes - generation of (pseudo) randomness
118 * ossl-digest - gateway to digest functions
121 * ossl-hmac - gateway to message authentication codes
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
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
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
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
143 * ossl-ec-generate-key - constructor of EC public keys
144 * ossl-ec-pkey-p - discriminator of EC public keys
146 * ossl-dh-pkey-p - discriminator of DH public keys
149 * ossl-seal - gateway to public key hybrid (envelope) encryption
150 * ossl-open - gateway to public key hybrid (envelope) decryption
153 * ossl-sign - gateway to public key signature
154 * ossl-verify - gateway to public key signature verification
157 * ossl-pem-read-public-key
159 * ossl-pem-write-public-key
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
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
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
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
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
200 * - any function using or needing random data assumes you have /dev/urandom
206 * (ossl-rand-bytes 8)
207 * (base16-encode-string (ossl-rand-bytes 16))
210 * (ossl-available-digests)
212 * (ossl-digest 'MD5 "test")
213 * (base16-encode-string (ossl-digest 'MD5 "test"))
217 * (base64-encode-string (ossl-digest 'SHA1 "test"))
219 * (base16-encode-string (ossl-digest 'RIPEMD160 "test"))
222 * (ossl-hmac 'md5 "testmess" "testpass")
224 * (base16-encode-string (ossl-hmac 'dsa-sha1 "testmess" "testpass"))
227 * ;; retrieve a list of available cipher algorithms first
228 * (ossl-available-ciphers)
230 * ;; generate a key/iv pair (iv = initialisation vector)
232 * (ossl-bytes-to-key 'AES-256-ECB 'RIPEMD160 nil "password" 1)
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))
240 * (ossl-decrypt 'BF-ECB enc (car key) (cdr key))
241 * ;; this one yields an error since BF-CBC is not BF-ECB
248 * ;; generate an rsa key of size 2048
249 * (setq pkey (ossl-rsa-generate-key 2048 17))
250 * (ossl-rsa-pkey-p pkey)
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)
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)
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)
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))
285 * Note: For these functions you must have enabled DH in your OpenSSL lib
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))
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
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!
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)
305 * (ossl-verify 'DSA-SHA1 "this is not MY msg" sig key)
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)
312 * (ossl-verify 'RSA-SHA1 "this is MY msg" sig2 key)
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)
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)
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)
348 #include "events/events.h"
350 #include "procimpl.h"
358 #include "mule/file-coding.h"
361 #ifdef HAVE_POSTGRESQL
362 #include "database/postgresql.h"
365 #define OSSL_CODING Qbinary
367 #define OSSL_STRING_LENGTH XSTRING_CHAR_LENGTH
369 static Lisp_Object Qopenssl;
371 #define __OSSL_DEBUG__(args...) fprintf(stderr, "OSSL " args)
372 #ifndef OSSL_DEBUG_FLAG
373 #define OSSL_DEBUG(args...)
375 #define OSSL_DEBUG(args...) __OSSL_DEBUG__(args)
377 #define OSSL_DEBUG_CTX(args...) OSSL_DEBUG("[connection]: " args)
378 #define OSSL_CRITICAL(args...) __OSSL_DEBUG__("CRITICAL: " args)
381 int ossl_pkey_has_public_data(EVP_PKEY *pkey);
382 int ossl_pkey_has_private_data(EVP_PKEY *pkey);
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);
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);
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);
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);
412 #ifdef OSSL_DEBUG_FLAG
413 static long ossl_bio_dump_callback(BIO*, int, const char*, int, long, long);
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);
423 Lisp_Object Qssl2, Qssl23, Qssl3, Qtls1;
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);
438 extern Lisp_Object Qfile_readable_p;
439 extern Lisp_Object Qfile_writable_p;
446 DEFUN("ossl-version", Fossl_version, 0, 0, 0, /*
447 Return a descriptive version number of the OpenSSL in use.
451 return build_string(SSLeay_version(SSLEAY_VERSION));
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.
466 OpenSSL_add_all_digests();
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);
472 digests = Fcons(intern(OBJ_nid2sn(nid)), digests);
482 ossl_check_cipher(Lisp_Object cipher)
484 if (!NILP(Fmember(cipher, Vossl_cipher_blacklist))) {
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.
500 OpenSSL_add_all_ciphers();
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);
508 (ossl_check_cipher(intern(OBJ_nid2sn(nid))) == 0)) {
509 ciphers = Fcons(intern(OBJ_nid2sn(nid)), ciphers);
519 #define ossl_digest_fun(var, fun) \
522 const EVP_MD *__md; \
524 OpenSSL_add_all_digests(); \
526 __md = EVP_get_digestbyname( \
527 (char *)string_data(XSYMBOL(var)->name)); \
542 ossl_digest_size(Lisp_Object digest)
544 ossl_digest_fun(digest, EVP_MD_size);
548 ossl_digest_block_size(Lisp_Object digest)
550 ossl_digest_fun(digest, EVP_MD_block_size);
553 DEFUN("ossl-digest-size", Fossl_digest_size, 1, 1, 0, /*
554 Return the hash length of DIGEST in bytes.
558 int size = ossl_digest_size(digest);
561 error ("no such digest");
563 return make_int(size);
567 DEFUN("ossl-digest-bits", Fossl_digest_bits, 1, 1, 0, /*
568 Return the number of effective output bits of DIGEST.
572 int size = ossl_digest_size(digest);
575 error ("no such digest");
577 return make_int(size*8);
580 DEFUN("ossl-digest-block-size", Fossl_digest_block_size, 1, 1, 0, /*
581 Return the block size of DIGEST in bytes.
585 int size = ossl_digest_block_size(digest);
588 error ("no such digest");
590 return make_int(size);
594 #define ossl_cipher_fun(var, fun) \
597 const EVP_CIPHER *__ciph; \
599 if (ossl_check_cipher(var) != 0) \
600 error("use of blacklisted cipher prohibited"); \
602 OpenSSL_add_all_ciphers(); \
604 __ciph = EVP_get_cipherbyname( \
605 (char *)string_data(XSYMBOL(var)->name)); \
612 __kl = fun(__ciph); \
620 ossl_cipher_key_length(Lisp_Object cipher)
622 ossl_cipher_fun(cipher, EVP_CIPHER_key_length);
626 ossl_cipher_iv_length(Lisp_Object cipher)
628 ossl_cipher_fun(cipher, EVP_CIPHER_iv_length);
632 ossl_cipher_block_size(Lisp_Object cipher)
634 ossl_cipher_fun(cipher, EVP_CIPHER_block_size);
638 ossl_cipher_mode(Lisp_Object cipher)
640 ossl_cipher_fun(cipher, EVP_CIPHER_mode);
643 DEFUN("ossl-cipher-key-length", Fossl_cipher_key_length, 1, 1, 0, /*
644 Return the effective key length of CIPHER in bytes.
648 int size = ossl_cipher_key_length(cipher);
651 error ("no such cipher");
653 return make_int(size);
657 DEFUN("ossl-cipher-bits", Fossl_cipher_bits, 1, 1, 0, /*
658 Return the effective key size of CIPHER in bits.
662 int size = ossl_cipher_key_length(cipher);
665 error ("no such cipher");
667 return make_int(size*8);
670 DEFUN("ossl-cipher-iv-length", Fossl_cipher_iv_length, 1, 1, 0, /*
671 Return the initialisation vector length of CIPHER in bytes.
675 int size = ossl_cipher_iv_length(cipher);
678 error ("no such cipher");
680 return make_int(size);
683 DEFUN("ossl-cipher-block-size", Fossl_cipher_block_size, 1, 1, 0, /*
684 Return the block size of CIPHER in bytes.
688 int size = ossl_cipher_block_size(cipher);
691 error ("no such cipher");
693 return make_int(size);
696 DEFUN("ossl-cipher-mode", Fossl_cipher_mode, 1, 1, 0, /*
697 Return the operation mode of CIPHER.
701 Lisp_Object result = Qnil;
702 int mode = ossl_cipher_mode(cipher);
705 error ("no such cipher");
708 case EVP_CIPH_STREAM_CIPHER:
709 result = intern("stream");
711 case EVP_CIPH_ECB_MODE:
712 result = intern("ecb");
714 case EVP_CIPH_CBC_MODE:
715 result = intern("cbc");
717 case EVP_CIPH_CFB_MODE:
718 result = intern("cfb");
720 case EVP_CIPH_OFB_MODE:
721 result = intern("ofb");
724 result = intern("cbc");
737 DEFUN("ossl-rand-bytes", Fossl_rand_bytes, 1, 1, 0, /*
738 Return COUNT bytes of randomness.
740 Note: You probably want to put a wrapping encoder function
741 \(like `base16-encode-string'\) around it, since this returns
747 Lisp_Object l_outbuf;
750 int speccount = specpdl_depth(), res;
753 count_ext = (int)XINT(count);
755 /* now allocate some output buffer externally */
756 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, count_ext, char);
758 res = RAND_bytes((unsigned char*)outbuf, count_ext);
760 error("RAND_bytes did not have enough seed "
761 "to perform operation");
763 } else if (res < 0) {
764 error("RAND_bytes failed");
768 l_outbuf = make_ext_string(outbuf, count_ext, OSSL_CODING);
769 XMALLOC_UNBIND(outbuf, count_ext, speccount);
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.
778 Note: You probably want to put a wrapping encoder function
779 \(like `base16-encode-string'\) around it, since this returns
784 /* This function can GC */
786 Lisp_Object l_outbuf;
788 int speccount = specpdl_depth(), res;
790 struct gcpro gcpro1, gcpro2;
797 egd = Fexpand_file_name(egd, Qnil);
798 if (NILP(Ffile_exists_p(egd)))
801 count_ext = XINT(count);
803 /* now allocate some output buffer externally */
804 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, count_ext, char);
807 res = RAND_query_egd_bytes((char*)XSTRING_DATA(egd),
808 (unsigned char*)outbuf, count_ext);
810 res = RAND_query_egd_bytes("/var/run/egd-pool",
811 (unsigned char*)outbuf, count_ext);
815 error("RAND_query_egd_bytes did not have enough seed "
816 "to perform operation");
818 } else if (res < 0) {
820 error("RAND_query_egd_bytes failed");
824 l_outbuf = make_ext_string(outbuf, count_ext, OSSL_CODING);
825 XMALLOC_UNBIND(outbuf, count_ext, speccount);
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'.
841 Note: You probably want to put a wrapping encoder function
842 \(like `base16-encode-string'\) around it, since this returns
849 char md_value[EVP_MAX_MD_SIZE];
852 CHECK_SYMBOL(digest);
853 CHECK_STRING(string);
855 OpenSSL_add_all_digests();
856 md = EVP_get_digestbyname(
857 (char *)string_data(XSYMBOL(digest)->name));
861 error ("no such digest");
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);
875 return make_ext_string(md_value, md_len, OSSL_CODING);
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'.
883 Note: You probably want to put a wrapping encoder function
884 \(like `base16-encode-string'\) around it, since this returns
891 unsigned char md_value[EVP_MAX_MD_SIZE];
892 unsigned int md_len, md_blocksize;
898 CHECK_SYMBOL(digest);
902 file = Fexpand_file_name(file, Qnil);
904 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
905 (fseek(fp, 0, SEEK_SET))) {
908 return wrong_type_argument(Qfile_readable_p, file);
911 OpenSSL_add_all_digests();
912 md = EVP_get_digestbyname(
913 (char *)string_data(XSYMBOL(digest)->name));
918 error ("no such digest");
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);
926 EVP_DigestInit_ex(mdctx, md, NULL);
928 /* we reuse md_value here for streaming over fp */
930 n = fread(md_value, 1, EVP_MAX_MD_SIZE, fp);
935 error("file corrupted");
938 EVP_DigestUpdate(mdctx, md_value, n);
941 EVP_DigestFinal_ex(mdctx, md_value, &md_len);
942 EVP_MD_CTX_cleanup(mdctx);
948 return make_ext_string((char *)md_value, md_len, OSSL_CODING);
954 * HMAC (aka keyed hashes)
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.
961 Note: You probably want to put a wrapping encoder function
962 \(like `base16-encode-string'\) around it, since this returns
965 (digest, msg, password))
970 /* buffer for the ciphertext */
971 unsigned char outbuf[EVP_MAX_MD_SIZE];
973 /* buffer for external password */
975 unsigned int password_len;
977 /* buffer for external message */
979 unsigned int msg_len;
982 CHECK_SYMBOL(digest);
984 CHECK_STRING(password);
986 OpenSSL_add_all_digests();
987 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
991 error ("no such digest");
994 TO_EXTERNAL_FORMAT (LISP_STRING, password,
995 C_STRING_ALLOCA, password_ext, OSSL_CODING);
996 password_len = OSSL_STRING_LENGTH(password);
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);
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);
1015 return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
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.
1022 Note: You probably want to put a wrapping encoder function
1023 \(like `base16-encode-string'\) around it, since this returns
1026 (digest, file, password))
1031 /* buffer for the ciphertext */
1032 unsigned char outbuf[EVP_MAX_MD_SIZE];
1033 unsigned int outlen;
1035 /* buffer for external password */
1037 unsigned int password_len;
1041 CHECK_SYMBOL(digest);
1043 CHECK_STRING(password);
1045 file = Fexpand_file_name(file, Qnil);
1047 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1048 (fseek(fp, 0, SEEK_SET))) {
1051 return wrong_type_argument(Qfile_readable_p, file);
1055 OpenSSL_add_all_digests();
1056 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
1060 error ("no such digest");
1063 TO_EXTERNAL_FORMAT (LISP_STRING, password,
1064 C_STRING_ALLOCA, password_ext, OSSL_CODING);
1065 password_len = OSSL_STRING_LENGTH(password);
1067 hmacctx = xnew(HMAC_CTX);
1068 HMAC_CTX_init(hmacctx);
1069 HMAC_Init(hmacctx, password_ext, password_len, md);
1071 /* we reuse md_value here for streaming over fp */
1073 n = fread(outbuf, 1, EVP_MAX_MD_SIZE, fp);
1078 error("file corrupted");
1081 HMAC_Update(hmacctx, outbuf, n);
1084 HMAC_Final(hmacctx, outbuf, &outlen);
1085 HMAC_CTX_cleanup(hmacctx);
1091 return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
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.
1105 CIPHER \(a symbol\) is the cipher to derive the key and IV for.
1106 Valid ciphers can be obtained by `ossl-available-ciphers'.
1108 DIGEST \(a symbol\) is the message digest to use.
1109 Valid digests can be obtained by `ossl-available-digests'.
1111 SALT \(string or `nil'\) is used as a salt in the derivation.
1112 Use `nil' here to indicate that no salt is used.
1114 PASSWORD is an arbitrary string which is processed to derive a
1117 COUNT \(a positive integer\) is the iteration count to use. This
1118 indicates how often the hash algorithm is called recursively.
1120 Note: You probably want to put a wrapping encoder function
1121 \(like `base16-encode-string'\) around it, since this returns
1124 (cipher, digest, salt, password, count))
1127 const EVP_CIPHER *ciph;
1128 const char *salt_ext;
1131 unsigned int password_len;
1133 char key[EVP_MAX_KEY_LENGTH];
1134 char iv[EVP_MAX_IV_LENGTH];
1138 CHECK_STRING(password);
1139 CHECK_SYMBOL(cipher);
1140 CHECK_SYMBOL(digest);
1141 CHECK_NATNUM(count);
1143 if (ossl_check_cipher(cipher) != 0)
1144 error("use of blacklisted cipher prohibited");
1147 error ("count has to be a non-zero positive integer");
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));
1157 error ("no such cipher");
1162 error ("no such digest");
1169 TO_EXTERNAL_FORMAT (LISP_STRING, salt,
1170 C_STRING_ALLOCA, salt_ext, OSSL_CODING);
1174 TO_EXTERNAL_FORMAT (LISP_STRING, password,
1175 C_STRING_ALLOCA, password_ext, OSSL_CODING);
1176 password_len = OSSL_STRING_LENGTH(password);
1178 EVP_BytesToKey(ciph, md, (const unsigned char *)salt_ext,
1179 (const unsigned char *)password_ext, password_len,
1181 (unsigned char *)key,
1182 (unsigned char *)iv);
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));
1194 DEFUN("ossl-encrypt", Fossl_encrypt, 3, 4, 0, /*
1195 Return the cipher of STRING computed by CIPHER under KEY.
1197 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1198 you have compiled. See `ossl-available-ciphers'.
1200 STRING is the text to be encrypted.
1202 KEY should be a key generated suitably for this cipher, for example
1203 by `ossl-bytes-to-key'.
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.
1210 Note: You probably want to put a wrapping encoder function
1211 \(like `base16-encode-string'\) around it, since this returns
1214 (cipher, string, key, iv))
1216 /* buffer for the external string */
1218 unsigned int string_len;
1219 /* buffer for the ciphertext */
1222 Lisp_Object l_outbuf;
1223 /* buffer for key */
1228 /* declarations for the cipher */
1229 const EVP_CIPHER *ciph;
1230 EVP_CIPHER_CTX *ciphctx;
1233 int speccount = specpdl_depth();
1236 /* frob the IV from the plist of key maybe */
1238 iv = Fget(key, intern("iv"), Qnil);
1240 CHECK_SYMBOL(cipher);
1241 CHECK_STRING(string);
1245 if (ossl_check_cipher(cipher) != 0)
1246 error("use of blacklisted cipher prohibited");
1248 TO_EXTERNAL_FORMAT(LISP_STRING, string,
1249 C_STRING_ALLOCA, string_ext, OSSL_CODING);
1250 string_len = OSSL_STRING_LENGTH(string);
1252 if (string_len <= 0)
1253 error ("string must be of non-zero positive length.");
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));
1263 error ("no such cipher");
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
1270 alloclen = XSTRING_LENGTH(string) + EVP_CIPHER_block_size(ciph);
1271 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
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);
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)) {
1285 error ("error in EncryptInit");
1287 if (!EVP_EncryptUpdate(ciphctx,
1288 (unsigned char *)outbuf, &outlen,
1289 (unsigned char *)string_ext, string_len)) {
1292 error ("error in EncryptUpdate");
1294 /* Buffer passed to EVP_EncryptFinal() must be after data just
1295 * encrypted to avoid overwriting it.
1297 if (!EVP_EncryptFinal(ciphctx,
1298 (unsigned char *)outbuf+outlen, &tmplen)) {
1301 error ("error in EncryptFinal");
1303 /* added probable padding space to the length of the output buffer */
1305 EVP_CIPHER_CTX_cleanup(ciphctx);
1307 l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1308 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1316 DEFUN("ossl-encrypt-file", Fossl_encrypt_file, 3, 5, 0, /*
1317 Return the encrypted contents of FILE computed by CIPHER under KEY.
1319 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1320 you have compiled. See `ossl-available-ciphers'.
1322 FILE is the file to be encrypted.
1324 Third argument KEY should be a key generated suitably for this
1325 cipher, for example by `ossl-bytes-to-key'.
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.
1332 Optional fifth argument OUTFILE may specify a file to have the
1333 encrypted data redirected.
1335 Note: You probably want to put a wrapping encoder function
1336 \(like `base16-encode-string'\) around it, since this returns
1339 (cipher, file, key, iv, outfile))
1341 /* buffer for the external string */
1342 unsigned char string_in[1024];
1344 unsigned int block_len;
1345 unsigned long file_size;
1346 /* buffer for the ciphertext */
1347 unsigned char *outbuf;
1350 Lisp_Object l_outbuf;
1351 /* buffer for key */
1361 /* declarations for the cipher */
1362 const EVP_CIPHER *ciph;
1363 EVP_CIPHER_CTX *ciphctx;
1366 int speccount = specpdl_depth();
1369 /* frob the IV from the plist of key maybe */
1371 iv = Fget(key, intern("iv"), Qnil);
1373 CHECK_SYMBOL(cipher);
1378 if (ossl_check_cipher(cipher) != 0)
1379 error("use of blacklisted cipher prohibited");
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);
1390 file = Fexpand_file_name(file, Qnil);
1391 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1392 (fseek(fp, 0, SEEK_SET))) {
1397 return wrong_type_argument(Qfile_readable_p, file);
1400 fseek(fp, 0, SEEK_END);
1401 file_size = ftell(fp);
1402 fseek(fp, 0, SEEK_SET);
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));
1416 error ("no such cipher");
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
1423 block_len = EVP_CIPHER_block_size(ciph);
1424 if (UNLIKELY(of != NULL)) {
1427 alloclen = file_size + block_len;
1429 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
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);
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)) {
1446 error("error in EncryptInit");
1452 string_len = fread(string_in, 1, 1024, fp);
1453 if (string_len < 0) {
1459 error("file corrupted");
1464 if (string_len > 0 &&
1465 !EVP_EncryptUpdate(ciphctx,
1467 string_in, string_len)) {
1473 error("error in EncryptUpdate");
1477 fwrite(obp, 1, tmplen, of);
1482 } while (string_len > 0);
1484 /* Buffer passed to EVP_EncryptFinal() must be after data just
1485 * encrypted to avoid overwriting it.
1487 if (!EVP_EncryptFinal(ciphctx, obp, &tmplen)) {
1493 error("error in EncryptFinal");
1497 fwrite(obp, 1, tmplen, of);
1499 /* added probable padding space to the length of the output buffer */
1501 EVP_CIPHER_CTX_cleanup(ciphctx);
1503 if (UNLIKELY(of != NULL)) {
1506 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1508 XMALLOC_UNBIND(outbuf, alloclen, speccount);
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")
1525 DEFUN("ossl-decrypt", Fossl_decrypt, 3, 4, 0, /*
1526 Return the deciphered version of STRING computed by CIPHER under KEY.
1528 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1529 you have compiled. See `ossl-available-ciphers'.
1531 STRING is the text to be decrypted.
1533 KEY should be a key generated suitably for this
1534 cipher, for example by `ossl-bytes-to-key'.
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.
1541 (cipher, string, key, iv))
1543 /* buffer for the external string */
1545 unsigned int string_len;
1546 /* buffer for the deciphered text */
1549 Lisp_Object l_outbuf;
1550 /* buffer for key */
1555 /* declarations for the decipher */
1556 const EVP_CIPHER *ciph;
1557 EVP_CIPHER_CTX *ciphctx;
1560 int speccount = specpdl_depth();
1563 /* frob the IV from the plist of key maybe */
1565 iv = Fget(key, intern("iv"), Qnil);
1567 CHECK_SYMBOL(cipher);
1568 CHECK_STRING(string);
1572 if (ossl_check_cipher(cipher) != 0)
1573 error("use of blacklisted cipher prohibited");
1575 TO_EXTERNAL_FORMAT(LISP_STRING, string,
1576 C_STRING_ALLOCA, string_ext, OSSL_CODING);
1577 string_len = OSSL_STRING_LENGTH(string);
1580 error ("string must be of non-zero positive length.");
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));
1590 error ("no such cipher");
1593 /* now allocate some output buffer externally */
1594 alloclen = XSTRING_LENGTH(string);
1595 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
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);
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)) {
1609 error ("error in DecryptInit");
1611 if (!EVP_DecryptUpdate(ciphctx,
1612 (unsigned char *)outbuf, &outlen,
1613 (unsigned char *)string_ext,string_len)) {
1616 error ("error in DecryptUpdate");
1618 /* Buffer passed to EVP_EncryptFinal() must be after data just
1619 * encrypted to avoid overwriting it.
1621 if (!EVP_DecryptFinal(ciphctx,
1622 (unsigned char *)outbuf+outlen, &tmplen)) {
1625 error ("error in DecryptFinal");
1627 /* added probable padding space to the length of the output buffer */
1629 EVP_CIPHER_CTX_cleanup(ciphctx);
1631 l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1632 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1640 DEFUN("ossl-decrypt-file", Fossl_decrypt_file, 3, 5, 0, /*
1641 Return the deciphered version of FILE computed by CIPHER under KEY.
1643 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1644 you have compiled. See `ossl-available-ciphers'.
1646 FILE is the file to be decrypted.
1648 Third argument KEY should be a key generated suitably for this
1649 cipher, for example by `ossl-bytes-to-key'.
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.
1656 Optional fifth argument OUTFILE may specify a file to have the
1657 encrypted data redirected.
1659 (cipher, file, key, iv, outfile))
1661 /* buffer for the external string */
1662 unsigned char string_in[1024];
1664 unsigned int block_len;
1665 unsigned long file_size;
1666 /* buffer for the deciphered text */
1667 unsigned char *outbuf;
1670 Lisp_Object l_outbuf;
1671 /* buffer for key */
1681 /* declarations for the decipher */
1682 const EVP_CIPHER *ciph;
1683 EVP_CIPHER_CTX *ciphctx;
1686 int speccount = specpdl_depth();
1689 /* frob the IV from the plist of key maybe */
1691 iv = Fget(key, intern("iv"), Qnil);
1693 CHECK_SYMBOL(cipher);
1698 if (ossl_check_cipher(cipher) != 0)
1699 error("use of blacklisted cipher prohibited");
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);
1710 file = Fexpand_file_name(file, Qnil);
1711 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1712 (fseek(fp, 0, SEEK_SET))) {
1717 return wrong_type_argument(Qfile_readable_p, file);
1720 fseek(fp, 0, SEEK_END);
1721 file_size = ftell(fp);
1722 fseek(fp, 0, SEEK_SET);
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));
1736 error ("no such cipher");
1739 /* now allocate some output buffer externally */
1740 block_len = EVP_CIPHER_block_size(ciph);
1741 if (UNLIKELY(of != NULL)) {
1744 alloclen = file_size + block_len;
1746 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
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);
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)) {
1763 error ("error in DecryptInit");
1769 string_len = fread(string_in, 1, 1024, fp);
1770 if (string_len < 0) {
1776 error("file corrupted");
1781 if (string_len > 0 &&
1782 !EVP_DecryptUpdate(ciphctx,
1784 string_in, string_len)) {
1790 error ("error in DecryptUpdate");
1794 fwrite(obp, 1, tmplen, of);
1799 } while (string_len > 0);
1801 /* Buffer passed to EVP_EncryptFinal() must be after data just
1802 * encrypted to avoid overwriting it.
1804 if (!EVP_DecryptFinal(ciphctx, obp, &tmplen)) {
1810 error ("error in DecryptFinal");
1814 fwrite(obp, 1, tmplen, of);
1816 /* added probable padding space to the length of the output buffer */
1818 EVP_CIPHER_CTX_cleanup(ciphctx);
1820 if (UNLIKELY(of != NULL)) {
1823 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1825 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1842 /* This is an opaque object for storing PKEYs in lisp */
1843 Lisp_Object Qevp_pkeyp;
1846 mark_evp_pkey(Lisp_Object obj)
1848 /* avoid some warning */
1854 print_evp_pkey(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1859 pkey = XEVPPKEY(obj)->evp_pkey;
1860 x509 = XEVPPKEY(obj)->x509;
1862 write_c_string("#<OpenSSL", printcharfun);
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);
1876 write_c_string(";", printcharfun);
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);
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);
1890 write_c_string(" empty key", printcharfun);
1892 if (EVP_PKEY_size(pkey) > 0) {
1893 write_fmt_str(printcharfun, ", size %d", EVP_PKEY_size(pkey)*8);
1897 write_c_string(">", printcharfun);
1899 /* avoid some warning */
1903 static Lisp_EVP_PKEY *
1904 allocate_evp_pkey(void)
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;
1914 finalise_evp_pkey(void *header, int for_disksave)
1916 Lisp_EVP_PKEY *evp_pkey = (Lisp_EVP_PKEY *) header;
1918 if (evp_pkey->evp_pkey) {
1919 EVP_PKEY_free(evp_pkey->evp_pkey);
1920 evp_pkey->evp_pkey = NULL;
1922 if (evp_pkey->x509) {
1923 X509_free(evp_pkey->x509);
1924 evp_pkey->x509 = NULL;
1927 /* avoid some warning */
1931 DEFINE_LRECORD_IMPLEMENTATION("evp_pkey", evp_pkey,
1932 mark_evp_pkey, print_evp_pkey,
1938 make_evp_pkey(EVP_PKEY *pkey, X509 *x509)
1940 Lisp_EVP_PKEY *lisp_pkey = allocate_evp_pkey();
1942 lisp_pkey->evp_pkey = pkey;
1943 lisp_pkey->x509 = x509;
1945 return wrap_evppkey(lisp_pkey);
1949 make_evp_pkey_pk(EVP_PKEY *pkey)
1951 return make_evp_pkey(pkey, NULL);
1955 make_evp_pkey_x509(X509 *x509)
1957 return make_evp_pkey(X509_get_pubkey(x509), x509);
1960 DEFUN("ossl-pkey-p", Fossl_pkey_p, 1, 1, 0, /*
1961 Return t iff OBJECT is a pkey, nil otherwise.
1965 if (EVPPKEYP(object))
1971 DEFUN("ossl-pkey-size", Fossl_pkey_size, 1, 1, 0, /*
1972 Return the size a public key PKEY in bits.
1978 CHECK_EVPPKEY(pkey);
1980 pk = (XEVPPKEY(pkey))->evp_pkey;
1982 return make_int(EVP_PKEY_size(pk)*8);
1986 ossl_pkey_has_public_data(EVP_PKEY *pkey)
1988 if (rsa_pkey_p(pkey)) {
1989 #ifndef OPENSSL_NO_RSA
1990 return rsa_pkey_has_public_data((pkey->pkey).rsa);
1994 } else if (dsa_pkey_p(pkey)) {
1995 #ifndef OPENSSL_NO_DSA
1996 return dsa_pkey_has_public_data((pkey->pkey).dsa);
2000 } else if (ec_pkey_p(pkey)) {
2001 #ifndef OPENSSL_NO_EC
2002 return ec_pkey_has_public_data((pkey->pkey).ec);
2006 } else if (dh_pkey_p(pkey)) {
2007 #ifndef OPENSSL_NO_DH
2008 return dh_pkey_has_public_data((pkey->pkey).dh);
2016 ossl_pkey_has_private_data(EVP_PKEY *pkey)
2018 if (rsa_pkey_p(pkey)) {
2019 #ifndef OPENSSL_NO_RSA
2020 return rsa_pkey_has_private_data((pkey->pkey).rsa);
2024 } else if (dsa_pkey_p(pkey)) {
2025 #ifndef OPENSSL_NO_DSA
2026 return dsa_pkey_has_private_data((pkey->pkey).dsa);
2030 } else if (ec_pkey_p(pkey)) {
2031 #ifndef OPENSSL_NO_EC
2032 return ec_pkey_has_private_data((pkey->pkey).ec);
2036 } else if (dh_pkey_p(pkey)) {
2037 #ifndef OPENSSL_NO_DH
2038 return dh_pkey_has_private_data((pkey->pkey).dh);
2046 DEFUN("ossl-pkey-private-p", Fossl_pkey_private_p, 1, 1, 0, /*
2047 Return non-nil if PKEY contains private data.
2049 This function is not native OpenSSL.
2055 if (!(EVPPKEYP(pkey)))
2058 pk = (XEVPPKEY(pkey))->evp_pkey;
2060 if (ossl_pkey_has_private_data(pk))
2066 DEFUN("ossl-pkey-get-public", Fossl_pkey_get_public, 1, 1, 0, /*
2067 Return a copy of PKEY stripped by the private data.
2069 This function is not native OpenSSL.
2076 CHECK_EVPPKEY(pkey);
2078 pk = (XEVPPKEY(pkey))->evp_pkey;
2079 if (!(ossl_pkey_has_public_data(pk)))
2080 error ("key must have public data");
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));
2087 } else if (dsa_pkey_p(pk)) {
2088 #ifndef OPENSSL_NO_DSA
2089 EVP_PKEY_assign_DSA(pkout, dsa_get_public(pk));
2091 } else if (ec_pkey_p(pk)) {
2092 #ifndef OPENSSL_NO_EC
2093 EVP_PKEY_assign_EC_KEY(pkout, ec_get_public(pk));
2096 error ("no method to strip private data yet");
2098 return make_evp_pkey_pk(pkout);
2103 rsa_pkey_p(EVP_PKEY *pkey)
2107 type = EVP_PKEY_type(pkey->type);
2109 #ifndef OPENSSL_NO_RSA
2110 return ((type == EVP_PKEY_RSA) ||
2111 (type == EVP_PKEY_RSA2));
2116 #ifndef OPENSSL_NO_RSA
2118 rsa_pkey_has_public_data(RSA *rsakey)
2120 return (!(rsakey->n == NULL) &&
2121 !(rsakey->e == NULL));
2124 rsa_pkey_has_private_data(RSA *rsakey)
2126 return (rsa_pkey_has_public_data(rsakey) &&
2127 !(rsakey->d == NULL));
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.
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");
2147 pkey = EVP_PKEY_new();
2148 rsakey = RSA_generate_key(XINT(bits), XINT(expo), NULL, NULL);
2149 EVP_PKEY_assign_RSA(pkey, rsakey);
2151 return make_evp_pkey_pk(pkey);
2154 DEFUN("ossl-rsa-pkey-p", Fossl_rsa_pkey_p, 1, 1, 0, /*
2155 Return t iff PKEY is of RSA type.
2161 if (!EVPPKEYP(pkey))
2164 pk = (XEVPPKEY(pkey))->evp_pkey;
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.
2177 This function is not native OpenSSL.
2186 CHECK_EVPPKEY(pkey1);
2187 CHECK_EVPPKEY(pkey2);
2189 pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2190 pk2 = (XEVPPKEY(pkey2))->evp_pkey;
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");
2198 rk1 = (pk1->pkey).rsa;
2199 rk2 = (pk2->pkey).rsa;
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)))
2209 #endif /* OPENSSL_NO_RSA */
2214 dsa_pkey_p(EVP_PKEY *pkey)
2218 type = EVP_PKEY_type(pkey->type);
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));
2230 #ifndef OPENSSL_NO_DSA
2232 dsa_pkey_has_public_data(DSA *dsakey)
2234 return (!(dsakey->p == NULL) &&
2235 !(dsakey->q == NULL) &&
2236 !(dsakey->g == NULL) &&
2237 !(dsakey->pub_key == NULL));
2240 dsa_pkey_has_private_data(DSA *dsakey)
2242 return (dsa_pkey_has_public_data(dsakey) &&
2243 !(dsakey->priv_key == NULL));
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.
2256 unsigned_long h_ret;
2263 error ("prime number size must be a non-zero positive integer");
2270 TO_EXTERNAL_FORMAT (LISP_STRING, seed,
2271 C_STRING_ALLOCA, seed_ext, OSSL_CODING);
2272 seed_len = OSSL_STRING_LENGTH(seed);
2275 pkey = EVP_PKEY_new();
2276 dsakey = DSA_generate_parameters(XINT(bits),
2277 (unsigned char*)seed_ext, seed_len,
2278 &counter_ret, &h_ret,
2280 if (!DSA_generate_key(dsakey))
2281 error ("error during generation of DSA key");
2283 EVP_PKEY_assign_DSA(pkey, dsakey);
2285 return make_evp_pkey_pk(pkey);
2288 DEFUN("ossl-dsa-pkey-p", Fossl_dsa_pkey_p, 1, 1, 0, /*
2289 Return t iff PKEY is of DSA type.
2295 if (!EVPPKEYP(pkey))
2298 pk = (XEVPPKEY(pkey))->evp_pkey;
2306 dsa_get_public(EVP_PKEY *pk)
2311 memcpy(key, (pk->pkey).dsa, sizeof(DSA));
2313 /* now kill the private data */
2314 key->priv_key = NULL;
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.
2324 This function is not native OpenSSL.
2333 CHECK_EVPPKEY(pkey1);
2334 CHECK_EVPPKEY(pkey2);
2336 pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2337 pk2 = (XEVPPKEY(pkey2))->evp_pkey;
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");
2345 dk1 = (pk1->pkey).dsa;
2346 dk2 = (pk2->pkey).dsa;
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)))
2358 #endif /* OPENSSL_NO_DSA */
2363 ec_pkey_p(EVP_PKEY *pkey)
2367 type = EVP_PKEY_type(pkey->type);
2369 #ifndef OPENSSL_NO_EC
2370 return (type == EVP_PKEY_EC);
2375 #ifndef OPENSSL_NO_EC
2377 ec_pkey_has_public_data(EC_KEY *ec_key)
2379 return (!(EC_KEY_get0_group(ec_key) == NULL) &&
2380 !(EC_KEY_get0_public_key(ec_key) == NULL));
2383 ec_pkey_has_private_data(EC_KEY *ec_key)
2385 return (ec_pkey_has_public_data(ec_key) &&
2386 !(EC_KEY_get0_private_key(ec_key) == NULL));
2389 DEFUN("ossl-ec-available-curves", Fossl_ec_available_curves, 0, 0, 0, /*
2390 Return a list of builtin elliptic curves.
2394 EC_builtin_curve *curves = NULL;
2395 size_t crv_len = 0, n = 0;
2396 Lisp_Object lcurves;
2400 crv_len = EC_get_builtin_curves(NULL, 0);
2401 curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
2404 error ("no curves defined");
2406 if (!EC_get_builtin_curves(curves, crv_len)) {
2407 OPENSSL_free(curves);
2408 error ("error during initialisation of curves");
2411 for (n = 0; n < crv_len; n++) {
2412 int nid = curves[n].nid;
2413 lcurves = Fcons(intern(OBJ_nid2sn(nid)), lcurves);
2416 OPENSSL_free(curves);
2422 ec_curve_by_name(char *name)
2424 return OBJ_sn2nid(name);
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'.
2431 At the moment we do not support creating custom curves.
2438 CHECK_SYMBOL(curve);
2440 pkey = EVP_PKEY_new();
2441 eckey = EC_KEY_new_by_curve_name(
2442 ec_curve_by_name((char *)string_data(XSYMBOL(curve)->name)));
2444 if (eckey == NULL) {
2445 error ("no such curve");
2448 if (!EC_KEY_generate_key(eckey))
2449 error ("error during generation of EC key");
2451 EVP_PKEY_assign_EC_KEY(pkey, eckey);
2453 return make_evp_pkey_pk(pkey);
2456 DEFUN("ossl-ec-pkey-p", Fossl_ec_pkey_p, 1, 1, 0, /*
2457 Return t iff PKEY is of EC type.
2464 if (!EVPPKEYP(pkey))
2467 pk = (XEVPPKEY(pkey))->evp_pkey;
2468 type = EVP_PKEY_type(pk->type);
2469 if (type == EVP_PKEY_EC)
2476 ec_get_public(EVP_PKEY *pk)
2480 key = EC_KEY_dup((pk->pkey).ec);
2482 /* now kill the private data */
2483 EC_KEY_set_private_key(key, NULL);
2487 #endif /* OPENSSL_NO_EC */
2492 dh_pkey_p(EVP_PKEY *pkey)
2496 type = EVP_PKEY_type(pkey->type);
2498 #ifndef OPENSSL_NO_DH
2499 return (type == EVP_PKEY_DH);
2504 #ifndef OPENSSL_NO_DH
2506 dh_pkey_has_public_data(DH *dhkey)
2508 return (!(dhkey->p == NULL) &&
2509 !(dhkey->g == NULL) &&
2510 !(dhkey->pub_key == NULL));
2513 dh_pkey_has_private_data(DH *dhkey)
2515 return (dh_pkey_has_public_data(dhkey) &&
2516 !(dhkey->priv_key == NULL));
2519 DEFUN("ossl-dh-pkey-p", Fossl_dh_pkey_p, 1, 1, 0, /*
2520 Return t iff PKEY is of DH type.
2526 if (!EVPPKEYP(pkey))
2529 pk = (XEVPPKEY(pkey))->evp_pkey;
2537 #endif /* OPENSSL_NO_DH */
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.
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
2549 The envelope returned is a list
2550 \(encrypted_string encrypted_key encrypted_iv\)
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
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.
2560 (cipher, string, pkey))
2562 /* declarations for the cipher */
2563 const EVP_CIPHER *ciph;
2564 EVP_CIPHER_CTX ciphctx;
2565 /* declarations for the pkey */
2568 unsigned char *ekey;
2571 /* buffer for the generated IV */
2572 char iv[EVP_MAX_IV_LENGTH];
2574 /* buffer for output */
2575 unsigned char *outbuf;
2576 unsigned int outlen;
2577 Lisp_Object l_outbuf;
2578 /* buffer for external string data */
2585 CHECK_SYMBOL(cipher);
2586 CHECK_STRING(string);
2587 CHECK_EVPPKEY(pkey);
2590 if (ossl_check_cipher(cipher) != 0)
2591 error("use of blacklisted cipher prohibited");
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");
2599 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2600 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2601 string_len = OSSL_STRING_LENGTH(string);
2603 OpenSSL_add_all_algorithms();
2604 ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2608 error ("no such cipher");
2612 /* alloc ekey buffer */
2613 ekey = (unsigned char*)xmalloc_atomic(EVP_PKEY_size(pk[0]));
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
2619 outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string) +
2620 EVP_CIPHER_block_size(ciph));
2622 EVP_CIPHER_CTX_init(&ciphctx);
2623 if (!(EVP_SealInit(&ciphctx, ciph,
2625 (unsigned char *)&iv,
2626 (EVP_PKEY **)&pk, npubk)==npubk)) {
2630 error ("error in SealInit");
2633 if (!EVP_SealUpdate(&ciphctx, outbuf, (int *)&outlen,
2634 (unsigned char*)string_ext, string_len)) {
2638 error ("error in SealUpdate");
2641 if (!EVP_SealFinal(&ciphctx, (unsigned char*)outbuf+outlen, &tmplen)) {
2645 error ("error in SealFinal");
2648 /* added probable padding space to the length of the output buffer */
2650 EVP_CIPHER_CTX_cleanup(&ciphctx);
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);
2659 return list3(l_outbuf, l_ekey, l_iv);
2663 DEFUN("ossl-open", Fossl_open, 4, 5, 0, /*
2664 Return the deciphered message STRING from an envelope
2665 obtained by `ossl-seal'.
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
2673 (cipher, string, pkey, ekey, eiv))
2675 /* declarations for the cipher */
2676 const EVP_CIPHER *ciph;
2677 EVP_CIPHER_CTX ciphctx;
2678 /* declarations for the pkey */
2680 /* buffer for external ekey data */
2683 /* buffer for external eiv data */
2685 /* buffer for output */
2686 unsigned char *outbuf;
2687 unsigned int outlen;
2688 Lisp_Object l_outbuf;
2689 /* buffer for external string data */
2696 CHECK_SYMBOL(cipher);
2697 CHECK_STRING(string);
2698 CHECK_EVPPKEY(pkey);
2702 if (ossl_check_cipher(cipher) != 0)
2703 error("use of blacklisted cipher prohibited");
2705 pk = (XEVPPKEY(pkey))->evp_pkey;
2706 if (!ossl_pkey_has_private_data(pk))
2707 error ("cannot open, key has no private key data");
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);
2716 OpenSSL_add_all_algorithms();
2717 ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2721 error ("no such cipher");
2729 TO_EXTERNAL_FORMAT (LISP_STRING, eiv,
2730 C_STRING_ALLOCA, eiv_ext, OSSL_CODING);
2733 /* now allocate some output buffer externally */
2734 outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string));
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)) {
2743 error ("error in OpenInit");
2746 if (!EVP_OpenUpdate(&ciphctx, outbuf, (int *)&outlen,
2747 (unsigned char*)string_ext,
2748 (unsigned int)string_len)) {
2751 error ("error in OpenUpdate");
2754 if (!EVP_OpenFinal(&ciphctx, outbuf+outlen, &tmplen)) {
2757 error ("error in OpenFinal");
2760 /* added probable padding space to the length of the output buffer */
2762 EVP_CIPHER_CTX_cleanup(&ciphctx);
2764 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2773 DEFUN("ossl-sign", Fossl_sign, 3, 3, 0, /*
2774 Return a signature obtained by signing STRING under DIGEST with PKEY.
2776 That is, hash the message STRING with the message digest DIGEST and
2777 encrypt the result with the private key PKEY.
2779 Note: Due to some relationship between the public key system and the
2780 message digest you cannot use every digest algorithm with every
2782 The most certain results will be achieved using
2783 RSA keys with RSA-* digests, DSA keys with DSA-* digests.
2785 See `ossl-available-digests'.
2787 Note: You probably want to put a wrapping encoder function
2788 (like `base16-encode-string') around it, since this returns
2791 (digest, string, pkey))
2793 /* declarations for the cipher */
2796 /* declarations for the pkey */
2798 /* buffer for output */
2799 unsigned char *outbuf;
2800 unsigned int outlen;
2801 Lisp_Object l_outbuf;
2802 /* buffer for external string data */
2807 CHECK_SYMBOL(digest);
2808 CHECK_STRING(string);
2809 CHECK_EVPPKEY(pkey);
2812 pk = (XEVPPKEY(pkey))->evp_pkey;
2813 if (!ossl_pkey_has_private_data(pk)) {
2814 error ("cannot sign, key has no private key data");
2817 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2818 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2819 string_len = OSSL_STRING_LENGTH(string);
2821 OpenSSL_add_all_algorithms();
2822 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2826 error ("no such digest");
2830 /* now allocate some output buffer externally */
2831 outbuf = (unsigned char *)xmalloc_atomic(EVP_PKEY_size(pk));
2833 EVP_MD_CTX_init(&mdctx);
2834 if (!(EVP_SignInit(&mdctx, md))) {
2837 error ("error in SignInit");
2840 if (!EVP_SignUpdate(&mdctx, string_ext, string_len)) {
2843 error ("error in SignUpdate");
2846 if (!EVP_SignFinal(&mdctx, outbuf, &outlen, pk)) {
2849 error ("error in SignFinal");
2852 EVP_MD_CTX_cleanup(&mdctx);
2854 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
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.
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.
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
2874 (digest, string, sig, pkey))
2876 /* declarations for the cipher */
2879 /* declarations for the pkey */
2881 /* buffer for external signature data */
2884 /* buffer for external string data */
2891 CHECK_SYMBOL(digest);
2892 CHECK_STRING(string);
2894 CHECK_EVPPKEY(pkey);
2897 pk = (XEVPPKEY(pkey))->evp_pkey;
2898 if (!ossl_pkey_has_public_data(pk))
2899 error ("cannot verify, key has no public key data");
2901 OpenSSL_add_all_algorithms();
2902 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2906 error ("no such digest");
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);
2917 EVP_MD_CTX_init(&mdctx);
2918 if (!EVP_VerifyInit(&mdctx, md)) {
2920 error ("error in VerifyInit");
2923 if (!EVP_VerifyUpdate(&mdctx, string_ext, string_len)) {
2925 error ("error in VerifyUpdate");
2928 result = EVP_VerifyFinal(&mdctx, (unsigned char*)sig_ext, sig_len, pk);
2931 error ("error in VerifyFinal");
2934 EVP_MD_CTX_cleanup(&mdctx);
2938 return result ? Qt : Qnil;
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.
2952 /* declarations for the pkey */
2961 file = Fexpand_file_name(file, Qnil);
2963 if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2964 error ("error opening file.");
2966 pk509 = PEM_read_X509(fp, NULL, NULL, NULL);
2967 pk = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
2971 return make_evp_pkey(pk, pk509);
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.
2981 /* declarations for the pkey */
2985 /* password pointer */
2990 file = Fexpand_file_name(file, Qnil);
2992 if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2993 error ("error opening file.");
2995 if (NILP(password)) {
2998 CHECK_STRING(password);
2999 pass = (char *)XSTRING_DATA(password);
3002 pk = PEM_read_PrivateKey(fp, NULL, NULL, pass);
3005 /* now maybe it is a public key only */
3006 return Fossl_pem_read_public_key(file);
3009 return make_evp_pkey_pk(pk);
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.
3017 /* declarations for the pkey */
3024 CHECK_EVPPKEY(pkey);
3026 file = Fexpand_file_name(file, Qnil);
3028 pk = XEVPPKEY(pkey)->evp_pkey;
3029 pk509 = XEVPPKEY(pkey)->x509;
3030 SXE_SET_UNUSED(pk509);
3032 if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL)
3033 error ("error opening file.");
3035 if (!PEM_write_PUBKEY(fp, pk)) {
3037 error ("error writing PEM file.");
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.
3049 CIPHER can be set to nil and the key will not be encrypted.
3050 PASSWORD is ignored in this case.
3052 (file, pkey, cipher, password))
3054 const EVP_CIPHER *ciph;
3055 /* declarations for the pkey */
3060 /* password pointer */
3064 CHECK_EVPPKEY(pkey);
3066 file = Fexpand_file_name(file, Qnil);
3068 pk = XEVPPKEY(pkey)->evp_pkey;
3069 pk509 = XEVPPKEY(pkey)->x509;
3070 SXE_SET_UNUSED(pk509);
3072 if (!ossl_pkey_has_private_data(pk))
3073 return Fossl_pem_write_public_key(file, pkey);
3075 CHECK_SYMBOL(cipher);
3077 if (ossl_check_cipher(cipher) != 0)
3078 error("use of blacklisted cipher prohibited");
3080 OpenSSL_add_all_algorithms();
3086 ciph = EVP_get_cipherbyname(
3087 (char *)string_data(XSYMBOL(cipher)->name));
3090 error ("no such cipher");
3094 if (NILP(password)) {
3098 CHECK_STRING(password);
3099 pass = (char *)XSTRING_DATA(password);
3102 if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL) {
3104 error ("error opening file.");
3107 if (!PEM_write_PKCS8PrivateKey(fp, pk, ciph, NULL, 0, NULL, pass)) {
3110 error ("error writing PEM file.");
3120 ossl_pem_pkey_cb(BIO *bio, int cmd, const char *argp,
3121 int argi, long argl, long ret)
3124 void *foo = BIO_get_callback_arg(bio);
3126 if (!(key = (Lisp_Object)foo)) {
3130 if (BIO_CB_RETURN & cmd) {
3136 key = concat2(key, make_ext_string(argp, argi, OSSL_CODING));
3137 BIO_set_callback_arg(bio, (void*)key);
3145 DEFUN("ossl-pem-public-key",Fossl_pem_public_key, 1, 1, 0, /*
3146 Return PKEY as PEM encoded string.
3150 /* This function can GC */
3151 /* declarations for the pkey */
3157 struct gcpro gcpro1;
3161 CHECK_EVPPKEY(pkey);
3163 pk = (XEVPPKEY(pkey))->evp_pkey;
3165 if (!(b = BIO_new(BIO_s_null()))) {
3167 error("cannot open memory buffer");
3171 result = build_string("");
3172 BIO_set_callback(b, ossl_pem_pkey_cb);
3173 BIO_set_callback_arg(b, (void*)result);
3175 if (!PEM_write_bio_PUBKEY(b, pk)) {
3179 error ("error creating PEM string");
3184 void *foo = BIO_get_callback_arg(b);
3185 if (!(result = (Lisp_Object)foo)) {
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.
3200 CIPHER can be set to nil and the key will not be encrypted.
3201 PASSWORD is ignored in this case.
3203 (pkey, cipher, password))
3205 /* This function can GC */
3206 /* declarations for the pkey */
3209 const EVP_CIPHER *ciph;
3213 struct gcpro gcpro1, gcpro2, gcpro3;
3215 GCPRO3(pkey, cipher, password);
3217 CHECK_EVPPKEY(pkey);
3219 pk = (XEVPPKEY(pkey))->evp_pkey;
3221 if (!ossl_pkey_has_private_data(pk)) {
3223 return Fossl_pem_public_key(pkey);
3226 CHECK_SYMBOL(cipher);
3228 if (ossl_check_cipher(cipher) != 0)
3229 error("use of blacklisted cipher prohibited");
3231 OpenSSL_add_all_algorithms();
3237 ciph = EVP_get_cipherbyname(
3238 (char *)string_data(XSYMBOL(cipher)->name));
3242 error ("no such cipher");
3247 if (NILP(password)) {
3251 CHECK_STRING(password);
3252 pass = (char *)XSTRING_DATA(password);
3255 if (!(b = BIO_new(BIO_s_null()))) {
3257 error("cannot open memory buffer");
3261 result = build_string("");
3262 BIO_set_callback(b, ossl_pem_pkey_cb);
3263 BIO_set_callback_arg(b, (void*)result);
3265 if (!PEM_write_bio_PKCS8PrivateKey(b, pk, ciph, NULL, 0, NULL, pass)) {
3269 error ("error creating PEM string");
3274 void *foo = BIO_get_callback_arg(b);
3276 if (!(result = (Lisp_Object)foo)) {
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
3296 /* This is an opaque object for storing PKEYs in lisp */
3297 Lisp_Object Qssl_connp;
3300 make_ssl_conn(Lisp_SSL_CONN *ssl_conn)
3302 Lisp_Object lisp_ssl_conn;
3303 XSETSSLCONN(lisp_ssl_conn, ssl_conn);
3304 return lisp_ssl_conn;
3308 mark_ssl_conn(Lisp_Object obj)
3310 mark_object(XSSLCONN(obj)->parent);
3311 mark_object(XSSLCONN(obj)->pipe_instream);
3312 mark_object(XSSLCONN(obj)->pipe_outstream);
3314 mark_object(XSSLCONN(obj)->coding_instream);
3315 mark_object(XSSLCONN(obj)->coding_outstream);
3322 print_ssl_conn(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3327 conn = XSSLCONN(obj)->ssl_conn;
3328 parent = XSSLCONN(obj)->parent;
3330 write_c_string("#<OpenSSL socket layer: ", printcharfun);
3332 write_c_string("dead", printcharfun);
3334 write_c_string(SSL_get_version(conn), printcharfun);
3337 if (PROCESSP(parent)) {
3338 write_c_string(" on top of ", printcharfun);
3339 print_internal(parent, printcharfun, escapeflag);
3341 #endif /* HAVE_SOCKETS */
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);
3349 #endif /* HAVE_POSTGRESQL */
3350 write_c_string(">", printcharfun);
3354 allocate_ssl_conn(void)
3356 Lisp_SSL_CONN *ssl_conn =
3357 alloc_lcrecord_type(Lisp_SSL_CONN, &lrecord_ssl_conn);
3359 /* the network process stuff */
3360 ssl_conn->parent = Qnil;
3361 ssl_conn->infd = -1;
3362 ssl_conn->outfd = -1;
3364 ssl_conn->connected_p = 0;
3365 ssl_conn->protected_p = 0;
3367 ssl_conn->pipe_instream = Qnil;
3368 ssl_conn->pipe_outstream = Qnil;
3370 ssl_conn->coding_instream = Qnil;
3371 ssl_conn->coding_outstream = Qnil;
3378 finalise_ssl_conn(void *header, int for_disksave)
3380 Lisp_SSL_CONN *ssl_conn = (Lisp_SSL_CONN *) header;
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;
3388 if (!(ssl_conn->ssl_ctx == NULL)) {
3389 SSL_CTX_free(ssl_conn->ssl_ctx);
3390 ssl_conn->ssl_ctx = NULL;
3392 ssl_conn->ssl_bio = NULL;
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;
3398 /* we leave the process alive, it's not our fault, but
3399 * we nullify its pointer
3401 ssl_conn->parent = Qnil;
3402 ssl_conn->infd = -1;
3403 ssl_conn->outfd = -1;
3405 ssl_conn->connected_p = 0;
3406 ssl_conn->protected_p = 0;
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));
3415 ssl_conn->pipe_instream = Qnil;
3416 ssl_conn->pipe_outstream = Qnil;
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));
3424 ssl_conn->coding_instream = Qnil;
3425 ssl_conn->coding_outstream = Qnil;
3428 /* avoid some warning */
3432 DEFINE_LRECORD_IMPLEMENTATION("ssl_conn", ssl_conn,
3433 mark_ssl_conn, print_ssl_conn,
3435 NULL, NULL, 0, Lisp_SSL_CONN);
3438 ssl_conn_alive_p(Lisp_SSL_CONN *ssl_conn)
3440 return ssl_conn->connected_p;
3444 get_process_infd(Lisp_Process * p)
3446 Lisp_Object instr, outstr;
3447 get_process_streams(p, &instr, &outstr);
3448 return Lstream_get_fd(XLSTREAM(instr));
3451 get_process_outfd(Lisp_Process * p)
3453 Lisp_Object instr, outstr;
3454 get_process_streams(p, &instr, &outstr);
3455 return Lstream_get_fd(XLSTREAM(outstr));
3459 event_stream_ssl_create_stream_pair(
3461 Lisp_Object *instream, Lisp_Object *outstream, int flags)
3463 *instream = make_ssl_input_stream(conn, flags);
3464 *outstream = make_ssl_output_stream(conn, flags);
3470 init_ssl_io_handles(Lisp_SSL_CONN *s, int flags)
3472 event_stream_ssl_create_stream_pair(
3473 s->ssl_conn, &s->pipe_instream, &s->pipe_outstream, flags);
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 */
3486 /* Advanced step-by-step initialisation */
3487 #define OSSL_CHECK_PROCESS(process) \
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)); \
3499 #ifdef OSSL_DEBUG_FLAG
3501 ossl_bio_dump_callback(BIO *bio, int cmd, const char *argp,
3502 int argi, long argl, long ret)
3506 out=(BIO *)BIO_get_callback_arg(bio);
3507 if (out == NULL) return(ret);
3509 if (cmd == (BIO_CB_READ|BIO_CB_RETURN))
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);
3516 else if (cmd == (BIO_CB_WRITE|BIO_CB_RETURN))
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);
3527 ossl_ssl_prepare_cmeth(Lisp_Object method)
3529 SSL_METHOD *meth = NULL;
3530 Lisp_SSL_CONN *lisp_ssl_conn;
3532 /* start preparing the conn object */
3534 SSL_load_error_strings();
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.
3542 #pragma GCC diagnostic push
3543 #pragma GCC diagnostic ignored "-Wcast-qual"
3545 } else if (EQ(method, Qssl2)) {
3546 #if HAVE_SSLV2_CLIENT_METHOD
3547 meth = (SSL_METHOD *)SSLv2_client_method();
3549 error("sslv2 client method not supported");
3551 } else if (EQ(method, Qssl3)) {
3552 #if HAVE_SSLV3_CLIENT_METHOD
3553 meth = (SSL_METHOD *)SSLv3_client_method();
3555 error("sslv3 client method not supported");
3557 } else if (EQ(method, Qssl23)) {
3558 #if HAVE_SSLV23_CLIENT_METHOD
3559 meth = (SSL_METHOD *)SSLv23_client_method();
3561 error("sslv23 client method not supported");
3563 } else if (EQ(method, Qtls1)) {
3564 #if HAVE_TLSV1_CLIENT_METHOD
3565 meth = (SSL_METHOD *)TLSv1_client_method();
3567 error("tlsv1 client method not supported");
3570 #if HAVE_TLSV1_CLIENT_METHOD
3571 meth = (SSL_METHOD *)TLSv1_client_method();
3573 error("default tlsv1 client method not supported");
3576 #pragma GCC diagnostic pop
3578 error("OSSL: not enough random data");
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;
3587 return make_ssl_conn(lisp_ssl_conn);
3591 ossl_ssl_prepare_smeth(Lisp_Object method)
3593 SSL_METHOD *meth = NULL;
3594 Lisp_SSL_CONN *lisp_ssl_conn;
3596 /* start preparing the conn object */
3598 SSL_load_error_strings();
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.
3606 #pragma GCC diagnostic push
3607 #pragma GCC diagnostic ignored "-Wcast-qual"
3609 } else if (EQ(method, Qssl2)) {
3610 #if HAVE_SSLV2_SERVER_METHOD
3611 meth = (SSL_METHOD *)SSLv2_server_method();
3613 error("sslv2 client method not supported");
3615 } else if (EQ(method, Qssl3)) {
3616 #if HAVE_SSLV3_SERVER_METHOD
3617 meth = (SSL_METHOD *)SSLv3_server_method();
3619 error("sslv3 client method not supported");
3621 } else if (EQ(method, Qssl23)) {
3622 #if HAVE_SSLV23_SERVER_METHOD
3623 meth = (SSL_METHOD *)SSLv23_server_method();
3625 error("sslv23 client method not supported");
3627 } else if (EQ(method, Qtls1)) {
3628 #if HAVE_TLSV1_SERVER_METHOD
3629 meth = (SSL_METHOD *)TLSv1_server_method();
3631 error("tlsv1 client method not supported");
3634 #if HAVE_SSLV23_SERVER_METHOD
3635 meth = (SSL_METHOD *)SSLv23_server_method();
3637 error("default sslv23 client method not supported");
3640 #pragma GCC diagnostic pop
3642 error("OSSL: not enough random data");
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;
3651 return make_ssl_conn(lisp_ssl_conn);
3655 ossl_ssl_prepare_ctx(Lisp_Object ssl_conn)
3657 /* SSL connection stuff */
3658 SSL_CTX *ctx = NULL;
3659 Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3661 ctx = SSL_CTX_new(lisp_ssl_conn->ssl_meth);
3663 error("OSSL: context initialisation failed");
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."
3672 SSL_CTX_set_options(ctx, SSL_OP_ALL);
3674 lisp_ssl_conn->ssl_ctx = ctx;
3680 ossl_ssl_prepare(Lisp_Object ssl_conn, void(*fun)(SSL*))
3682 /* SSL connection stuff */
3685 #ifdef OSSL_DEBUG_FLAG
3686 BIO *bio_c_out = NULL;
3688 Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
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");
3695 /* always renegotiate */
3696 SSL_set_mode(conn, SSL_MODE_AUTO_RETRY);
3698 /* initialise the main connection BIO */
3699 bio = BIO_new(BIO_s_socket());
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);
3708 /* connect SSL with the bio */
3709 SSL_set_bio(conn, bio, bio);
3710 /* turn into client or server */
3713 /* now allocate this stuff, pump it and return */
3714 lisp_ssl_conn->ssl_conn = conn;
3715 lisp_ssl_conn->ssl_bio = bio;
3717 /* create lstream handles */
3718 init_ssl_io_handles(lisp_ssl_conn, STREAM_NETWORK_CONNECTION);
3723 /* Injection of CA certificates */
3724 int ossl_ssl_inject_ca(Lisp_Object ssl_conn, Lisp_Object cacert)
3730 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3731 cert = XEVPPKEY(cacert)->evp_pkey;
3732 xc509 = XEVPPKEY(cacert)->x509;
3734 if (cert && !xc509) {
3736 X509_set_pubkey(xc509, cert);
3737 XEVPPKEY(cacert)->x509 = xc509;
3742 /* what about coding system issues? */
3743 if (!SSL_CTX_add_client_CA(ctx, xc509))
3749 int ossl_ssl_inject_ca_file(Lisp_Object ssl_conn, Lisp_Object cafile)
3753 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3755 /* what about coding system issues? */
3756 if (!SSL_CTX_load_verify_locations(
3757 ctx, (char*)XSTRING_DATA(cafile), NULL))
3763 int ossl_ssl_inject_ca_path(Lisp_Object ssl_conn, Lisp_Object capath)
3767 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3769 /* what about coding system issues? */
3770 if (!SSL_CTX_load_verify_locations(
3771 ctx, NULL, (char*)XSTRING_DATA(capath)))
3777 int ossl_ssl_inject_cert(Lisp_Object ssl_conn,
3778 Lisp_Object cert, Lisp_Object key)
3785 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3786 pkey = XEVPPKEY(key)->evp_pkey;
3787 xcert = XEVPPKEY(cert)->evp_pkey;
3788 xc509 = XEVPPKEY(cert)->x509;
3790 if (xcert && !xc509) {
3792 X509_set_pubkey(xc509, xcert);
3793 XEVPPKEY(cert)->x509 = xc509;
3798 if (SSL_CTX_use_certificate(ctx, xc509) <= 0)
3801 if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
3803 if (!SSL_CTX_check_private_key(ctx))
3809 int ossl_ssl_inject_cert_file(Lisp_Object ssl_conn,
3810 Lisp_Object cert, Lisp_Object key)
3814 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3816 if (SSL_CTX_use_certificate_file(
3817 ctx, (char*)XSTRING_DATA(cert), SSL_FILETYPE_PEM) <= 0)
3819 if (SSL_CTX_use_PrivateKey_file(
3820 ctx, (char*)XSTRING_DATA(key), SSL_FILETYPE_PEM) <= 0)
3822 if (!SSL_CTX_check_private_key(ctx))
3828 Lisp_Object ossl_ssl_handshake(Lisp_Object ssl_conn, Lisp_Object process)
3830 /* This function can GC */
3831 /* SSL connection stuff */
3834 #if 0 && defined(OSSL_DEBUG_FLAG)
3835 BIO *bio_c_out = NULL;
3837 int ret, err, infd, outfd;
3839 struct gcpro gcpro1, gcpro2;
3841 /* Make sure we have a process, the alive check should be done in the
3842 function calling this here */
3843 CHECK_PROCESS(process);
3845 GCPRO2(ssl_conn, process);
3847 /* set the alternate one */
3848 event_stream_unselect_process(XPROCESS(process));
3851 /* just announce that we are very binary */
3852 Fset_process_coding_system(process, Qbinary, Qbinary);
3855 /* initialise the process' buffer for type-specific data,
3856 * we will store process input there */
3857 XPROCESS(process)->process_type_data = Qnil;
3859 /* retrieve the sockets of the process */
3860 infd = get_process_infd(XPROCESS(process));
3861 outfd = get_process_outfd(XPROCESS(process));
3863 /* push data to ssl_conn */
3864 XSSLCONN(ssl_conn)->parent = process;
3865 XSSLCONN(ssl_conn)->infd = infd;
3866 XSSLCONN(ssl_conn)->outfd = outfd;
3868 /* frob vars from ssl_conn */
3869 conn = XSSLCONN(ssl_conn)->ssl_conn;
3870 bio = XSSLCONN(ssl_conn)->ssl_bio;
3872 /* initialise the main connection BIO */
3873 BIO_set_fd(bio, infd, 0);
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 */
3881 ret = SSL_do_handshake(conn);
3882 err = SSL_get_error(conn, ret);
3884 /* perform select() with timeout
3885 * 1 second at the moment */
3889 if (err == SSL_ERROR_NONE) {
3891 } else if (err == SSL_ERROR_WANT_READ) {
3893 OSSL_DEBUG("WANT_READ\n");
3896 FD_SET(infd, &read_fds);
3898 /* wait for socket to be readable */
3899 if (!(ret = select(infd+1, &read_fds, 0, NULL, &to))) {
3901 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3902 error("timeout during handshake");
3905 } else if (err == SSL_ERROR_WANT_WRITE) {
3907 OSSL_DEBUG("WANT_WRITE\n");
3908 FD_ZERO(&write_fds);
3909 FD_SET(outfd, &write_fds);
3911 /* wait for socket to be writable */
3912 if (!(ret = select(infd+1, &write_fds, 0, NULL, &to))) {
3914 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3915 error("timeout during handshake");
3918 } else if (err == SSL_ERROR_SSL) {
3919 /* close down the process object */
3920 Fdelete_process(process);
3923 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3924 error("handshake failed");
3927 OSSL_CRITICAL("\nUnknown error: %d\n"
3929 "sxemacs-devel@sxemacs.org\n\n", err);
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);
3936 (try < 0 && !BIO_should_retry(bio))) {
3937 /* Handle closed connection */
3938 XPROCESS(process)->exit_code = 256;
3939 XPROCESS(process)->status_symbol = Qexit;
3942 /* close down the process object */
3943 Fdelete_process(process);
3947 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3948 error("unknown handshake error");
3953 /* marry the socket layer now */
3954 ossl_ssl_proselytise_process(ssl_conn, process);
3956 /* declare the whole pig connected */
3957 XSSLCONN(ssl_conn)->connected_p = 1;
3959 event_stream_select_process(XPROCESS(process));
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.
3970 Both, CERT and KEY may be either a filename pointing to a
3971 PEM-encoded certificate and key respectively, or may be an
3974 (ssl_conn, cert, key))
3976 /* This function can GC */
3977 int (*fun)(Lisp_Object, Lisp_Object, Lisp_Object) = NULL;
3978 struct gcpro gcpro1, gcpro2, gcpro3;
3980 GCPRO3(ssl_conn, cert, key);
3982 CHECK_SSLCONN(ssl_conn);
3985 CHECK_EVPPKEY(cert);
3990 /* certificate and key preparation */
3991 if (STRINGP(cert)) {
3992 cert = Fexpand_file_name(cert, Qnil);
3993 if (NILP(Ffile_readable_p(cert)))
3998 key = Fexpand_file_name(key, Qnil);
3999 if (NILP(Ffile_readable_p(key)))
4003 if (STRINGP(cert) && NILP(key))
4005 else if (EVPPKEYP(cert) && NILP(key))
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;
4016 if (fun && fun(ssl_conn, cert, key)) {
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,
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.
4038 /* This function can GC */
4039 int (*fun)(Lisp_Object, Lisp_Object) = NULL;
4041 struct gcpro gcpro1, gcpro2;
4043 GCPRO2(ssl_conn, ca);
4045 CHECK_SSLCONN(ssl_conn);
4051 ca = Fexpand_file_name(ca, Qnil);
4052 if (NILP(Ffile_readable_p(ca)))
4056 if (!NILP(ca) && STRINGP(ca)) {
4057 if (NILP(Ffile_directory_p(ca)))
4058 fun = ossl_ssl_inject_ca_file;
4060 fun = ossl_ssl_inject_ca_path;
4061 } else if (!NILP(ca) && EVPPKEYP(ca))
4062 fun = ossl_ssl_inject_ca;
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));
4069 error("SSL certificate chain verification not supported");
4079 DEFUN("ossl-ssl-handshake", Fossl_ssl_handshake, 1, 6, 0, /*
4080 Perform a handshake on the network connection PROCESS.
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
4087 Optional argument METHOD indicates the SSL connection method,
4088 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
4090 Optional argument CA indicates a CA certificate.
4091 See `ossl-ssl-inject-ca'.
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'.
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.
4102 (process, method, ca, cert, key, serverp))
4104 /* This function can GC */
4106 Lisp_Object ssl_conn, result;
4108 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
4110 GCPRO6(process, method, ca, cert, key, serverp);
4112 /* Make sure the process is really alive. */
4113 CHECK_PROCESS(process);
4114 OSSL_CHECK_PROCESS(process);
4116 /* create a ssl_conn object first */
4118 ssl_conn = ossl_ssl_prepare_cmeth(method);
4120 ssl_conn = ossl_ssl_prepare_smeth(method);
4122 /* create the context */
4123 ossl_ssl_prepare_ctx(ssl_conn);
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);
4130 /* prepare for handshake */
4132 ossl_ssl_prepare(ssl_conn, SSL_set_connect_state);
4134 ossl_ssl_prepare(ssl_conn, SSL_set_accept_state);
4136 result = ossl_ssl_handshake(ssl_conn, process);
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
4157 Optional argument METHOD indicates the SSL connection method,
4158 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
4160 (int nargs, Lisp_Object *args))
4164 for (i = 0; i < nargs; i++);
4170 ossl_swap_process_streams(Lisp_SSL_CONN *s, Lisp_Process *p)
4172 Lisp_Object in, out;
4174 in = p->pipe_instream;
4175 out = p->pipe_outstream;
4177 p->pipe_instream = s->pipe_instream;
4178 p->pipe_outstream = s->pipe_outstream;
4180 s->pipe_instream = in;
4181 s->pipe_outstream = out;
4184 in = p->coding_instream;
4185 out = p->coding_outstream;
4187 p->coding_instream = s->coding_instream;
4188 p->coding_outstream = s->coding_outstream;
4190 s->coding_instream = in;
4191 s->coding_outstream = out;
4196 ossl_ssl_proselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4198 Lisp_Process *p = XPROCESS(process);
4199 Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4201 event_stream_unselect_process(p);
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);
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
4213 p->process_type = PROCESS_TYPE_SSL;
4214 p->process_type_data = ssl_conn;
4216 event_stream_select_process(p);
4222 ossl_ssl_unproselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4224 Lisp_Process *p = XPROCESS(process);
4225 Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
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);
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
4237 XPROCESS(process)->process_type = PROCESS_TYPE_NETWORK;
4238 XPROCESS(process)->process_type_data = Qnil;
4243 DEFUN("ossl-ssl-proselytise-process", Fossl_ssl_proselytise_process,
4245 Convert the underlying process of SSL-CONN into a secure
4246 network connection object.
4250 Lisp_Object process;
4252 CHECK_SSLCONN(ssl_conn);
4254 process = XSSLCONN(ssl_conn)->parent;
4255 if (!PROCESSP(process)) {
4256 error("no process associated with this connection");
4260 /* Make sure the process is really alive. */
4261 OSSL_CHECK_PROCESS(process);
4263 ossl_ssl_proselytise_process(ssl_conn, process);
4268 DEFUN("ossl-ssl-unproselytise-process", Fossl_ssl_unproselytise_process,
4270 Convert the underlying process of SSL-CONN into an ordinary
4271 network connection object.
4275 Lisp_Object process;
4277 CHECK_SSLCONN(ssl_conn);
4279 process = XSSLCONN(ssl_conn)->parent;
4280 if (!PROCESSP(process)) {
4281 error("no process associated with this connection");
4285 /* Make sure the process is really alive. */
4286 OSSL_CHECK_PROCESS(process);
4288 /* Castrate the process and make it a network process again */
4289 ossl_ssl_unproselytise_process(ssl_conn, process);
4294 DEFUN("ossl-ssl-finish", Fossl_ssl_finish, 1, 1, 0, /*
4295 Finish an SSL connection SSL-CONN.
4297 Note: This may also finish the network connection.
4301 Lisp_Object process;
4303 CHECK_SSLCONN(ssl_conn);
4305 if (XSSLCONN(ssl_conn)->protected_p)
4306 error ("Cannot finish protected SSL connection");
4308 process = XSSLCONN(ssl_conn)->parent;
4309 if (PROCESSP(process))
4310 ossl_ssl_unproselytise_process(ssl_conn, process);
4312 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
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.
4322 /* network stream stuff */
4324 Lisp_Object process;
4326 Lisp_Object result = Qnil;
4328 CHECK_SSLCONN(ssl_conn);
4329 CHECK_STRING(string);
4331 if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4332 error("SSL connection dead");
4334 conn = XSSLCONN(ssl_conn)->ssl_conn;
4335 SXE_SET_UNUSED(conn);
4337 process = XSSLCONN(ssl_conn)->parent;
4339 /* Make sure the process is really alive. */
4340 OSSL_CHECK_PROCESS(process);
4345 DEFUN("ossl-ssl-write", Fossl_ssl_write, 2, 2, 0, /*
4346 Send STRING to the tunnel SSL-CONN.
4350 /* network stream stuff */
4352 Lisp_Object process, proc_filter;
4357 CHECK_SSLCONN(ssl_conn);
4358 CHECK_STRING(string);
4360 if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4361 error("SSL connection dead");
4363 conn = XSSLCONN(ssl_conn)->ssl_conn;
4364 process = XSSLCONN(ssl_conn)->parent;
4366 /* Make sure the process is really alive. */
4367 OSSL_CHECK_PROCESS(process);
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)));
4374 case PROCESS_TYPE_SSL:
4375 /* ssl streams reside in process object, snarf from there */
4376 out = XLSTREAM(DATA_OUTSTREAM(XPROCESS(process)));
4380 error("unable to write");
4383 /* store the original process filter */
4384 proc_filter = XPROCESS(process)->filter;
4385 SXE_SET_UNUSED(proc_filter);
4387 ret = Lstream_write(out, XSTRING_DATA(string), XSTRING_LENGTH(string));
4390 switch (SSL_get_error(conn, ret)) {
4391 case SSL_ERROR_NONE:
4393 case SSL_ERROR_WANT_WRITE:
4394 error("Connection wants write");
4395 case SSL_ERROR_WANT_READ:
4396 error("Connection wants read");
4398 error("Severe SSL connection error");
4401 /* restore the original process filter */
4402 return (SSL_pending(conn) == 0) ? Qt : Qnil;
4405 /* convenience functions */
4406 DEFUN("ossl-ssl-parent", Fossl_ssl_parent, 1, 1, 0, /*
4407 Return the underlying parent layer of SSL-CONN.
4411 CHECK_SSLCONN(ssl_conn);
4413 return XSSLCONN(ssl_conn)->parent;
4416 DEFUN("ossl-ssl-cert", Fossl_ssl_cert, 1, 1, 0, /*
4417 Return the local peer's certificate of SSL-CONN if present,
4422 /* SSL connection stuff */
4426 CHECK_SSLCONN(ssl_conn);
4428 conn = XSSLCONN(ssl_conn)->ssl_conn;
4429 cert = SSL_get_certificate(conn);
4432 return make_evp_pkey_x509(cert);
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,
4443 /* SSL connection stuff */
4447 CHECK_SSLCONN(ssl_conn);
4449 conn = XSSLCONN(ssl_conn)->ssl_conn;
4450 cert = SSL_get_peer_certificate(conn);
4453 return make_evp_pkey_x509(cert);
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
4465 /* SSL connection stuff */
4469 Lisp_Object result = Qnil;
4471 CHECK_SSLCONN(ssl_conn);
4473 conn = XSSLCONN(ssl_conn)->ssl_conn;
4474 sk = SSL_get_peer_cert_chain(conn);
4479 for (i=0; i<sk_X509_num(sk); i++) {
4480 X509 *cert = sk_X509_value(sk, i);
4482 result = Fcons(make_evp_pkey_x509(cert), result);
4489 DEFUN("ossl-ssl-cert-store", Fossl_ssl_cert_store, 1, 1, 0, /*
4490 Return the X509 cert store of SSL-CONN.
4494 X509_STORE *sto = NULL;
4500 #if 0 /* just thoughts */
4501 int SSL_get_verify_mode(const SSL *s);
4502 int SSL_get_verify_depth(const SSL *s);
4505 DEFUN("ossl-ssl-verify-certificate", Fossl_ssl_verify_certificate,
4507 Return a verify code of SSL-CONN.
4509 The result is a cons cell with the numeric verify code in
4510 the car and a verbose string in the cdr.
4515 /* SSL connection stuff */
4518 Lisp_Object result = Qnil;
4520 CHECK_SSLCONN(ssl_conn);
4522 conn = XSSLCONN(ssl_conn)->ssl_conn;
4523 vrc = SSL_get_verify_result(conn);
4527 build_string(X509_verify_cert_error_string(vrc)));
4532 DEFUN("ossl-ssl-cipher-version", Fossl_ssl_cipher_version, 1, 1, 0, /*
4533 Return the protocol version of the tunnel SSL-CONN.
4537 /* SSL connection stuff */
4539 const SSL_CIPHER *ciph;
4540 /* network stream stuff */
4541 Lisp_SSL_CONN *lisp_ssl_conn;
4543 CHECK_SSLCONN(ssl_conn);
4544 lisp_ssl_conn = XSSLCONN(ssl_conn);
4546 conn = lisp_ssl_conn->ssl_conn;
4550 ciph = SSL_get_current_cipher(conn);
4552 if (!(ciph == NULL))
4553 return Fmake_symbol(
4554 build_string(SSL_CIPHER_get_version(ciph)));
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.
4564 /* SSL connection stuff */
4566 const SSL_CIPHER *ciph;
4567 /* network stream stuff */
4568 Lisp_SSL_CONN *lisp_ssl_conn;
4570 CHECK_SSLCONN(ssl_conn);
4571 lisp_ssl_conn = XSSLCONN(ssl_conn);
4573 conn = lisp_ssl_conn->ssl_conn;
4577 ciph = SSL_get_current_cipher(conn);
4579 if (!(ciph == NULL))
4580 return intern(SSL_CIPHER_get_name(ciph));
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.
4591 /* SSL connection stuff */
4593 STACK_OF(SSL_CIPHER) *ciphs;
4594 Lisp_Object result = Qnil;
4596 CHECK_SSLCONN(ssl_conn);
4598 conn = XSSLCONN(ssl_conn)->ssl_conn;
4602 ciphs = SSL_get_ciphers(conn);
4604 for (i=sk_SSL_CIPHER_num(ciphs)-1; i>=0; i--) {
4605 SSL_CIPHER *ciph = sk_SSL_CIPHER_value(ciphs, i);
4607 result = Fcons(intern(SSL_CIPHER_get_name(ciph)), result);
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.
4618 /* SSL connection stuff */
4620 const SSL_CIPHER *ciph;
4621 int alg_bits, strength_bits;
4622 /* network stream stuff */
4623 Lisp_SSL_CONN *lisp_ssl_conn;
4625 CHECK_SSLCONN(ssl_conn);
4626 lisp_ssl_conn = XSSLCONN(ssl_conn);
4628 conn = lisp_ssl_conn->ssl_conn;
4632 ciph = SSL_get_current_cipher(conn);
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);
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.
4647 /* SSL connection stuff */
4649 const SSL_CIPHER *ciph;
4650 /* network stream stuff */
4651 Lisp_SSL_CONN *lisp_ssl_conn;
4653 CHECK_SSLCONN(ssl_conn);
4654 lisp_ssl_conn = XSSLCONN(ssl_conn);
4656 conn = lisp_ssl_conn->ssl_conn;
4660 ciph = SSL_get_current_cipher(conn);
4662 if (!(ciph == NULL))
4663 return build_string(SSL_CIPHER_description(ciph, NULL, 0));
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).
4673 This will return a string in LDAP syntax.
4679 CHECK_EVPPKEY(cert);
4681 pk509 = XEVPPKEY(cert)->x509;
4684 X509_NAME *sub = X509_get_subject_name(pk509);
4685 return build_string(X509_NAME_oneline(sub, NULL, 0));
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.
4694 This will return a string in LDAP syntax.
4700 CHECK_EVPPKEY(cert);
4702 pk509 = XEVPPKEY(cert)->x509;
4705 X509_NAME *iss = X509_get_issuer_name(pk509);
4706 return build_string(X509_NAME_oneline(iss, NULL, 0));
4711 DEFUN("ossl-x509-serial", Fossl_x509_serial, 1, 1, 0, /*
4712 Return the certificate serial of CERT (an evp-pkey object).
4718 CHECK_EVPPKEY(cert);
4720 pk509 = XEVPPKEY(cert)->x509;
4723 ASN1_INTEGER *ser = X509_get_serialNumber(pk509);
4724 return make_integer(ASN1_INTEGER_get(ser));
4729 DEFUN("ossl-x509-not-before", Fossl_x509_not_before, 1, 1, 0, /*
4730 Return the certificate valid-not-before time of CERT.
4736 CHECK_EVPPKEY(cert);
4738 pk509 = XEVPPKEY(cert)->x509;
4741 ASN1_TIME *nbf = X509_get_notBefore(pk509);
4742 return build_string((char*)nbf->data);
4747 DEFUN("ossl-x509-not-after", Fossl_x509_not_after, 1, 1, 0, /*
4748 Return the certificate valid-not-after time of CERT.
4754 CHECK_EVPPKEY(cert);
4756 pk509 = XEVPPKEY(cert)->x509;
4759 ASN1_TIME *nbf = X509_get_notAfter(pk509);
4760 return build_string((char*)nbf->data);
4765 DEFUN("ossl-x509-signature-type", Fossl_x509_signature_type, 1, 1, 0, /*
4766 Return the signature type of CERT.
4772 CHECK_EVPPKEY(cert);
4774 pk509 = XEVPPKEY(cert)->x509;
4777 int ty = X509_get_signature_type(pk509);
4778 Lisp_Object result = Qnil;
4782 result = intern("none");
4784 #ifndef OPENSSL_NO_RSA
4786 result = intern("rsa");
4789 result = intern("rsa2");
4792 #ifndef OPENSSL_NO_DSA
4794 result = intern("dsa");
4797 result = intern("dsa1");
4800 result = intern("dsa2");
4803 result = intern("dsa3");
4806 result = intern("dsa4");
4809 #ifndef OPENSSL_NO_DH
4811 result = intern("dh");
4814 #ifndef OPENSSL_NO_EC
4816 result = intern("ec");
4820 result = intern("unknown");
4835 * Initialisation stuff
4838 void syms_of_openssl(void)
4840 INIT_LRECORD_IMPLEMENTATION(evp_pkey);
4841 INIT_LRECORD_IMPLEMENTATION(ssl_conn);
4843 defsymbol(&Qopenssl, "openssl");
4844 defsymbol(&Qevp_pkeyp, "ossl-pkey-p");
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);
4858 DEFSUBR(Fossl_rand_bytes);
4859 DEFSUBR(Fossl_rand_bytes_egd);
4861 DEFSUBR(Fossl_digest);
4862 DEFSUBR(Fossl_digest_file);
4864 DEFSUBR(Fossl_hmac);
4865 DEFSUBR(Fossl_hmac_file);
4867 DEFSUBR(Fossl_bytes_to_key);
4868 DEFSUBR(Fossl_encrypt);
4869 DEFSUBR(Fossl_encrypt_file);
4870 DEFSUBR(Fossl_decrypt);
4871 DEFSUBR(Fossl_decrypt_file);
4874 DEFSUBR(Fossl_pkey_p);
4875 DEFSUBR(Fossl_pkey_size);
4876 DEFSUBR(Fossl_pkey_private_p);
4877 DEFSUBR(Fossl_pkey_get_public);
4879 #ifndef OPENSSL_NO_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
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
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
4899 /* DEFSUBR(Fossl_ec_generate_key); */
4900 DEFSUBR(Fossl_dh_pkey_p);
4902 DEFSUBR(Fossl_seal);
4903 DEFSUBR(Fossl_open);
4905 DEFSUBR(Fossl_sign);
4906 DEFSUBR(Fossl_verify);
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);
4917 defsymbol(&Qssl_connp, "ossl-ssl-conn-p");
4918 defsymbol(&Qssl2, "ssl2");
4919 defsymbol(&Qssl23, "ssl23");
4920 defsymbol(&Qssl3, "ssl3");
4921 defsymbol(&Qtls1, "tls1");
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);
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);
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");
4982 void vars_of_openssl(void)
4984 DEFVAR_LISP("ossl-cipher-blacklist", &Vossl_cipher_blacklist /*
4985 A list of ciphers that are blacklisted against use.
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...
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);
5008 #ifndef OPENSSL_NO_RSA
5009 Fprovide(intern("openssl-rsa"));
5011 #ifndef OPENSSL_NO_DSA
5012 Fprovide(intern("openssl-dsa"));
5014 #ifndef OPENSSL_NO_EC
5015 Fprovide(intern("openssl-ec"));
5017 #ifndef OPENSSL_NO_DH
5018 Fprovide(intern("openssl-dh"));
5021 Fprovide(intern("openssl-ssl"));