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 extern Lisp_Object Qfile_readable_p;
426 extern Lisp_Object Qfile_writable_p;
433 DEFUN("ossl-version", Fossl_version, 0, 0, 0, /*
434 Return a descriptive version number of the OpenSSL in use.
438 return build_string(SSLeay_version(SSLEAY_VERSION));
442 DEFUN("ossl-available-digests", Fossl_available_digests, 0, 0, 0, /*
443 Return a list of digest algorithms in the underlying crypto library.
444 This yields a plain list of symbols.
453 OpenSSL_add_all_digests();
455 /* is there a better way to get the size of the nid list? */
456 for (nid = 10000; nid >= 0; --nid) {
457 const EVP_MD *digest = EVP_get_digestbynid(nid);
459 digests = Fcons(intern(OBJ_nid2sn(nid)), digests);
469 DEFUN("ossl-available-ciphers", Fossl_available_ciphers, 0, 0, 0, /*
470 Return a list of cipher algorithms in the underlying crypto library.
471 This yields a plain list of symbols.
478 OpenSSL_add_all_ciphers();
482 /* is there a better way to get the size of the nid list? */
483 for (nid = 10000; nid >= 0; --nid) {
484 const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
486 ciphers = Fcons(intern(OBJ_nid2sn(nid)), ciphers);
496 #define ossl_digest_fun(var, fun) \
499 const EVP_MD *__md; \
501 OpenSSL_add_all_digests(); \
503 __md = EVP_get_digestbyname( \
504 (char *)string_data(XSYMBOL(var)->name)); \
519 ossl_digest_size(Lisp_Object digest)
521 ossl_digest_fun(digest, EVP_MD_size);
525 ossl_digest_block_size(Lisp_Object digest)
527 ossl_digest_fun(digest, EVP_MD_block_size);
530 DEFUN("ossl-digest-size", Fossl_digest_size, 1, 1, 0, /*
531 Return the hash length of DIGEST in bytes.
535 int size = ossl_digest_size(digest);
538 error ("no such cipher");
540 return make_int(size);
544 DEFUN("ossl-digest-bits", Fossl_digest_bits, 1, 1, 0, /*
545 Return the number of effective output bits of DIGEST.
549 int size = ossl_digest_size(digest);
552 error ("no such digest");
554 return make_int(size*8);
557 DEFUN("ossl-digest-block-size", Fossl_digest_block_size, 1, 1, 0, /*
558 Return the block size of DIGEST in bytes.
562 int size = ossl_digest_block_size(digest);
565 error ("no such digest");
567 return make_int(size);
571 #define ossl_cipher_fun(var, fun) \
574 const EVP_CIPHER *__ciph; \
576 OpenSSL_add_all_ciphers(); \
578 __ciph = EVP_get_cipherbyname( \
579 (char *)string_data(XSYMBOL(var)->name)); \
586 __kl = fun(__ciph); \
594 ossl_cipher_key_length(Lisp_Object cipher)
596 ossl_cipher_fun(cipher, EVP_CIPHER_key_length);
600 ossl_cipher_iv_length(Lisp_Object cipher)
602 ossl_cipher_fun(cipher, EVP_CIPHER_iv_length);
606 ossl_cipher_block_size(Lisp_Object cipher)
608 ossl_cipher_fun(cipher, EVP_CIPHER_block_size);
612 ossl_cipher_mode(Lisp_Object cipher)
614 ossl_cipher_fun(cipher, EVP_CIPHER_mode);
617 DEFUN("ossl-cipher-key-length", Fossl_cipher_key_length, 1, 1, 0, /*
618 Return the effective key length of CIPHER in bytes.
622 int size = ossl_cipher_key_length(cipher);
625 error ("no such cipher");
627 return make_int(size);
631 DEFUN("ossl-cipher-bits", Fossl_cipher_bits, 1, 1, 0, /*
632 Return the effective key size of CIPHER in bits.
636 int size = ossl_cipher_key_length(cipher);
639 error ("no such cipher");
641 return make_int(size*8);
644 DEFUN("ossl-cipher-iv-length", Fossl_cipher_iv_length, 1, 1, 0, /*
645 Return the initialisation vector length of CIPHER in bytes.
649 int size = ossl_cipher_iv_length(cipher);
652 error ("no such cipher");
654 return make_int(size);
657 DEFUN("ossl-cipher-block-size", Fossl_cipher_block_size, 1, 1, 0, /*
658 Return the block size of CIPHER in bytes.
662 int size = ossl_cipher_block_size(cipher);
665 error ("no such cipher");
667 return make_int(size);
670 DEFUN("ossl-cipher-mode", Fossl_cipher_mode, 1, 1, 0, /*
671 Return the operation mode of CIPHER.
675 Lisp_Object result = Qnil;
676 int mode = ossl_cipher_mode(cipher);
679 error ("no such cipher");
682 case EVP_CIPH_STREAM_CIPHER:
683 result = intern("stream");
685 case EVP_CIPH_ECB_MODE:
686 result = intern("ecb");
688 case EVP_CIPH_CBC_MODE:
689 result = intern("cbc");
691 case EVP_CIPH_CFB_MODE:
692 result = intern("cfb");
694 case EVP_CIPH_OFB_MODE:
695 result = intern("ofb");
698 result = intern("cbc");
711 DEFUN("ossl-rand-bytes", Fossl_rand_bytes, 1, 1, 0, /*
712 Return COUNT bytes of randomness.
714 Note: You probably want to put a wrapping encoder function
715 \(like `base16-encode-string'\) around it, since this returns
721 Lisp_Object l_outbuf;
724 int speccount = specpdl_depth(), res;
727 count_ext = (int)XINT(count);
729 /* now allocate some output buffer externally */
730 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, count_ext, char);
732 res = RAND_bytes((unsigned char*)outbuf, count_ext);
734 error("RAND_bytes did not have enough seed "
735 "to perform operation");
737 } else if (res < 0) {
738 error("RAND_bytes failed");
742 l_outbuf = make_ext_string(outbuf, count_ext, OSSL_CODING);
743 XMALLOC_UNBIND(outbuf, count_ext, speccount);
748 DEFUN("ossl-rand-bytes-egd", Fossl_rand_bytes_egd, 1, 2, 0, /*
749 Return COUNT bytes of randomness from an EGD socket.
750 By default use the socket /var/run/egd-pool.
752 Note: You probably want to put a wrapping encoder function
753 \(like `base16-encode-string'\) around it, since this returns
758 /* This function can GC */
760 Lisp_Object l_outbuf;
762 int speccount = specpdl_depth(), res;
764 struct gcpro gcpro1, gcpro2;
771 egd = Fexpand_file_name(egd, Qnil);
772 if (NILP(Ffile_exists_p(egd)))
775 count_ext = XINT(count);
777 /* now allocate some output buffer externally */
778 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, count_ext, char);
781 res = RAND_query_egd_bytes((char*)XSTRING_DATA(egd),
782 (unsigned char*)outbuf, count_ext);
784 res = RAND_query_egd_bytes("/var/run/egd-pool",
785 (unsigned char*)outbuf, count_ext);
789 error("RAND_query_egd_bytes did not have enough seed "
790 "to perform operation");
792 } else if (res < 0) {
794 error("RAND_query_egd_bytes failed");
798 l_outbuf = make_ext_string(outbuf, count_ext, OSSL_CODING);
799 XMALLOC_UNBIND(outbuf, count_ext, speccount);
810 DEFUN("ossl-digest", Fossl_digest, 2, 2, 0, /*
811 Return the message digest of STRING computed by DIGEST.
812 DIGEST may be one of the OpenSSL digests you have compiled.
813 See `ossl-available-digests'.
815 Note: You probably want to put a wrapping encoder function
816 \(like `base16-encode-string'\) around it, since this returns
823 char md_value[EVP_MAX_MD_SIZE];
826 CHECK_SYMBOL(digest);
827 CHECK_STRING(string);
829 OpenSSL_add_all_digests();
830 md = EVP_get_digestbyname(
831 (char *)string_data(XSYMBOL(digest)->name));
835 error ("no such digest");
838 mdctx = xnew(EVP_MD_CTX);
839 EVP_MD_CTX_init(mdctx);
840 EVP_DigestInit_ex(mdctx, md, NULL);
841 EVP_DigestUpdate(mdctx,(char*)XSTRING_DATA(string),
842 XSTRING_LENGTH(string));
843 EVP_DigestFinal_ex(mdctx, (unsigned char *)md_value, &md_len);
844 EVP_MD_CTX_cleanup(mdctx);
849 return make_ext_string(md_value, md_len, OSSL_CODING);
852 DEFUN("ossl-digest-file", Fossl_digest_file, 2, 2, 0, /*
853 Return the message digest of the contents of FILE computed by DIGEST.
854 DIGEST may be one of the OpenSSL digests you have compiled.
855 See `ossl-available-digests'.
857 Note: You probably want to put a wrapping encoder function
858 \(like `base16-encode-string'\) around it, since this returns
865 unsigned char md_value[EVP_MAX_MD_SIZE];
866 unsigned int md_len, md_blocksize;
872 CHECK_SYMBOL(digest);
876 file = Fexpand_file_name(file, Qnil);
878 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
879 (fseek(fp, 0, SEEK_SET))) {
882 return wrong_type_argument(Qfile_readable_p, file);
885 OpenSSL_add_all_digests();
886 md = EVP_get_digestbyname(
887 (char *)string_data(XSYMBOL(digest)->name));
892 error ("no such digest");
895 mdctx = xnew(EVP_MD_CTX);
896 EVP_MD_CTX_init(mdctx);
897 md_blocksize = (unsigned int)(EVP_MD_block_size(md) / 8);
899 EVP_DigestInit_ex(mdctx, md, NULL);
901 /* we reuse md_value here for streaming over fp */
903 n = fread(md_value, 1, EVP_MAX_MD_SIZE, fp);
908 error("file corrupted");
911 EVP_DigestUpdate(mdctx, md_value, n);
914 EVP_DigestFinal_ex(mdctx, md_value, &md_len);
915 EVP_MD_CTX_cleanup(mdctx);
921 return make_ext_string((char *)md_value, md_len, OSSL_CODING);
927 * HMAC (aka keyed hashes)
930 DEFUN("ossl-hmac", Fossl_hmac, 3, 3, 0, /*
931 Return the message authentication code of MSG
932 using the hash function DIGEST and the key PASSWORD.
934 Note: You probably want to put a wrapping encoder function
935 \(like `base16-encode-string'\) around it, since this returns
938 (digest, msg, password))
943 /* buffer for the ciphertext */
944 unsigned char outbuf[EVP_MAX_MD_SIZE];
946 /* buffer for external password */
948 unsigned int password_len;
950 /* buffer for external message */
952 unsigned int msg_len;
955 CHECK_SYMBOL(digest);
957 CHECK_STRING(password);
959 OpenSSL_add_all_digests();
960 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
964 error ("no such digest");
967 TO_EXTERNAL_FORMAT (LISP_STRING, password,
968 C_STRING_ALLOCA, password_ext, OSSL_CODING);
969 password_len = OSSL_STRING_LENGTH(password);
971 #if 0 /* i wonder why */
972 TO_EXTERNAL_FORMAT (LISP_STRING, msg,
973 C_STRING_ALLOCA, msg_ext, OSSL_CODING);
974 msg_len = OSSL_STRING_LENGTH(msg);
977 hmacctx = xnew(HMAC_CTX);
978 HMAC_CTX_init(hmacctx);
979 HMAC_Init(hmacctx, password_ext, password_len, md);
980 HMAC_Update(hmacctx, (unsigned char*)XSTRING_DATA(msg),
981 XSTRING_LENGTH(msg));
982 HMAC_Final(hmacctx, outbuf, &outlen);
983 HMAC_CTX_cleanup(hmacctx);
988 return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
991 DEFUN("ossl-hmac-file", Fossl_hmac_file, 3, 3, 0, /*
992 Return the message authentication code of the contents of FILE
993 using the hash function DIGEST and the key PASSWORD.
995 Note: You probably want to put a wrapping encoder function
996 \(like `base16-encode-string'\) around it, since this returns
999 (digest, file, password))
1004 /* buffer for the ciphertext */
1005 unsigned char outbuf[EVP_MAX_MD_SIZE];
1006 unsigned int outlen;
1008 /* buffer for external password */
1010 unsigned int password_len;
1014 CHECK_SYMBOL(digest);
1016 CHECK_STRING(password);
1018 file = Fexpand_file_name(file, Qnil);
1020 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1021 (fseek(fp, 0, SEEK_SET))) {
1024 return wrong_type_argument(Qfile_readable_p, file);
1028 OpenSSL_add_all_digests();
1029 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
1033 error ("no such digest");
1036 TO_EXTERNAL_FORMAT (LISP_STRING, password,
1037 C_STRING_ALLOCA, password_ext, OSSL_CODING);
1038 password_len = OSSL_STRING_LENGTH(password);
1040 hmacctx = xnew(HMAC_CTX);
1041 HMAC_CTX_init(hmacctx);
1042 HMAC_Init(hmacctx, password_ext, password_len, md);
1044 /* we reuse md_value here for streaming over fp */
1046 n = fread(outbuf, 1, EVP_MAX_MD_SIZE, fp);
1051 error("file corrupted");
1054 HMAC_Update(hmacctx, outbuf, n);
1057 HMAC_Final(hmacctx, outbuf, &outlen);
1058 HMAC_CTX_cleanup(hmacctx);
1064 return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1073 DEFUN("ossl-bytes-to-key", Fossl_bytes_to_key, 5, 5, 0, /*
1074 Derive a key and initialisation vector (iv) suitable for a cipher.
1075 Return a string KEY being the key. The initialisation vector is
1076 put into KEY's property list as 'iv.
1078 CIPHER \(a symbol\) is the cipher to derive the key and IV for.
1079 Valid ciphers can be obtained by `ossl-available-ciphers'.
1081 DIGEST \(a symbol\) is the message digest to use.
1082 Valid digests can be obtained by `ossl-available-digests'.
1084 SALT \(string or `nil'\) is used as a salt in the derivation.
1085 Use `nil' here to indicate that no salt is used.
1087 PASSWORD is an arbitrary string which is processed to derive a
1090 COUNT \(a positive integer\) is the iteration count to use. This
1091 indicates how often the hash algorithm is called recursively.
1093 Note: You probably want to put a wrapping encoder function
1094 \(like `base16-encode-string'\) around it, since this returns
1097 (cipher, digest, salt, password, count))
1100 const EVP_CIPHER *ciph;
1101 const char *salt_ext;
1104 unsigned int password_len;
1106 char key[EVP_MAX_KEY_LENGTH];
1107 char iv[EVP_MAX_IV_LENGTH];
1111 CHECK_STRING(password);
1112 CHECK_SYMBOL(cipher);
1113 CHECK_SYMBOL(digest);
1114 CHECK_NATNUM(count);
1118 error ("count has to be a non-zero positive integer");
1120 OpenSSL_add_all_algorithms();
1121 md = EVP_get_digestbyname(
1122 (char *)string_data(XSYMBOL(digest)->name));
1123 ciph = EVP_get_cipherbyname(
1124 (char *)string_data(XSYMBOL(cipher)->name));
1128 error ("no such cipher");
1133 error ("no such digest");
1140 TO_EXTERNAL_FORMAT (LISP_STRING, salt,
1141 C_STRING_ALLOCA, salt_ext, OSSL_CODING);
1145 TO_EXTERNAL_FORMAT (LISP_STRING, password,
1146 C_STRING_ALLOCA, password_ext, OSSL_CODING);
1147 password_len = OSSL_STRING_LENGTH(password);
1149 EVP_BytesToKey(ciph, md, (const unsigned char *)salt_ext,
1150 (const unsigned char *)password_ext, password_len,
1152 (unsigned char *)key,
1153 (unsigned char *)iv);
1157 result = make_ext_string(key, EVP_CIPHER_key_length(ciph), OSSL_CODING);
1158 Fput(result, intern("iv"),
1159 make_ext_string(iv, EVP_CIPHER_iv_length(ciph), OSSL_CODING));
1165 DEFUN("ossl-encrypt", Fossl_encrypt, 3, 4, 0, /*
1166 Return the cipher of STRING computed by CIPHER under KEY.
1168 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1169 you have compiled. See `ossl-available-ciphers'.
1171 STRING is the text to be encrypted.
1173 KEY should be a key generated suitably for this cipher, for example
1174 by `ossl-bytes-to-key'.
1176 Optional fourth argument IV should be an initialisation vector
1177 suitable for this cipher. Normally the initialisation vector from
1178 KEY's property list is used. However, if IV is
1179 non-nil, use this IV instead.
1181 Note: You probably want to put a wrapping encoder function
1182 \(like `base16-encode-string'\) around it, since this returns
1185 (cipher, string, key, iv))
1187 /* buffer for the external string */
1189 unsigned int string_len;
1190 /* buffer for the ciphertext */
1193 Lisp_Object l_outbuf;
1194 /* buffer for key */
1199 /* declarations for the cipher */
1200 const EVP_CIPHER *ciph;
1201 EVP_CIPHER_CTX *ciphctx;
1204 int speccount = specpdl_depth();
1207 /* frob the IV from the plist of key maybe */
1209 iv = Fget(key, intern("iv"), Qnil);
1211 CHECK_SYMBOL(cipher);
1212 CHECK_STRING(string);
1216 TO_EXTERNAL_FORMAT(LISP_STRING, string,
1217 C_STRING_ALLOCA, string_ext, OSSL_CODING);
1218 string_len = OSSL_STRING_LENGTH(string);
1220 if (string_len <= 0)
1221 error ("string must be of non-zero positive length.");
1223 OpenSSL_add_all_algorithms();
1224 /* ENGINE_load_builtin_engines(); */
1225 /* atm, no support for different engines */
1226 ciph = EVP_get_cipherbyname(
1227 (char *)string_data(XSYMBOL(cipher)->name));
1231 error ("no such cipher");
1234 /* now allocate some output buffer externally
1235 * this one has to be at least EVP_CIPHER_block_size bigger
1236 * since block algorithms merely operate blockwise
1238 alloclen = XSTRING_LENGTH(string) + EVP_CIPHER_block_size(ciph);
1239 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
1241 TO_EXTERNAL_FORMAT(LISP_STRING, key,
1242 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1243 TO_EXTERNAL_FORMAT(LISP_STRING, iv,
1244 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1246 ciphctx = xnew(EVP_CIPHER_CTX);
1247 EVP_CIPHER_CTX_init(ciphctx);
1248 if (!EVP_EncryptInit(ciphctx, ciph,
1249 (unsigned char *)key_ext,
1250 (unsigned char *)iv_ext)) {
1253 error ("error in EncryptInit");
1255 if (!EVP_EncryptUpdate(ciphctx,
1256 (unsigned char *)outbuf, &outlen,
1257 (unsigned char *)string_ext, string_len)) {
1260 error ("error in EncryptUpdate");
1262 /* Buffer passed to EVP_EncryptFinal() must be after data just
1263 * encrypted to avoid overwriting it.
1265 if (!EVP_EncryptFinal(ciphctx,
1266 (unsigned char *)outbuf+outlen, &tmplen)) {
1269 error ("error in EncryptFinal");
1271 /* added probable padding space to the length of the output buffer */
1273 EVP_CIPHER_CTX_cleanup(ciphctx);
1275 l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1276 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1284 DEFUN("ossl-encrypt-file", Fossl_encrypt_file, 3, 5, 0, /*
1285 Return the encrypted contents of FILE computed by CIPHER under KEY.
1287 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1288 you have compiled. See `ossl-available-ciphers'.
1290 FILE is the file to be encrypted.
1292 Third argument KEY should be a key generated suitably for this
1293 cipher, for example by `ossl-bytes-to-key'.
1295 Optional fourth argument IV should be an initialisation vector
1296 suitable for this cipher. Normally the initialisation vector from
1297 KEY's property list is used. However, if IV is
1298 non-nil, use this IV instead.
1300 Optional fifth argument OUTFILE may specify a file to have the
1301 encrypted data redirected.
1303 Note: You probably want to put a wrapping encoder function
1304 \(like `base16-encode-string'\) around it, since this returns
1307 (cipher, file, key, iv, outfile))
1309 /* buffer for the external string */
1310 unsigned char string_in[1024];
1312 unsigned int block_len;
1313 unsigned long file_size;
1314 /* buffer for the ciphertext */
1315 unsigned char *outbuf;
1318 Lisp_Object l_outbuf;
1319 /* buffer for key */
1329 /* declarations for the cipher */
1330 const EVP_CIPHER *ciph;
1331 EVP_CIPHER_CTX *ciphctx;
1334 int speccount = specpdl_depth();
1337 /* frob the IV from the plist of key maybe */
1339 iv = Fget(key, intern("iv"), Qnil);
1341 CHECK_SYMBOL(cipher);
1346 if (!NILP(outfile)) {
1347 CHECK_STRING(outfile);
1348 outfile = Fexpand_file_name(outfile, Qnil);
1349 if ((of = fopen((char *)XSTRING_DATA(outfile),"wb")) == NULL)
1350 return wrong_type_argument(Qfile_writable_p, outfile);
1355 file = Fexpand_file_name(file, Qnil);
1356 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1357 (fseek(fp, 0, SEEK_SET))) {
1362 return wrong_type_argument(Qfile_readable_p, file);
1365 fseek(fp, 0, SEEK_END);
1366 file_size = ftell(fp);
1367 fseek(fp, 0, SEEK_SET);
1370 OpenSSL_add_all_algorithms();
1371 /* ENGINE_load_builtin_engines(); */
1372 /* atm, no support for different engines */
1373 ciph = EVP_get_cipherbyname(
1374 (char *)string_data(XSYMBOL(cipher)->name));
1381 error ("no such cipher");
1384 /* now allocate some output buffer externally
1385 * this one has to be at least EVP_CIPHER_block_size bigger
1386 * since block algorithms merely operate blockwise
1388 block_len = EVP_CIPHER_block_size(ciph);
1389 if (UNLIKELY(of != NULL)) {
1392 alloclen = file_size + block_len;
1394 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
1396 TO_EXTERNAL_FORMAT(LISP_STRING, key,
1397 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1398 TO_EXTERNAL_FORMAT(LISP_STRING, iv,
1399 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1401 ciphctx = xnew(EVP_CIPHER_CTX);
1402 EVP_CIPHER_CTX_init(ciphctx);
1403 if (!EVP_EncryptInit(ciphctx, ciph,
1404 (unsigned char *)key_ext,
1405 (unsigned char *)iv_ext)) {
1411 error("error in EncryptInit");
1417 string_len = fread(string_in, 1, 1024, fp);
1418 if (string_len < 0) {
1424 error("file corrupted");
1429 if (string_len > 0 &&
1430 !EVP_EncryptUpdate(ciphctx,
1432 string_in, string_len)) {
1438 error("error in EncryptUpdate");
1442 fwrite(obp, 1, tmplen, of);
1447 } while (string_len > 0);
1449 /* Buffer passed to EVP_EncryptFinal() must be after data just
1450 * encrypted to avoid overwriting it.
1452 if (!EVP_EncryptFinal(ciphctx, obp, &tmplen)) {
1458 error("error in EncryptFinal");
1462 fwrite(obp, 1, tmplen, of);
1464 /* added probable padding space to the length of the output buffer */
1466 EVP_CIPHER_CTX_cleanup(ciphctx);
1468 if (UNLIKELY(of != NULL)) {
1471 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1473 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1484 (setq k (ossl-bytes-to-key 'AES-256-OFB 'SHA1 nil "password" 1))
1485 (ossl-encrypt-file 'AES-256-OFB "~/.gnus" k nil "/tmp/gnus-enc")
1486 (ossl-decrypt-file 'AES-256-OFB "/tmp/gnus-enc" k nil "/tmp/gnus-dec")
1490 DEFUN("ossl-decrypt", Fossl_decrypt, 3, 4, 0, /*
1491 Return the deciphered version of STRING computed by CIPHER under KEY.
1493 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1494 you have compiled. See `ossl-available-ciphers'.
1496 STRING is the text to be decrypted.
1498 KEY should be a key generated suitably for this
1499 cipher, for example by `ossl-bytes-to-key'.
1501 Optional fourth argument IV should be an initialisation vector
1502 suitable for this cipher. Normally the initialisation vector from
1503 KEY's property list is used. However, if IV is
1504 non-nil, use this IV instead.
1506 (cipher, string, key, iv))
1508 /* buffer for the external string */
1510 unsigned int string_len;
1511 /* buffer for the deciphered text */
1514 Lisp_Object l_outbuf;
1515 /* buffer for key */
1520 /* declarations for the decipher */
1521 const EVP_CIPHER *ciph;
1522 EVP_CIPHER_CTX *ciphctx;
1525 int speccount = specpdl_depth();
1528 /* frob the IV from the plist of key maybe */
1530 iv = Fget(key, intern("iv"), Qnil);
1532 CHECK_SYMBOL(cipher);
1533 CHECK_STRING(string);
1537 TO_EXTERNAL_FORMAT(LISP_STRING, string,
1538 C_STRING_ALLOCA, string_ext, OSSL_CODING);
1539 string_len = OSSL_STRING_LENGTH(string);
1542 error ("string must be of non-zero positive length.");
1544 OpenSSL_add_all_algorithms();
1545 /* ENGINE_load_builtin_engines(); */
1546 /* atm, no support for different engines */
1547 ciph = EVP_get_cipherbyname(
1548 (char *)string_data(XSYMBOL(cipher)->name));
1552 error ("no such cipher");
1555 /* now allocate some output buffer externally */
1556 alloclen = XSTRING_LENGTH(string);
1557 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
1559 TO_EXTERNAL_FORMAT (LISP_STRING, key,
1560 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1561 TO_EXTERNAL_FORMAT (LISP_STRING, iv,
1562 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1564 ciphctx = xnew(EVP_CIPHER_CTX);
1565 EVP_CIPHER_CTX_init(ciphctx);
1566 if (!EVP_DecryptInit(ciphctx, ciph,
1567 (unsigned char *)key_ext,
1568 (unsigned char *)iv_ext)) {
1571 error ("error in DecryptInit");
1573 if (!EVP_DecryptUpdate(ciphctx,
1574 (unsigned char *)outbuf, &outlen,
1575 (unsigned char *)string_ext,string_len)) {
1578 error ("error in DecryptUpdate");
1580 /* Buffer passed to EVP_EncryptFinal() must be after data just
1581 * encrypted to avoid overwriting it.
1583 if (!EVP_DecryptFinal(ciphctx,
1584 (unsigned char *)outbuf+outlen, &tmplen)) {
1587 error ("error in DecryptFinal");
1589 /* added probable padding space to the length of the output buffer */
1591 EVP_CIPHER_CTX_cleanup(ciphctx);
1593 l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1594 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1602 DEFUN("ossl-decrypt-file", Fossl_decrypt_file, 3, 5, 0, /*
1603 Return the deciphered version of FILE computed by CIPHER under KEY.
1605 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1606 you have compiled. See `ossl-available-ciphers'.
1608 FILE is the file to be decrypted.
1610 Third argument KEY should be a key generated suitably for this
1611 cipher, for example by `ossl-bytes-to-key'.
1613 Optional fourth argument IV should be an initialisation vector
1614 suitable for this cipher. Normally the initialisation vector from
1615 KEY's property list is used. However, if IV is
1616 non-nil, use this IV instead.
1618 Optional fifth argument OUTFILE may specify a file to have the
1619 encrypted data redirected.
1621 (cipher, file, key, iv, outfile))
1623 /* buffer for the external string */
1624 unsigned char string_in[1024];
1626 unsigned int block_len;
1627 unsigned long file_size;
1628 /* buffer for the deciphered text */
1629 unsigned char *outbuf;
1632 Lisp_Object l_outbuf;
1633 /* buffer for key */
1643 /* declarations for the decipher */
1644 const EVP_CIPHER *ciph;
1645 EVP_CIPHER_CTX *ciphctx;
1648 int speccount = specpdl_depth();
1651 /* frob the IV from the plist of key maybe */
1653 iv = Fget(key, intern("iv"), Qnil);
1655 CHECK_SYMBOL(cipher);
1660 if (!NILP(outfile)) {
1661 CHECK_STRING(outfile);
1662 outfile = Fexpand_file_name(outfile, Qnil);
1663 if ((of = fopen((char *)XSTRING_DATA(outfile),"wb")) == NULL)
1664 return wrong_type_argument(Qfile_writable_p, outfile);
1669 file = Fexpand_file_name(file, Qnil);
1670 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1671 (fseek(fp, 0, SEEK_SET))) {
1676 return wrong_type_argument(Qfile_readable_p, file);
1679 fseek(fp, 0, SEEK_END);
1680 file_size = ftell(fp);
1681 fseek(fp, 0, SEEK_SET);
1684 OpenSSL_add_all_algorithms();
1685 /* ENGINE_load_builtin_engines(); */
1686 /* atm, no support for different engines */
1687 ciph = EVP_get_cipherbyname(
1688 (char *)string_data(XSYMBOL(cipher)->name));
1695 error ("no such cipher");
1698 /* now allocate some output buffer externally */
1699 block_len = EVP_CIPHER_block_size(ciph);
1700 if (UNLIKELY(of != NULL)) {
1703 alloclen = file_size + block_len;
1705 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
1707 TO_EXTERNAL_FORMAT (LISP_STRING, key,
1708 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1709 TO_EXTERNAL_FORMAT (LISP_STRING, iv,
1710 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1712 ciphctx = xnew(EVP_CIPHER_CTX);
1713 EVP_CIPHER_CTX_init(ciphctx);
1714 if (!EVP_DecryptInit(ciphctx, ciph,
1715 (unsigned char *)key_ext,
1716 (unsigned char *)iv_ext)) {
1722 error ("error in DecryptInit");
1728 string_len = fread(string_in, 1, 1024, fp);
1729 if (string_len < 0) {
1735 error("file corrupted");
1740 if (string_len > 0 &&
1741 !EVP_DecryptUpdate(ciphctx,
1743 string_in, string_len)) {
1749 error ("error in DecryptUpdate");
1753 fwrite(obp, 1, tmplen, of);
1758 } while (string_len > 0);
1760 /* Buffer passed to EVP_EncryptFinal() must be after data just
1761 * encrypted to avoid overwriting it.
1763 if (!EVP_DecryptFinal(ciphctx, obp, &tmplen)) {
1769 error ("error in DecryptFinal");
1773 fwrite(obp, 1, tmplen, of);
1775 /* added probable padding space to the length of the output buffer */
1777 EVP_CIPHER_CTX_cleanup(ciphctx);
1779 if (UNLIKELY(of != NULL)) {
1782 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1784 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1801 /* This is an opaque object for storing PKEYs in lisp */
1802 Lisp_Object Qevp_pkeyp;
1805 mark_evp_pkey(Lisp_Object obj)
1807 /* avoid some warning */
1813 print_evp_pkey(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1818 pkey = XEVPPKEY(obj)->evp_pkey;
1819 x509 = XEVPPKEY(obj)->x509;
1821 write_c_string("#<OpenSSL", printcharfun);
1824 X509_NAME *iss = X509_get_issuer_name(x509);
1825 X509_NAME *sub = X509_get_subject_name(x509);
1826 write_c_string(" X509 Certificate", printcharfun);
1827 write_c_string(" iss:", printcharfun);
1828 write_c_string(X509_NAME_oneline(sub, NULL, 0), printcharfun);
1829 write_c_string(" sub:", printcharfun);
1830 write_c_string(X509_NAME_oneline(iss, NULL, 0), printcharfun);
1835 write_c_string(";", printcharfun);
1837 if (rsa_pkey_p(pkey))
1838 write_c_string(" RSA", printcharfun);
1839 else if (dsa_pkey_p(pkey))
1840 write_c_string(" DSA", printcharfun);
1841 else if (ec_pkey_p(pkey))
1842 write_c_string(" EC", printcharfun);
1844 if (ossl_pkey_has_private_data(pkey))
1845 write_c_string(" private/public key", printcharfun);
1846 else if (ossl_pkey_has_public_data(pkey))
1847 write_c_string(" public key", printcharfun);
1849 write_c_string(" empty key", printcharfun);
1851 if (EVP_PKEY_size(pkey) > 0) {
1852 write_fmt_str(printcharfun, ", size %d", EVP_PKEY_size(pkey)*8);
1856 write_c_string(">", printcharfun);
1858 /* avoid some warning */
1862 static Lisp_EVP_PKEY *
1863 allocate_evp_pkey(void)
1865 Lisp_EVP_PKEY *evp_pkey =
1866 alloc_lcrecord_type(Lisp_EVP_PKEY, &lrecord_evp_pkey);
1867 evp_pkey->evp_pkey = NULL;
1868 evp_pkey->x509 = NULL;
1873 finalise_evp_pkey(void *header, int for_disksave)
1875 Lisp_EVP_PKEY *evp_pkey = (Lisp_EVP_PKEY *) header;
1877 if (evp_pkey->evp_pkey) {
1878 EVP_PKEY_free(evp_pkey->evp_pkey);
1879 evp_pkey->evp_pkey = NULL;
1881 if (evp_pkey->x509) {
1882 X509_free(evp_pkey->x509);
1883 evp_pkey->x509 = NULL;
1886 /* avoid some warning */
1890 DEFINE_LRECORD_IMPLEMENTATION("evp_pkey", evp_pkey,
1891 mark_evp_pkey, print_evp_pkey,
1897 make_evp_pkey(EVP_PKEY *pkey, X509 *x509)
1899 Lisp_EVP_PKEY *lisp_pkey = allocate_evp_pkey();
1901 lisp_pkey->evp_pkey = pkey;
1902 lisp_pkey->x509 = x509;
1904 return wrap_evppkey(lisp_pkey);
1908 make_evp_pkey_pk(EVP_PKEY *pkey)
1910 return make_evp_pkey(pkey, NULL);
1914 make_evp_pkey_x509(X509 *x509)
1916 return make_evp_pkey(X509_get_pubkey(x509), x509);
1919 DEFUN("ossl-pkey-p", Fossl_pkey_p, 1, 1, 0, /*
1920 Return t iff OBJECT is a pkey, nil otherwise.
1924 if (EVPPKEYP(object))
1930 DEFUN("ossl-pkey-size", Fossl_pkey_size, 1, 1, 0, /*
1931 Return the size a public key PKEY in bits.
1937 CHECK_EVPPKEY(pkey);
1939 pk = (XEVPPKEY(pkey))->evp_pkey;
1941 return make_int(EVP_PKEY_size(pk)*8);
1945 ossl_pkey_has_public_data(EVP_PKEY *pkey)
1947 if (rsa_pkey_p(pkey)) {
1948 #ifndef OPENSSL_NO_RSA
1949 return rsa_pkey_has_public_data((pkey->pkey).rsa);
1953 } else if (dsa_pkey_p(pkey)) {
1954 #ifndef OPENSSL_NO_DSA
1955 return dsa_pkey_has_public_data((pkey->pkey).dsa);
1959 } else if (ec_pkey_p(pkey)) {
1960 #ifndef OPENSSL_NO_EC
1961 return ec_pkey_has_public_data((pkey->pkey).ec);
1965 } else if (dh_pkey_p(pkey)) {
1966 #ifndef OPENSSL_NO_DH
1967 return dh_pkey_has_public_data((pkey->pkey).dh);
1975 ossl_pkey_has_private_data(EVP_PKEY *pkey)
1977 if (rsa_pkey_p(pkey)) {
1978 #ifndef OPENSSL_NO_RSA
1979 return rsa_pkey_has_private_data((pkey->pkey).rsa);
1983 } else if (dsa_pkey_p(pkey)) {
1984 #ifndef OPENSSL_NO_DSA
1985 return dsa_pkey_has_private_data((pkey->pkey).dsa);
1989 } else if (ec_pkey_p(pkey)) {
1990 #ifndef OPENSSL_NO_EC
1991 return ec_pkey_has_private_data((pkey->pkey).ec);
1995 } else if (dh_pkey_p(pkey)) {
1996 #ifndef OPENSSL_NO_DH
1997 return dh_pkey_has_private_data((pkey->pkey).dh);
2005 DEFUN("ossl-pkey-private-p", Fossl_pkey_private_p, 1, 1, 0, /*
2006 Return non-nil if PKEY contains private data.
2008 This function is not native OpenSSL.
2014 if (!(EVPPKEYP(pkey)))
2017 pk = (XEVPPKEY(pkey))->evp_pkey;
2019 if (ossl_pkey_has_private_data(pk))
2025 DEFUN("ossl-pkey-get-public", Fossl_pkey_get_public, 1, 1, 0, /*
2026 Return a copy of PKEY stripped by the private data.
2028 This function is not native OpenSSL.
2035 CHECK_EVPPKEY(pkey);
2037 pk = (XEVPPKEY(pkey))->evp_pkey;
2038 if (!(ossl_pkey_has_public_data(pk)))
2039 error ("key must have public data");
2041 pkout = EVP_PKEY_new();
2042 if (rsa_pkey_p(pk)) {
2043 #ifndef OPENSSL_NO_RSA
2044 EVP_PKEY_assign_RSA(pkout, RSAPublicKey_dup((pk->pkey).rsa));
2046 } else if (dsa_pkey_p(pk)) {
2047 #ifndef OPENSSL_NO_DSA
2048 EVP_PKEY_assign_DSA(pkout, dsa_get_public(pk));
2050 } else if (ec_pkey_p(pk)) {
2051 #ifndef OPENSSL_NO_EC
2052 EVP_PKEY_assign_EC_KEY(pkout, ec_get_public(pk));
2055 error ("no method to strip private data yet");
2057 return make_evp_pkey_pk(pkout);
2062 rsa_pkey_p(EVP_PKEY *pkey)
2066 type = EVP_PKEY_type(pkey->type);
2068 #ifndef OPENSSL_NO_RSA
2069 return ((type == EVP_PKEY_RSA) ||
2070 (type == EVP_PKEY_RSA2));
2075 #ifndef OPENSSL_NO_RSA
2077 rsa_pkey_has_public_data(RSA *rsakey)
2079 return (!(rsakey->n == NULL) &&
2080 !(rsakey->e == NULL));
2083 rsa_pkey_has_private_data(RSA *rsakey)
2085 return (rsa_pkey_has_public_data(rsakey) &&
2086 !(rsakey->d == NULL));
2089 DEFUN("ossl-rsa-generate-key", Fossl_rsa_generate_key, 2, 2, 0, /*
2090 Return an RSA public key with of length BITS and exponent EXPO.
2102 error ("modulus size must be a non-zero positive integer");
2103 if (!(XINT(expo) % 2))
2104 error ("exponent must be an odd positive integer");
2106 pkey = EVP_PKEY_new();
2107 rsakey = RSA_generate_key(XINT(bits), XINT(expo), NULL, NULL);
2108 EVP_PKEY_assign_RSA(pkey, rsakey);
2110 return make_evp_pkey_pk(pkey);
2113 DEFUN("ossl-rsa-pkey-p", Fossl_rsa_pkey_p, 1, 1, 0, /*
2114 Return t iff PKEY is of RSA type.
2120 if (!EVPPKEYP(pkey))
2123 pk = (XEVPPKEY(pkey))->evp_pkey;
2131 DEFUN("ossl-rsa-subkey-p", Fossl_rsa_subkey_p, 2, 2, 0, /*
2132 Return t iff PKEY1 is a subkey of PKEY2.
2133 I.e. if PKEY1 has the same public key data as PKEY2 and
2134 PKEY2 has all private data.
2136 This function is not native OpenSSL.
2145 CHECK_EVPPKEY(pkey1);
2146 CHECK_EVPPKEY(pkey2);
2148 pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2149 pk2 = (XEVPPKEY(pkey2))->evp_pkey;
2151 /* perform a type check first */
2152 if (!rsa_pkey_p(pk1))
2153 error ("pkey1 must be of RSA type");
2154 if (!rsa_pkey_p(pk2))
2155 error ("pkey2 must be of RSA type");
2157 rk1 = (pk1->pkey).rsa;
2158 rk2 = (pk2->pkey).rsa;
2160 if (rsa_pkey_has_private_data(rk2) &&
2161 rsa_pkey_has_public_data(rk1) &&
2162 (!BN_cmp(rk1->n, rk2->n)) &&
2163 (!BN_cmp(rk1->e, rk2->e)))
2168 #endif /* OPENSSL_NO_RSA */
2173 dsa_pkey_p(EVP_PKEY *pkey)
2177 type = EVP_PKEY_type(pkey->type);
2179 #ifndef OPENSSL_NO_DSA
2180 return ((type == EVP_PKEY_DSA) ||
2181 (type == EVP_PKEY_DSA1) ||
2182 (type == EVP_PKEY_DSA2) ||
2183 (type == EVP_PKEY_DSA3) ||
2184 (type == EVP_PKEY_DSA4));
2189 #ifndef OPENSSL_NO_DSA
2191 dsa_pkey_has_public_data(DSA *dsakey)
2193 return (!(dsakey->p == NULL) &&
2194 !(dsakey->q == NULL) &&
2195 !(dsakey->g == NULL) &&
2196 !(dsakey->pub_key == NULL));
2199 dsa_pkey_has_private_data(DSA *dsakey)
2201 return (dsa_pkey_has_public_data(dsakey) &&
2202 !(dsakey->priv_key == NULL));
2205 DEFUN("ossl-dsa-generate-key", Fossl_dsa_generate_key, 1, 2, 0, /*
2206 Return a DSA public key with of length BITS seeded with (optional) SEED.
2215 unsigned_long h_ret;
2222 error ("prime number size must be a non-zero positive integer");
2229 TO_EXTERNAL_FORMAT (LISP_STRING, seed,
2230 C_STRING_ALLOCA, seed_ext, OSSL_CODING);
2231 seed_len = OSSL_STRING_LENGTH(seed);
2234 pkey = EVP_PKEY_new();
2235 dsakey = DSA_generate_parameters(XINT(bits),
2236 (unsigned char*)seed_ext, seed_len,
2237 &counter_ret, &h_ret,
2239 if (!DSA_generate_key(dsakey))
2240 error ("error during generation of DSA key");
2242 EVP_PKEY_assign_DSA(pkey, dsakey);
2244 return make_evp_pkey_pk(pkey);
2247 DEFUN("ossl-dsa-pkey-p", Fossl_dsa_pkey_p, 1, 1, 0, /*
2248 Return t iff PKEY is of DSA type.
2254 if (!EVPPKEYP(pkey))
2257 pk = (XEVPPKEY(pkey))->evp_pkey;
2265 dsa_get_public(EVP_PKEY *pk)
2270 memcpy(key, (pk->pkey).dsa, sizeof(DSA));
2272 /* now kill the private data */
2273 key->priv_key = NULL;
2278 DEFUN("ossl-dsa-subkey-p", Fossl_dsa_subkey_p, 2, 2, 0, /*
2279 Return t iff PKEY1 is a subkey of PKEY2.
2280 I.e. if PKEY1 has the same public key data as PKEY2 and
2281 PKEY2 has all private data.
2283 This function is not native OpenSSL.
2292 CHECK_EVPPKEY(pkey1);
2293 CHECK_EVPPKEY(pkey2);
2295 pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2296 pk2 = (XEVPPKEY(pkey2))->evp_pkey;
2298 /* perform a type check first */
2299 if (!dsa_pkey_p(pk1))
2300 error ("pkey1 must be of DSA type");
2301 if (!dsa_pkey_p(pk2))
2302 error ("pkey2 must be of DSA type");
2304 dk1 = (pk1->pkey).dsa;
2305 dk2 = (pk2->pkey).dsa;
2307 if (dsa_pkey_has_private_data(dk2) &&
2308 dsa_pkey_has_public_data(dk1) &&
2309 (!BN_cmp(dk1->p, dk2->p)) &&
2310 (!BN_cmp(dk1->q, dk2->q)) &&
2311 (!BN_cmp(dk1->g, dk2->g)) &&
2312 (!BN_cmp(dk1->pub_key, dk2->pub_key)))
2317 #endif /* OPENSSL_NO_DSA */
2322 ec_pkey_p(EVP_PKEY *pkey)
2326 type = EVP_PKEY_type(pkey->type);
2328 #ifndef OPENSSL_NO_EC
2329 return (type == EVP_PKEY_EC);
2334 #ifndef OPENSSL_NO_EC
2336 ec_pkey_has_public_data(EC_KEY *ec_key)
2338 return (!(EC_KEY_get0_group(ec_key) == NULL) &&
2339 !(EC_KEY_get0_public_key(ec_key) == NULL));
2342 ec_pkey_has_private_data(EC_KEY *ec_key)
2344 return (ec_pkey_has_public_data(ec_key) &&
2345 !(EC_KEY_get0_private_key(ec_key) == NULL));
2348 DEFUN("ossl-ec-available-curves", Fossl_ec_available_curves, 0, 0, 0, /*
2349 Return a list of builtin elliptic curves.
2353 EC_builtin_curve *curves = NULL;
2354 size_t crv_len = 0, n = 0;
2355 Lisp_Object lcurves;
2359 crv_len = EC_get_builtin_curves(NULL, 0);
2360 curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
2363 error ("no curves defined");
2365 if (!EC_get_builtin_curves(curves, crv_len)) {
2366 OPENSSL_free(curves);
2367 error ("error during initialisation of curves");
2370 for (n = 0; n < crv_len; n++) {
2371 int nid = curves[n].nid;
2372 lcurves = Fcons(intern(OBJ_nid2sn(nid)), lcurves);
2375 OPENSSL_free(curves);
2381 ec_curve_by_name(char *name)
2383 return OBJ_sn2nid(name);
2386 DEFUN("ossl-ec-generate-key", Fossl_ec_generate_key, 1, 1, 0, /*
2387 Return a EC public key on CURVE.
2388 CURVE may be any symbol from `ossl-ec-available-curves'.
2390 At the moment we do not support creating custom curves.
2397 CHECK_SYMBOL(curve);
2399 pkey = EVP_PKEY_new();
2400 eckey = EC_KEY_new_by_curve_name(
2401 ec_curve_by_name((char *)string_data(XSYMBOL(curve)->name)));
2403 if (eckey == NULL) {
2404 error ("no such curve");
2407 if (!EC_KEY_generate_key(eckey))
2408 error ("error during generation of EC key");
2410 EVP_PKEY_assign_EC_KEY(pkey, eckey);
2412 return make_evp_pkey_pk(pkey);
2415 DEFUN("ossl-ec-pkey-p", Fossl_ec_pkey_p, 1, 1, 0, /*
2416 Return t iff PKEY is of EC type.
2423 if (!EVPPKEYP(pkey))
2426 pk = (XEVPPKEY(pkey))->evp_pkey;
2427 type = EVP_PKEY_type(pk->type);
2428 if (type == EVP_PKEY_EC)
2435 ec_get_public(EVP_PKEY *pk)
2439 key = EC_KEY_dup((pk->pkey).ec);
2441 /* now kill the private data */
2442 EC_KEY_set_private_key(key, NULL);
2446 #endif /* OPENSSL_NO_EC */
2451 dh_pkey_p(EVP_PKEY *pkey)
2455 type = EVP_PKEY_type(pkey->type);
2457 #ifndef OPENSSL_NO_DH
2458 return (type == EVP_PKEY_DH);
2463 #ifndef OPENSSL_NO_DH
2465 dh_pkey_has_public_data(DH *dhkey)
2467 return (!(dhkey->p == NULL) &&
2468 !(dhkey->g == NULL) &&
2469 !(dhkey->pub_key == NULL));
2472 dh_pkey_has_private_data(DH *dhkey)
2474 return (dh_pkey_has_public_data(dhkey) &&
2475 !(dhkey->priv_key == NULL));
2478 DEFUN("ossl-dh-pkey-p", Fossl_dh_pkey_p, 1, 1, 0, /*
2479 Return t iff PKEY is of DH type.
2485 if (!EVPPKEYP(pkey))
2488 pk = (XEVPPKEY(pkey))->evp_pkey;
2496 #endif /* OPENSSL_NO_DH */
2499 /* more general access functions */
2500 DEFUN("ossl-seal", Fossl_seal, 3, 3, 0, /*
2501 Return an envelope derived from encrypting STRING by CIPHER under PKEY
2502 with the hybrid technique.
2504 That is, create a random key/iv pair for the symmetric encryption with
2505 CIPHER and encrypt that key/iv asymmetrically with the provided public
2508 The envelope returned is a list
2509 \(encrypted_string encrypted_key encrypted_iv\)
2511 `encrypted_string' is the (symmetrically) encrypted message
2512 `encrypted_key' is the (asymmetrically) encrypted random key
2513 `encrypted_iv' is the (asymmetrically) encrypted random iv
2515 Note: You probably want to put a wrapping encoder function
2516 (like `base16-encode-string') around it, since this function
2517 returns binary string data.
2519 (cipher, string, pkey))
2521 /* declarations for the cipher */
2522 const EVP_CIPHER *ciph;
2523 EVP_CIPHER_CTX ciphctx;
2524 /* declarations for the pkey */
2527 unsigned char *ekey;
2530 /* buffer for the generated IV */
2531 char iv[EVP_MAX_IV_LENGTH];
2533 /* buffer for output */
2534 unsigned char *outbuf;
2535 unsigned int outlen;
2536 Lisp_Object l_outbuf;
2537 /* buffer for external string data */
2544 CHECK_SYMBOL(cipher);
2545 CHECK_STRING(string);
2546 CHECK_EVPPKEY(pkey);
2549 pk[0] = (XEVPPKEY(pkey))->evp_pkey;
2550 if (!ossl_pkey_has_public_data(pk[0])) {
2551 error ("cannot seal, key has no public key data");
2555 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2556 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2557 string_len = OSSL_STRING_LENGTH(string);
2559 OpenSSL_add_all_algorithms();
2560 ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2564 error ("no such cipher");
2568 /* alloc ekey buffer */
2569 ekey = (unsigned char*)xmalloc_atomic(EVP_PKEY_size(pk[0]));
2571 /* now allocate some output buffer externally
2572 * this one has to be at least EVP_CIPHER_block_size bigger
2573 * since block algorithms merely operate blockwise
2575 outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string) +
2576 EVP_CIPHER_block_size(ciph));
2578 EVP_CIPHER_CTX_init(&ciphctx);
2579 if (!(EVP_SealInit(&ciphctx, ciph,
2581 (unsigned char *)&iv,
2582 (EVP_PKEY **)&pk, npubk)==npubk)) {
2586 error ("error in SealInit");
2589 if (!EVP_SealUpdate(&ciphctx, outbuf, (int *)&outlen,
2590 (unsigned char*)string_ext, string_len)) {
2594 error ("error in SealUpdate");
2597 if (!EVP_SealFinal(&ciphctx, (unsigned char*)outbuf+outlen, &tmplen)) {
2601 error ("error in SealFinal");
2604 /* added probable padding space to the length of the output buffer */
2606 EVP_CIPHER_CTX_cleanup(&ciphctx);
2608 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2609 l_ekey = make_ext_string((char *)ekey, ekey_len, OSSL_CODING);
2610 l_iv = make_ext_string(iv,EVP_CIPHER_iv_length(ciph), OSSL_CODING);
2615 return list3(l_outbuf, l_ekey, l_iv);
2619 DEFUN("ossl-open", Fossl_open, 4, 5, 0, /*
2620 Return the deciphered message STRING from an envelope
2621 obtained by `ossl-seal'.
2623 CIPHER is the cipher to use (the same as in `ossl-seal')
2624 STRING is the encrypted message
2625 PKEY is the private key
2626 EKEY is the encrypted random key
2627 EIV is the encrypted iv
2629 (cipher, string, pkey, ekey, eiv))
2631 /* declarations for the cipher */
2632 const EVP_CIPHER *ciph;
2633 EVP_CIPHER_CTX ciphctx;
2634 /* declarations for the pkey */
2636 /* buffer for external ekey data */
2639 /* buffer for external eiv data */
2641 /* buffer for output */
2642 unsigned char *outbuf;
2643 unsigned int outlen;
2644 Lisp_Object l_outbuf;
2645 /* buffer for external string data */
2652 CHECK_SYMBOL(cipher);
2653 CHECK_STRING(string);
2654 CHECK_EVPPKEY(pkey);
2658 pk = (XEVPPKEY(pkey))->evp_pkey;
2659 if (!ossl_pkey_has_private_data(pk))
2660 error ("cannot open, key has no private key data");
2662 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2663 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2664 string_len = OSSL_STRING_LENGTH(string);
2665 TO_EXTERNAL_FORMAT (LISP_STRING, ekey,
2666 C_STRING_ALLOCA, ekey_ext, OSSL_CODING);
2667 ekey_len = OSSL_STRING_LENGTH(ekey);
2669 OpenSSL_add_all_algorithms();
2670 ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2674 error ("no such cipher");
2682 TO_EXTERNAL_FORMAT (LISP_STRING, eiv,
2683 C_STRING_ALLOCA, eiv_ext, OSSL_CODING);
2686 /* now allocate some output buffer externally */
2687 outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string));
2689 EVP_CIPHER_CTX_init(&ciphctx);
2690 if (!EVP_OpenInit(&ciphctx, ciph,
2691 (unsigned char*)ekey_ext,
2692 (unsigned int)ekey_len,
2693 (unsigned char*)eiv_ext, pk)) {
2696 error ("error in OpenInit");
2699 if (!EVP_OpenUpdate(&ciphctx, outbuf, (int *)&outlen,
2700 (unsigned char*)string_ext,
2701 (unsigned int)string_len)) {
2704 error ("error in OpenUpdate");
2707 if (!EVP_OpenFinal(&ciphctx, outbuf+outlen, &tmplen)) {
2710 error ("error in OpenFinal");
2713 /* added probable padding space to the length of the output buffer */
2715 EVP_CIPHER_CTX_cleanup(&ciphctx);
2717 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2726 DEFUN("ossl-sign", Fossl_sign, 3, 3, 0, /*
2727 Return a signature obtained by signing STRING under DIGEST with PKEY.
2729 That is, hash the message STRING with the message digest DIGEST and
2730 encrypt the result with the private key PKEY.
2732 Note: Due to some relationship between the public key system and the
2733 message digest you cannot use every digest algorithm with every
2735 The most certain results will be achieved using
2736 RSA keys with RSA-* digests, DSA keys with DSA-* digests.
2738 See `ossl-available-digests'.
2740 Note: You probably want to put a wrapping encoder function
2741 (like `base16-encode-string') around it, since this returns
2744 (digest, string, pkey))
2746 /* declarations for the cipher */
2749 /* declarations for the pkey */
2751 /* buffer for output */
2752 unsigned char *outbuf;
2753 unsigned int outlen;
2754 Lisp_Object l_outbuf;
2755 /* buffer for external string data */
2760 CHECK_SYMBOL(digest);
2761 CHECK_STRING(string);
2762 CHECK_EVPPKEY(pkey);
2765 pk = (XEVPPKEY(pkey))->evp_pkey;
2766 if (!ossl_pkey_has_private_data(pk)) {
2767 error ("cannot sign, key has no private key data");
2770 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2771 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2772 string_len = OSSL_STRING_LENGTH(string);
2774 OpenSSL_add_all_algorithms();
2775 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2779 error ("no such digest");
2783 /* now allocate some output buffer externally */
2784 outbuf = (unsigned char *)xmalloc_atomic(EVP_PKEY_size(pk));
2786 EVP_MD_CTX_init(&mdctx);
2787 if (!(EVP_SignInit(&mdctx, md))) {
2790 error ("error in SignInit");
2793 if (!EVP_SignUpdate(&mdctx, string_ext, string_len)) {
2796 error ("error in SignUpdate");
2799 if (!EVP_SignFinal(&mdctx, outbuf, &outlen, pk)) {
2802 error ("error in SignFinal");
2805 EVP_MD_CTX_cleanup(&mdctx);
2807 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2815 DEFUN("ossl-verify", Fossl_verify, 4, 4, 0, /*
2816 Return t iff SIG is a valid signature of STRING under DIGEST obtained by PKEY.
2818 That is, hash the message STRING with the message digest DIGEST, then
2819 decrypt the signature SIG with the public key PKEY.
2820 Compare the results and return t iff both hashes are equal.
2822 DIGEST is the digest to use (the same as in `ossl-sign')
2823 STRING is the message
2824 SIG is the signature of message
2825 PKEY is the public key
2827 (digest, string, sig, pkey))
2829 /* declarations for the cipher */
2832 /* declarations for the pkey */
2834 /* buffer for external signature data */
2837 /* buffer for external string data */
2844 CHECK_SYMBOL(digest);
2845 CHECK_STRING(string);
2847 CHECK_EVPPKEY(pkey);
2850 pk = (XEVPPKEY(pkey))->evp_pkey;
2851 if (!ossl_pkey_has_public_data(pk))
2852 error ("cannot verify, key has no public key data");
2854 OpenSSL_add_all_algorithms();
2855 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2859 error ("no such digest");
2863 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2864 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2865 string_len = OSSL_STRING_LENGTH(string);
2866 TO_EXTERNAL_FORMAT (LISP_STRING, sig,
2867 C_STRING_ALLOCA, sig_ext, OSSL_CODING);
2868 sig_len = OSSL_STRING_LENGTH(sig);
2870 EVP_MD_CTX_init(&mdctx);
2871 if (!EVP_VerifyInit(&mdctx, md)) {
2873 error ("error in VerifyInit");
2876 if (!EVP_VerifyUpdate(&mdctx, string_ext, string_len)) {
2878 error ("error in VerifyUpdate");
2881 result = EVP_VerifyFinal(&mdctx, (unsigned char*)sig_ext, sig_len, pk);
2884 error ("error in VerifyFinal");
2887 EVP_MD_CTX_cleanup(&mdctx);
2891 return result ? Qt : Qnil;
2900 DEFUN("ossl-pem-read-public-key", Fossl_pem_read_public_key, 1, 1, 0, /*
2901 Return a key (the public part) stored in a PEM structure from FILE.
2905 /* declarations for the pkey */
2914 file = Fexpand_file_name(file, Qnil);
2916 if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2917 error ("error opening file.");
2919 pk509 = PEM_read_X509(fp, NULL, NULL, NULL);
2920 pk = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
2924 return make_evp_pkey(pk, pk509);
2927 DEFUN("ossl-pem-read-key", Fossl_pem_read_key, 1, 2, 0, /*
2928 Return a key stored in a PEM structure from FILE.
2929 If the (private part of the) key is protected with a password
2930 provide (optional) PASSWORD.
2934 /* declarations for the pkey */
2938 /* password pointer */
2943 file = Fexpand_file_name(file, Qnil);
2945 if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2946 error ("error opening file.");
2948 if (NILP(password)) {
2951 CHECK_STRING(password);
2952 pass = (char *)XSTRING_DATA(password);
2955 pk = PEM_read_PrivateKey(fp, NULL, NULL, pass);
2958 /* now maybe it is a public key only */
2959 return Fossl_pem_read_public_key(file);
2962 return make_evp_pkey_pk(pk);
2965 DEFUN("ossl-pem-write-public-key", Fossl_pem_write_public_key, 2, 2, 0, /*
2966 Write PKEY (the public part) in a PEM structure to FILE.
2970 /* declarations for the pkey */
2977 CHECK_EVPPKEY(pkey);
2979 file = Fexpand_file_name(file, Qnil);
2981 pk = XEVPPKEY(pkey)->evp_pkey;
2982 pk509 = XEVPPKEY(pkey)->x509;
2984 if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL)
2985 error ("error opening file.");
2987 if (!PEM_write_PUBKEY(fp, pk)) {
2989 error ("error writing PEM file.");
2997 DEFUN("ossl-pem-write-key", Fossl_pem_write_key, 2, 4, 0, /*
2998 Write PKEY in a PEM structure to FILE. The key itself is
2999 protected by (optional) CIPHER with PASSWORD.
3001 CIPHER can be set to nil and the key will not be encrypted.
3002 PASSWORD is ignored in this case.
3004 (file, pkey, cipher, password))
3006 const EVP_CIPHER *ciph;
3007 /* declarations for the pkey */
3012 /* password pointer */
3016 CHECK_EVPPKEY(pkey);
3018 file = Fexpand_file_name(file, Qnil);
3020 pk = XEVPPKEY(pkey)->evp_pkey;
3021 pk509 = XEVPPKEY(pkey)->x509;
3023 if (!ossl_pkey_has_private_data(pk))
3024 return Fossl_pem_write_public_key(file, pkey);
3026 CHECK_SYMBOL(cipher);
3028 OpenSSL_add_all_algorithms();
3034 ciph = EVP_get_cipherbyname(
3035 (char *)string_data(XSYMBOL(cipher)->name));
3038 error ("no such cipher");
3042 if (NILP(password)) {
3046 CHECK_STRING(password);
3047 pass = (char *)XSTRING_DATA(password);
3050 if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL) {
3052 error ("error opening file.");
3055 if (!PEM_write_PKCS8PrivateKey(fp, pk, ciph, NULL, 0, NULL, pass)) {
3058 error ("error writing PEM file.");
3068 ossl_pem_pkey_cb(BIO *bio, int cmd, const char *argp,
3069 int argi, long argl, long ret)
3072 void *foo = BIO_get_callback_arg(bio);
3074 if (!(key = (Lisp_Object)foo)) {
3078 if (BIO_CB_RETURN & cmd) {
3084 key = concat2(key, make_ext_string(argp, argi, OSSL_CODING));
3085 BIO_set_callback_arg(bio, (void*)key);
3093 DEFUN("ossl-pem-public-key",Fossl_pem_public_key, 1, 1, 0, /*
3094 Return PKEY as PEM encoded string.
3098 /* This function can GC */
3099 /* declarations for the pkey */
3105 struct gcpro gcpro1;
3109 CHECK_EVPPKEY(pkey);
3111 pk = (XEVPPKEY(pkey))->evp_pkey;
3113 if (!(b = BIO_new(BIO_s_null()))) {
3115 error("cannot open memory buffer");
3119 result = build_string("");
3120 BIO_set_callback(b, ossl_pem_pkey_cb);
3121 BIO_set_callback_arg(b, (void*)result);
3123 if (!PEM_write_bio_PUBKEY(b, pk)) {
3127 error ("error creating PEM string");
3132 void *foo = BIO_get_callback_arg(b);
3133 if (!(result = (Lisp_Object)foo)) {
3144 DEFUN("ossl-pem-key",Fossl_pem_key, 1, 3, 0, /*
3145 Return PKEY as PEM encoded string. The key itself is
3146 protected by (optional) CIPHER with PASSWORD.
3148 CIPHER can be set to nil and the key will not be encrypted.
3149 PASSWORD is ignored in this case.
3151 (pkey, cipher, password))
3153 /* This function can GC */
3154 /* declarations for the pkey */
3157 const EVP_CIPHER *ciph;
3161 struct gcpro gcpro1, gcpro2, gcpro3;
3163 GCPRO3(pkey, cipher, password);
3165 CHECK_EVPPKEY(pkey);
3167 pk = (XEVPPKEY(pkey))->evp_pkey;
3169 if (!ossl_pkey_has_private_data(pk)) {
3171 return Fossl_pem_public_key(pkey);
3174 CHECK_SYMBOL(cipher);
3176 OpenSSL_add_all_algorithms();
3182 ciph = EVP_get_cipherbyname(
3183 (char *)string_data(XSYMBOL(cipher)->name));
3187 error ("no such cipher");
3192 if (NILP(password)) {
3196 CHECK_STRING(password);
3197 pass = (char *)XSTRING_DATA(password);
3200 if (!(b = BIO_new(BIO_s_null()))) {
3202 error("cannot open memory buffer");
3206 result = build_string("");
3207 BIO_set_callback(b, ossl_pem_pkey_cb);
3208 BIO_set_callback_arg(b, (void*)result);
3210 if (!PEM_write_bio_PKCS8PrivateKey(b, pk, ciph, NULL, 0, NULL, pass)) {
3214 error ("error creating PEM string");
3219 void *foo = BIO_get_callback_arg(b);
3221 if (!(result = (Lisp_Object)foo)) {
3236 * The SSL support in this API is sorta high level since having
3237 * server hellos, handshakes and stuff like that is not what you want
3241 /* This is an opaque object for storing PKEYs in lisp */
3242 Lisp_Object Qssl_connp;
3245 make_ssl_conn(Lisp_SSL_CONN *ssl_conn)
3247 Lisp_Object lisp_ssl_conn;
3248 XSETSSLCONN(lisp_ssl_conn, ssl_conn);
3249 return lisp_ssl_conn;
3253 mark_ssl_conn(Lisp_Object obj)
3255 mark_object(XSSLCONN(obj)->parent);
3256 mark_object(XSSLCONN(obj)->pipe_instream);
3257 mark_object(XSSLCONN(obj)->pipe_outstream);
3259 mark_object(XSSLCONN(obj)->coding_instream);
3260 mark_object(XSSLCONN(obj)->coding_outstream);
3267 print_ssl_conn(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3272 conn = XSSLCONN(obj)->ssl_conn;
3273 parent = XSSLCONN(obj)->parent;
3275 write_c_string("#<OpenSSL socket layer: ", printcharfun);
3277 write_c_string("dead", printcharfun);
3279 write_c_string(SSL_get_version(conn), printcharfun);
3282 if (PROCESSP(parent)) {
3283 write_c_string(" on top of ", printcharfun);
3284 print_internal(parent, printcharfun, escapeflag);
3286 #endif /* HAVE_SOCKETS */
3288 #ifdef HAVE_POSTGRESQL
3289 if (PGCONNP(parent) &&
3290 PQstatus(XPGCONN(parent)->pgconn) == CONNECTION_OK) {
3291 write_c_string(" on top of ", printcharfun);
3292 print_internal(parent, printcharfun, escapeflag);
3294 #endif /* HAVE_POSTGRESQL */
3295 write_c_string(">", printcharfun);
3299 allocate_ssl_conn(void)
3301 Lisp_SSL_CONN *ssl_conn =
3302 alloc_lcrecord_type(Lisp_SSL_CONN, &lrecord_ssl_conn);
3304 /* the network process stuff */
3305 ssl_conn->parent = Qnil;
3306 ssl_conn->infd = -1;
3307 ssl_conn->outfd = -1;
3309 ssl_conn->connected_p = 0;
3310 ssl_conn->protected_p = 0;
3312 ssl_conn->pipe_instream = Qnil;
3313 ssl_conn->pipe_outstream = Qnil;
3315 ssl_conn->coding_instream = Qnil;
3316 ssl_conn->coding_outstream = Qnil;
3323 finalise_ssl_conn(void *header, int for_disksave)
3325 Lisp_SSL_CONN *ssl_conn = (Lisp_SSL_CONN *) header;
3327 if (!(ssl_conn->ssl_conn == NULL)) {
3328 if (ssl_conn->connected_p)
3329 SSL_shutdown(ssl_conn->ssl_conn);
3330 SSL_free(ssl_conn->ssl_conn);
3331 ssl_conn->ssl_conn = NULL;
3333 if (!(ssl_conn->ssl_ctx == NULL)) {
3334 SSL_CTX_free(ssl_conn->ssl_ctx);
3335 ssl_conn->ssl_ctx = NULL;
3337 ssl_conn->ssl_bio = NULL;
3339 if (PROCESSP(ssl_conn->parent)) {
3340 XPROCESS(ssl_conn->parent)->process_type = PROCESS_TYPE_NETWORK;
3341 XPROCESS(ssl_conn->parent)->process_type_data = Qnil;
3343 /* we leave the process alive, it's not our fault, but
3344 * we nullify its pointer
3346 ssl_conn->parent = Qnil;
3347 ssl_conn->infd = -1;
3348 ssl_conn->outfd = -1;
3350 ssl_conn->connected_p = 0;
3351 ssl_conn->protected_p = 0;
3353 /* free the lstream resources */
3354 #if 0 /* will lead to problems */
3355 if (LSTREAMP(ssl_conn->pipe_instream))
3356 Lstream_delete(XLSTREAM(ssl_conn->pipe_instream));
3357 if (LSTREAMP(ssl_conn->pipe_outstream))
3358 Lstream_delete(XLSTREAM(ssl_conn->pipe_outstream));
3360 ssl_conn->pipe_instream = Qnil;
3361 ssl_conn->pipe_outstream = Qnil;
3363 #if 0 /* will lead to problems */
3364 if (LSTREAMP(ssl_conn->coding_instream))
3365 Lstream_delete(XLSTREAM(ssl_conn->coding_instream));
3366 if (LSTREAMP(ssl_conn->coding_outstream))
3367 Lstream_delete(XLSTREAM(ssl_conn->coding_outstream));
3369 ssl_conn->coding_instream = Qnil;
3370 ssl_conn->coding_outstream = Qnil;
3373 /* avoid some warning */
3377 DEFINE_LRECORD_IMPLEMENTATION("ssl_conn", ssl_conn,
3378 mark_ssl_conn, print_ssl_conn,
3380 NULL, NULL, 0, Lisp_SSL_CONN);
3383 ssl_conn_alive_p(Lisp_SSL_CONN *ssl_conn)
3385 return ssl_conn->connected_p;
3389 get_process_infd(Lisp_Process * p)
3391 Lisp_Object instr, outstr;
3392 get_process_streams(p, &instr, &outstr);
3393 return Lstream_get_fd(XLSTREAM(instr));
3396 get_process_outfd(Lisp_Process * p)
3398 Lisp_Object instr, outstr;
3399 get_process_streams(p, &instr, &outstr);
3400 return Lstream_get_fd(XLSTREAM(outstr));
3404 event_stream_ssl_create_stream_pair(
3406 Lisp_Object *instream, Lisp_Object *outstream, int flags)
3408 *instream = make_ssl_input_stream(conn, flags);
3409 *outstream = make_ssl_output_stream(conn, flags);
3415 init_ssl_io_handles(Lisp_SSL_CONN *s, int flags)
3417 event_stream_ssl_create_stream_pair(
3418 s->ssl_conn, &s->pipe_instream, &s->pipe_outstream, flags);
3421 s->coding_instream = make_decoding_input_stream(
3422 XLSTREAM(s->pipe_instream), Fget_coding_system(
3423 Vcoding_system_for_read));
3424 Lstream_set_character_mode(XLSTREAM(s->coding_instream));
3425 s->coding_outstream = make_encoding_output_stream(
3426 XLSTREAM(s->pipe_outstream), Fget_coding_system(
3427 Vcoding_system_for_write));
3428 #endif /* FILE_CODING */
3431 /* Advanced step-by-step initialisation */
3432 #define OSSL_CHECK_PROCESS(process) \
3434 /* Make sure the process is really alive. */ \
3435 if (!EQ(XPROCESS(process)->status_symbol, Qrun)) \
3436 error("Network stream %s not alive", \
3437 XSTRING_DATA(XPROCESS(process)->name)); \
3438 /* Make sure the process is a network stream. */ \
3439 if (!network_connection_p(process)) \
3440 error("Process %s is not a network stream", \
3441 XSTRING_DATA(XPROCESS(process)->name)); \
3444 #ifdef OSSL_DEBUG_FLAG
3446 ossl_bio_dump_callback(BIO *bio, int cmd, const char *argp,
3447 int argi, long argl, long ret)
3451 out=(BIO *)BIO_get_callback_arg(bio);
3452 if (out == NULL) return(ret);
3454 if (cmd == (BIO_CB_READ|BIO_CB_RETURN))
3456 BIO_printf(out,"read from %p [%p] (%d bytes => %ld (0x%lX))\n",
3457 (void *)bio,argp,argi,ret,ret);
3458 BIO_dump(out,argp,(int)ret);
3461 else if (cmd == (BIO_CB_WRITE|BIO_CB_RETURN))
3463 BIO_printf(out,"write to %p [%p] (%d bytes => %ld (0x%lX))\n",
3464 (void *)bio,argp,argi,ret,ret);
3465 BIO_dump(out,argp,(int)ret);
3472 ossl_ssl_prepare_cmeth(Lisp_Object method)
3474 SSL_METHOD *meth = NULL;
3475 Lisp_SSL_CONN *lisp_ssl_conn;
3477 /* start preparing the conn object */
3479 SSL_load_error_strings();
3482 } else if (EQ(method, Qssl2)) {
3483 #if HAVE_SSLV2_CLIENT_METHOD
3484 meth = (SSL_METHOD *)SSLv2_client_method();
3486 error("sslv2 client method not supported");
3488 } else if (EQ(method, Qssl3)) {
3489 #if HAVE_SSLV3_CLIENT_METHOD
3490 meth = (SSL_METHOD *)SSLv3_client_method();
3492 error("sslv3 client method not supported");
3494 } else if (EQ(method, Qssl23)) {
3495 #if HAVE_SSLV23_CLIENT_METHOD
3496 meth = (SSL_METHOD *)SSLv23_client_method();
3498 error("sslv23 client method not supported");
3500 } else if (EQ(method, Qtls1)) {
3501 #if HAVE_TLSV1_CLIENT_METHOD
3502 meth = (SSL_METHOD *)TLSv1_client_method();
3504 error("tlsv1 client method not supported");
3507 #if HAVE_TLSV1_CLIENT_METHOD
3508 meth = (SSL_METHOD *)TLSv1_client_method();
3510 error("default tlsv1 client method not supported");
3514 error("OSSL: not enough random data");
3516 /* now allocate this stuff, pump it and return */
3517 lisp_ssl_conn = allocate_ssl_conn();
3518 lisp_ssl_conn->ssl_meth = meth;
3519 lisp_ssl_conn->ssl_ctx = NULL;
3520 lisp_ssl_conn->ssl_conn = NULL;
3521 lisp_ssl_conn->ssl_bio = NULL;
3523 return make_ssl_conn(lisp_ssl_conn);
3527 ossl_ssl_prepare_smeth(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();
3537 } else if (EQ(method, Qssl2)) {
3538 #if HAVE_SSLV2_SERVER_METHOD
3539 meth = (SSL_METHOD *)SSLv2_server_method();
3541 error("sslv2 client method not supported");
3543 } else if (EQ(method, Qssl3)) {
3544 #if HAVE_SSLV3_SERVER_METHOD
3545 meth = (SSL_METHOD *)SSLv3_server_method();
3547 error("sslv3 client method not supported");
3549 } else if (EQ(method, Qssl23)) {
3550 #if HAVE_SSLV23_SERVER_METHOD
3551 meth = (SSL_METHOD *)SSLv23_server_method();
3553 error("sslv23 client method not supported");
3555 } else if (EQ(method, Qtls1)) {
3556 #if HAVE_TLSV1_SERVER_METHOD
3557 meth = (SSL_METHOD *)TLSv1_server_method();
3559 error("tlsv1 client method not supported");
3562 #if HAVE_SSLV23_SERVER_METHOD
3563 meth = (SSL_METHOD *)SSLv23_server_method();
3565 error("default sslv23 client method not supported");
3569 error("OSSL: not enough random data");
3571 /* now allocate this stuff, pump it and return */
3572 lisp_ssl_conn = allocate_ssl_conn();
3573 lisp_ssl_conn->ssl_meth = meth;
3574 lisp_ssl_conn->ssl_ctx = NULL;
3575 lisp_ssl_conn->ssl_conn = NULL;
3576 lisp_ssl_conn->ssl_bio = NULL;
3578 return make_ssl_conn(lisp_ssl_conn);
3582 ossl_ssl_prepare_ctx(Lisp_Object ssl_conn)
3584 /* SSL connection stuff */
3585 SSL_CTX *ctx = NULL;
3586 Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3588 ctx = SSL_CTX_new(lisp_ssl_conn->ssl_meth);
3590 error("OSSL: context initialisation failed");
3592 /* OpenSSL contains code to work-around lots of bugs and flaws in
3593 * various SSL-implementations. SSL_CTX_set_options() is used to enabled
3594 * those work-arounds. The man page for this option states that
3595 * SSL_OP_ALL enables all the work-arounds and that "It is usually safe
3596 * to use SSL_OP_ALL to enable the bug workaround options if
3597 * compatibility with somewhat broken implementations is desired."
3599 SSL_CTX_set_options(ctx, SSL_OP_ALL);
3601 lisp_ssl_conn->ssl_ctx = ctx;
3607 ossl_ssl_prepare(Lisp_Object ssl_conn, void(*fun)(SSL*))
3609 /* SSL connection stuff */
3612 #ifdef OSSL_DEBUG_FLAG
3613 BIO *bio_c_out = NULL;
3615 Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3617 /* now initialise a new connection context */
3618 conn = SSL_new(lisp_ssl_conn->ssl_ctx);
3619 if (conn == NULL || fun == NULL)
3620 error("OSSL: connection initialisation failed");
3622 /* always renegotiate */
3623 SSL_set_mode(conn, SSL_MODE_AUTO_RETRY);
3625 /* initialise the main connection BIO */
3626 bio = BIO_new(BIO_s_socket());
3628 #ifdef OSSL_DEBUG_FLAG
3629 /* this is a debug BIO which pukes tons of stuff to stderr */
3630 bio_c_out = BIO_new_fp(stderr, BIO_NOCLOSE);
3631 BIO_set_callback(bio, ossl_bio_dump_callback);
3632 BIO_set_callback_arg(bio, bio_c_out);
3635 /* connect SSL with the bio */
3636 SSL_set_bio(conn, bio, bio);
3637 /* turn into client or server */
3640 /* now allocate this stuff, pump it and return */
3641 lisp_ssl_conn->ssl_conn = conn;
3642 lisp_ssl_conn->ssl_bio = bio;
3644 /* create lstream handles */
3645 init_ssl_io_handles(lisp_ssl_conn, STREAM_NETWORK_CONNECTION);
3650 /* Injection of CA certificates */
3651 int ossl_ssl_inject_ca(Lisp_Object ssl_conn, Lisp_Object cacert)
3657 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3658 cert = XEVPPKEY(cacert)->evp_pkey;
3659 xc509 = XEVPPKEY(cacert)->x509;
3661 if (cert && !xc509) {
3663 X509_set_pubkey(xc509, cert);
3664 XEVPPKEY(cacert)->x509 = xc509;
3669 /* what about coding system issues? */
3670 if (!SSL_CTX_add_client_CA(ctx, xc509))
3676 int ossl_ssl_inject_ca_file(Lisp_Object ssl_conn, Lisp_Object cafile)
3680 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3682 /* what about coding system issues? */
3683 if (!SSL_CTX_load_verify_locations(
3684 ctx, (char*)XSTRING_DATA(cafile), NULL))
3690 int ossl_ssl_inject_ca_path(Lisp_Object ssl_conn, Lisp_Object capath)
3694 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3696 /* what about coding system issues? */
3697 if (!SSL_CTX_load_verify_locations(
3698 ctx, NULL, (char*)XSTRING_DATA(capath)))
3704 int ossl_ssl_inject_cert(Lisp_Object ssl_conn,
3705 Lisp_Object cert, Lisp_Object key)
3712 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3713 pkey = XEVPPKEY(key)->evp_pkey;
3714 xcert = XEVPPKEY(cert)->evp_pkey;
3715 xc509 = XEVPPKEY(cert)->x509;
3717 if (xcert && !xc509) {
3719 X509_set_pubkey(xc509, xcert);
3720 XEVPPKEY(cert)->x509 = xc509;
3725 if (SSL_CTX_use_certificate(ctx, xc509) <= 0)
3728 if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
3730 if (!SSL_CTX_check_private_key(ctx))
3736 int ossl_ssl_inject_cert_file(Lisp_Object ssl_conn,
3737 Lisp_Object cert, Lisp_Object key)
3741 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3743 if (SSL_CTX_use_certificate_file(
3744 ctx, (char*)XSTRING_DATA(cert), SSL_FILETYPE_PEM) <= 0)
3746 if (SSL_CTX_use_PrivateKey_file(
3747 ctx, (char*)XSTRING_DATA(key), SSL_FILETYPE_PEM) <= 0)
3749 if (!SSL_CTX_check_private_key(ctx))
3755 Lisp_Object ossl_ssl_handshake(Lisp_Object ssl_conn, Lisp_Object process)
3757 /* This function can GC */
3758 /* SSL connection stuff */
3761 #if 0 && defined(OSSL_DEBUG_FLAG)
3762 BIO *bio_c_out = NULL;
3764 int ret, err, infd, outfd;
3766 struct gcpro gcpro1, gcpro2;
3768 /* Make sure we have a process, the alive check should be done in the
3769 function calling this here */
3770 CHECK_PROCESS(process);
3772 GCPRO2(ssl_conn, process);
3774 /* set the alternate one */
3775 event_stream_unselect_process(XPROCESS(process));
3778 /* just announce that we are very binary */
3779 Fset_process_coding_system(process, Qbinary, Qbinary);
3782 /* initialise the process' buffer for type-specific data,
3783 * we will store process input there */
3784 XPROCESS(process)->process_type_data = Qnil;
3786 /* retrieve the sockets of the process */
3787 infd = get_process_infd(XPROCESS(process));
3788 outfd = get_process_outfd(XPROCESS(process));
3790 /* push data to ssl_conn */
3791 XSSLCONN(ssl_conn)->parent = process;
3792 XSSLCONN(ssl_conn)->infd = infd;
3793 XSSLCONN(ssl_conn)->outfd = outfd;
3795 /* frob vars from ssl_conn */
3796 conn = XSSLCONN(ssl_conn)->ssl_conn;
3797 bio = XSSLCONN(ssl_conn)->ssl_bio;
3799 /* initialise the main connection BIO */
3800 BIO_set_fd(bio, infd, 0);
3802 /* now perform the actual handshake
3803 * this is a loop because of the genuine openssl concept to not handle
3804 * non-blocking I/O correctly */
3808 ret = SSL_do_handshake(conn);
3809 err = SSL_get_error(conn, ret);
3811 /* perform select() with timeout
3812 * 1 second at the moment */
3816 if (err == SSL_ERROR_NONE) {
3818 } else if (err == SSL_ERROR_WANT_READ) {
3820 OSSL_DEBUG("WANT_READ\n");
3823 FD_SET(infd, &read_fds);
3825 /* wait for socket to be readable */
3826 if (!(ret = select(infd+1, &read_fds, 0, NULL, &to))) {
3828 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3829 error("timeout during handshake");
3832 } else if (err == SSL_ERROR_WANT_WRITE) {
3834 OSSL_DEBUG("WANT_WRITE\n");
3835 FD_ZERO(&write_fds);
3836 FD_SET(outfd, &write_fds);
3838 /* wait for socket to be writable */
3839 if (!(ret = select(infd+1, &write_fds, 0, NULL, &to))) {
3841 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3842 error("timeout during handshake");
3845 } else if (err == SSL_ERROR_SSL) {
3846 /* close down the process object */
3847 Fdelete_process(process);
3850 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3851 error("handshake failed");
3854 OSSL_CRITICAL("\nUnknown error: %d\n"
3856 "sxemacs-devel@sxemacs.org\n\n", err);
3859 /* we used to check whether the connection is
3860 still alive, but this was perhaps a bad idea */
3861 try = BIO_read(bio, buf, 2);
3863 (try < 0 && !BIO_should_retry(bio))) {
3864 /* Handle closed connection */
3865 XPROCESS(process)->exit_code = 256;
3866 XPROCESS(process)->status_symbol = Qexit;
3869 /* close down the process object */
3870 Fdelete_process(process);
3874 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3875 error("unknown handshake error");
3880 /* marry the socket layer now */
3881 ossl_ssl_proselytise_process(ssl_conn, process);
3883 /* declare the whole pig connected */
3884 XSSLCONN(ssl_conn)->connected_p = 1;
3886 event_stream_select_process(XPROCESS(process));
3892 DEFUN("ossl-ssl-inject-cert", Fossl_ssl_inject_cert, 2, 3, 0, /*
3893 Add CERT as the local certificate of SSL-CONN.
3894 Optional argument KEY specifies a key file or evp-pkey, if
3895 CERT does not contain it.
3897 Both, CERT and KEY may be either a filename pointing to a
3898 PEM-encoded certificate and key respectively, or may be an
3901 (ssl_conn, cert, key))
3903 /* This function can GC */
3904 int (*fun)(Lisp_Object, Lisp_Object, Lisp_Object) = NULL;
3905 struct gcpro gcpro1, gcpro2, gcpro3;
3907 GCPRO3(ssl_conn, cert, key);
3909 CHECK_SSLCONN(ssl_conn);
3912 CHECK_EVPPKEY(cert);
3917 /* certificate and key preparation */
3918 if (STRINGP(cert)) {
3919 cert = Fexpand_file_name(cert, Qnil);
3920 if (NILP(Ffile_readable_p(cert)))
3925 key = Fexpand_file_name(key, Qnil);
3926 if (NILP(Ffile_readable_p(key)))
3930 if (STRINGP(cert) && NILP(key))
3932 else if (EVPPKEYP(cert) && NILP(key))
3935 /* certificate and key injection */
3936 if (!NILP(cert) && !NILP(key) &&
3937 STRINGP(cert) && STRINGP(key))
3938 fun = ossl_ssl_inject_cert_file;
3939 else if (!NILP(cert) && !NILP(key) &&
3940 EVPPKEYP(cert) && EVPPKEYP(key))
3941 fun = ossl_ssl_inject_cert;
3943 if (fun && fun(ssl_conn, cert, key)) {
3952 DEFUN("ossl-ssl-inject-ca", Fossl_ssl_inject_ca, 2, 2, 0, /*
3953 Add CA to the pile of certificate authorities of SSL-CONN.
3954 Also force a \(re\)verification of the remote peer certificate
3955 against CA. Return `t' if the injection was successful,
3958 CA may be either a file name pointing to a PEM-encoded
3959 CA certificate, or may be a directory containing a valid
3960 bunch of CA certificates according to OpenSSL's CA path
3961 layout, or may also be an evp-pkey object.
3965 /* This function can GC */
3966 int (*fun)(Lisp_Object, Lisp_Object) = NULL;
3968 struct gcpro gcpro1, gcpro2;
3970 GCPRO2(ssl_conn, ca);
3972 CHECK_SSLCONN(ssl_conn);
3978 ca = Fexpand_file_name(ca, Qnil);
3979 if (NILP(Ffile_readable_p(ca)))
3983 if (!NILP(ca) && STRINGP(ca)) {
3984 if (NILP(Ffile_directory_p(ca)))
3985 fun = ossl_ssl_inject_ca_file;
3987 fun = ossl_ssl_inject_ca_path;
3988 } else if (!NILP(ca) && EVPPKEYP(ca))
3989 fun = ossl_ssl_inject_ca;
3991 if (fun && fun(ssl_conn, ca) &&
3992 (conn = XSSLCONN(ssl_conn)->ssl_conn)) {
3993 #if HAVE_SSL_VERIFY_CERT_CHAIN
3994 ssl_verify_cert_chain(conn, SSL_get_peer_cert_chain(conn));
3996 error("SSL certificate chain verification not supported");
4006 DEFUN("ossl-ssl-handshake", Fossl_ssl_handshake, 1, 6, 0, /*
4007 Perform a handshake on the network connection PROCESS.
4009 Return a ssl-conn object, or `nil' if the handshake failed.
4010 In the latter case, most likely the remote site cannot handle
4011 the specified method, requires a client certificate, or cannot
4014 Optional argument METHOD indicates the SSL connection method,
4015 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
4017 Optional argument CA indicates a CA certificate.
4018 See `ossl-ssl-inject-ca'.
4020 Optional arguments CERT and KEY indicate a peer certificate
4021 and possibly a separate key file respectively.
4022 See `ossl-ssl-inject-peer-cert'.
4024 Optional argument SERVERP indicates whether to perform the
4025 handshake as a server if non-nil, and as a client otherwise.
4026 Note: In case of a handshake as server it is mandatory to provide
4027 a valid certificate and a corresponding key.
4029 (process, method, ca, cert, key, serverp))
4031 /* This function can GC */
4033 Lisp_Object ssl_conn, result;
4035 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
4037 GCPRO6(process, method, ca, cert, key, serverp);
4039 /* Make sure the process is really alive. */
4040 CHECK_PROCESS(process);
4041 OSSL_CHECK_PROCESS(process);
4043 /* create a ssl_conn object first */
4045 ssl_conn = ossl_ssl_prepare_cmeth(method);
4047 ssl_conn = ossl_ssl_prepare_smeth(method);
4049 /* create the context */
4050 ossl_ssl_prepare_ctx(ssl_conn);
4052 /* certificate and key preparation */
4053 Fossl_ssl_inject_cert(ssl_conn, cert, key);
4054 /* certificate authority preparation */
4055 Fossl_ssl_inject_ca(ssl_conn, ca);
4057 /* prepare for handshake */
4059 ossl_ssl_prepare(ssl_conn, SSL_set_connect_state);
4061 ossl_ssl_prepare(ssl_conn, SSL_set_accept_state);
4063 result = ossl_ssl_handshake(ssl_conn, process);
4069 DEFUN("ossl-ssl-connect", Fossl_ssl_connect, 0, MANY, 0, /*
4070 Perform a TLS or SSL handshake, return a ssl-conn object on
4071 success, or `nil' if the handshake failed.
4072 In the latter case, most likely the remote site cannot handle
4073 the specified method, requires a client certificate, or cannot
4084 Optional argument METHOD indicates the SSL connection method,
4085 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
4087 (int nargs, Lisp_Object *args))
4091 for (i = 0; i < nargs; i++);
4097 ossl_swap_process_streams(Lisp_SSL_CONN *s, Lisp_Process *p)
4099 Lisp_Object in, out;
4101 in = p->pipe_instream;
4102 out = p->pipe_outstream;
4104 p->pipe_instream = s->pipe_instream;
4105 p->pipe_outstream = s->pipe_outstream;
4107 s->pipe_instream = in;
4108 s->pipe_outstream = out;
4111 in = p->coding_instream;
4112 out = p->coding_outstream;
4114 p->coding_instream = s->coding_instream;
4115 p->coding_outstream = s->coding_outstream;
4117 s->coding_instream = in;
4118 s->coding_outstream = out;
4123 ossl_ssl_proselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4125 Lisp_Process *p = XPROCESS(process);
4126 Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4128 event_stream_unselect_process(p);
4130 /* put the streams we have in the ssl-conn object into the process
4131 object; actually these swap their places */
4132 if (p->process_type != PROCESS_TYPE_SSL)
4133 ossl_swap_process_streams(s, p);
4135 /* somehow we gotta link the network-process with the ss-layer
4136 * otherwise it'd be easy to open a network stream then
4137 * a ss-layer on top of it and then via `delete-process'
4138 * all the work is void while the ss-layer still exists
4140 p->process_type = PROCESS_TYPE_SSL;
4141 p->process_type_data = ssl_conn;
4143 event_stream_select_process(p);
4149 ossl_ssl_unproselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4151 Lisp_Process *p = XPROCESS(process);
4152 Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4154 /* put the streams we have in the ssl-conn object into the process
4155 object (they should be the former process streams) */
4156 if (p->process_type == PROCESS_TYPE_SSL)
4157 ossl_swap_process_streams(s, p);
4159 /* somehow we gotta link the network-process with the ss-layer
4160 * otherwise it'd be easy to open a network stream then
4161 * a ss-layer on top of it and then via `delete-process'
4162 * all the work is void while the ss-layer still exists
4164 XPROCESS(process)->process_type = PROCESS_TYPE_NETWORK;
4165 XPROCESS(process)->process_type_data = Qnil;
4170 DEFUN("ossl-ssl-proselytise-process", Fossl_ssl_proselytise_process,
4172 Convert the underlying process of SSL-CONN into a secure
4173 network connection object.
4177 Lisp_Object process;
4179 CHECK_SSLCONN(ssl_conn);
4181 process = XSSLCONN(ssl_conn)->parent;
4182 if (!PROCESSP(process)) {
4183 error("no process associated with this connection");
4187 /* Make sure the process is really alive. */
4188 OSSL_CHECK_PROCESS(process);
4190 ossl_ssl_proselytise_process(ssl_conn, process);
4195 DEFUN("ossl-ssl-unproselytise-process", Fossl_ssl_unproselytise_process,
4197 Convert the underlying process of SSL-CONN into an ordinary
4198 network connection object.
4202 Lisp_Object process;
4204 CHECK_SSLCONN(ssl_conn);
4206 process = XSSLCONN(ssl_conn)->parent;
4207 if (!PROCESSP(process)) {
4208 error("no process associated with this connection");
4212 /* Make sure the process is really alive. */
4213 OSSL_CHECK_PROCESS(process);
4215 /* Castrate the process and make it a network process again */
4216 ossl_ssl_unproselytise_process(ssl_conn, process);
4221 DEFUN("ossl-ssl-finish", Fossl_ssl_finish, 1, 1, 0, /*
4222 Finish an SSL connection SSL-CONN.
4224 Note: This may also finish the network connection.
4228 Lisp_Object process;
4230 CHECK_SSLCONN(ssl_conn);
4232 if (XSSLCONN(ssl_conn)->protected_p)
4233 error ("Cannot finish protected SSL connection");
4235 process = XSSLCONN(ssl_conn)->parent;
4236 if (PROCESSP(process))
4237 ossl_ssl_unproselytise_process(ssl_conn, process);
4239 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
4243 DEFUN("ossl-ssl-read", Fossl_ssl_read, 2, 2, 0, /*
4244 Return the cleartext of STRING which is assumed to be a complete
4245 block of data sent through SSL-CONN.
4249 /* network stream stuff */
4251 Lisp_Object process;
4253 Lisp_Object result = Qnil;
4255 CHECK_SSLCONN(ssl_conn);
4256 CHECK_STRING(string);
4258 if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4259 error("SSL connection dead");
4261 conn = XSSLCONN(ssl_conn)->ssl_conn;
4262 process = XSSLCONN(ssl_conn)->parent;
4264 /* Make sure the process is really alive. */
4265 OSSL_CHECK_PROCESS(process);
4270 DEFUN("ossl-ssl-write", Fossl_ssl_write, 2, 2, 0, /*
4271 Send STRING to the tunnel SSL-CONN.
4275 /* network stream stuff */
4277 Lisp_Object process, proc_filter;
4282 CHECK_SSLCONN(ssl_conn);
4283 CHECK_STRING(string);
4285 if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4286 error("SSL connection dead");
4288 conn = XSSLCONN(ssl_conn)->ssl_conn;
4289 process = XSSLCONN(ssl_conn)->parent;
4291 /* Make sure the process is really alive. */
4292 OSSL_CHECK_PROCESS(process);
4294 switch (XPROCESS(process)->process_type) {
4295 case PROCESS_TYPE_NETWORK:
4296 /* ssl streams reside in ssl-conn object atm */
4297 out = XLSTREAM(DATA_OUTSTREAM(XSSLCONN(ssl_conn)));
4299 case PROCESS_TYPE_SSL:
4300 /* ssl streams reside in process object, snarf from there */
4301 out = XLSTREAM(DATA_OUTSTREAM(XPROCESS(process)));
4305 error("unable to write");
4308 /* store the original process filter */
4309 proc_filter = XPROCESS(process)->filter;
4311 ret = Lstream_write(out, XSTRING_DATA(string), XSTRING_LENGTH(string));
4314 switch (SSL_get_error(conn, ret)) {
4315 case SSL_ERROR_NONE:
4317 case SSL_ERROR_WANT_WRITE:
4318 error("Connection wants write");
4319 case SSL_ERROR_WANT_READ:
4320 error("Connection wants read");
4322 error("Severe SSL connection error");
4325 /* restore the original process filter */
4326 return (SSL_pending(conn) == 0) ? Qt : Qnil;
4329 /* convenience functions */
4330 DEFUN("ossl-ssl-parent", Fossl_ssl_parent, 1, 1, 0, /*
4331 Return the underlying parent layer of SSL-CONN.
4335 CHECK_SSLCONN(ssl_conn);
4337 return XSSLCONN(ssl_conn)->parent;
4340 DEFUN("ossl-ssl-cert", Fossl_ssl_cert, 1, 1, 0, /*
4341 Return the local peer's certificate of SSL-CONN if present,
4346 /* SSL connection stuff */
4350 CHECK_SSLCONN(ssl_conn);
4352 conn = XSSLCONN(ssl_conn)->ssl_conn;
4353 cert = SSL_get_certificate(conn);
4356 return make_evp_pkey_x509(cert);
4361 DEFUN("ossl-ssl-peer-cert", Fossl_ssl_peer_cert, 1, 1, 0, /*
4362 Return the remote peer's certificate of SSL-CONN if present,
4367 /* SSL connection stuff */
4371 CHECK_SSLCONN(ssl_conn);
4373 conn = XSSLCONN(ssl_conn)->ssl_conn;
4374 cert = SSL_get_peer_certificate(conn);
4377 return make_evp_pkey_x509(cert);
4382 DEFUN("ossl-ssl-peer-cert-chain", Fossl_ssl_peer_cert_chain, 1, 1, 0, /*
4383 Return the certificate chain of SSL-CONN as a list of
4389 /* SSL connection stuff */
4393 Lisp_Object result = Qnil;
4395 CHECK_SSLCONN(ssl_conn);
4397 conn = XSSLCONN(ssl_conn)->ssl_conn;
4398 sk = SSL_get_peer_cert_chain(conn);
4403 for (i=0; i<sk_X509_num(sk); i++) {
4404 X509 *cert = sk_X509_value(sk, i);
4406 result = Fcons(make_evp_pkey_x509(cert), result);
4413 DEFUN("ossl-ssl-cert-store", Fossl_ssl_cert_store, 1, 1, 0, /*
4414 Return the X509 cert store of SSL-CONN.
4418 X509_STORE *sto = NULL;
4424 #if 0 /* just thoughts */
4425 int SSL_get_verify_mode(const SSL *s);
4426 int SSL_get_verify_depth(const SSL *s);
4429 DEFUN("ossl-ssl-verify-certificate", Fossl_ssl_verify_certificate,
4431 Return a verify code of SSL-CONN.
4433 The result is a cons cell with the numeric verify code in
4434 the car and a verbose string in the cdr.
4439 /* SSL connection stuff */
4442 Lisp_Object result = Qnil;
4444 CHECK_SSLCONN(ssl_conn);
4446 conn = XSSLCONN(ssl_conn)->ssl_conn;
4447 vrc = SSL_get_verify_result(conn);
4451 build_string(X509_verify_cert_error_string(vrc)));
4456 DEFUN("ossl-ssl-cipher-version", Fossl_ssl_cipher_version, 1, 1, 0, /*
4457 Return the protocol version of the tunnel SSL-CONN.
4461 /* SSL connection stuff */
4463 const SSL_CIPHER *ciph;
4464 /* network stream stuff */
4465 Lisp_SSL_CONN *lisp_ssl_conn;
4467 CHECK_SSLCONN(ssl_conn);
4468 lisp_ssl_conn = XSSLCONN(ssl_conn);
4470 conn = lisp_ssl_conn->ssl_conn;
4474 ciph = SSL_get_current_cipher(conn);
4476 if (!(ciph == NULL))
4477 return Fmake_symbol(
4478 build_string(SSL_CIPHER_get_version(ciph)));
4483 DEFUN("ossl-ssl-cipher-name", Fossl_ssl_cipher_name, 1, 1, 0, /*
4484 Return the name of the current cipher used in the tunnel SSL-CONN.
4488 /* SSL connection stuff */
4490 const SSL_CIPHER *ciph;
4491 /* network stream stuff */
4492 Lisp_SSL_CONN *lisp_ssl_conn;
4494 CHECK_SSLCONN(ssl_conn);
4495 lisp_ssl_conn = XSSLCONN(ssl_conn);
4497 conn = lisp_ssl_conn->ssl_conn;
4501 ciph = SSL_get_current_cipher(conn);
4503 if (!(ciph == NULL))
4504 return intern(SSL_CIPHER_get_name(ciph));
4509 DEFUN("ossl-ssl-cipher-names", Fossl_ssl_cipher_names, 1, 1, 0, /*
4510 Return the names of all supported ciphers in the tunnel SSL-CONN.
4515 /* SSL connection stuff */
4517 STACK_OF(SSL_CIPHER) *ciphs;
4518 Lisp_Object result = Qnil;
4520 CHECK_SSLCONN(ssl_conn);
4522 conn = XSSLCONN(ssl_conn)->ssl_conn;
4526 ciphs = SSL_get_ciphers(conn);
4528 for (i=sk_SSL_CIPHER_num(ciphs)-1; i>=0; i--) {
4529 SSL_CIPHER *ciph = sk_SSL_CIPHER_value(ciphs, i);
4531 result = Fcons(intern(SSL_CIPHER_get_name(ciph)), result);
4537 DEFUN("ossl-ssl-cipher-bits", Fossl_ssl_cipher_bits, 1, 1, 0, /*
4538 Return the number of effective bits of the current cipher in SSL-CONN.
4542 /* SSL connection stuff */
4544 const SSL_CIPHER *ciph;
4545 int alg_bits, strength_bits;
4546 /* network stream stuff */
4547 Lisp_SSL_CONN *lisp_ssl_conn;
4549 CHECK_SSLCONN(ssl_conn);
4550 lisp_ssl_conn = XSSLCONN(ssl_conn);
4552 conn = lisp_ssl_conn->ssl_conn;
4556 ciph = SSL_get_current_cipher(conn);
4558 if (!(ciph == NULL)) {
4559 strength_bits = SSL_CIPHER_get_bits(ciph, &alg_bits);
4560 /* what do we want to do with alg_bits? */
4561 return make_int(strength_bits);
4566 DEFUN("ossl-ssl-cipher-description", Fossl_ssl_cipher_description, 1, 1, 0, /*
4567 Return a description of the current cipher used in the tunnel SSL-CONN.
4571 /* SSL connection stuff */
4573 const SSL_CIPHER *ciph;
4574 /* network stream stuff */
4575 Lisp_SSL_CONN *lisp_ssl_conn;
4577 CHECK_SSLCONN(ssl_conn);
4578 lisp_ssl_conn = XSSLCONN(ssl_conn);
4580 conn = lisp_ssl_conn->ssl_conn;
4584 ciph = SSL_get_current_cipher(conn);
4586 if (!(ciph == NULL))
4587 return build_string(SSL_CIPHER_description(ciph, NULL, 0));
4593 /* X509 cert handling */
4594 DEFUN("ossl-x509-subject", Fossl_x509_subject, 1, 1, 0, /*
4595 Return the certificate subject of CERT (an evp-pkey object).
4597 This will return a string in LDAP syntax.
4603 CHECK_EVPPKEY(cert);
4605 pk509 = XEVPPKEY(cert)->x509;
4608 X509_NAME *sub = X509_get_subject_name(pk509);
4609 return build_string(X509_NAME_oneline(sub, NULL, 0));
4614 DEFUN("ossl-x509-issuer", Fossl_x509_issuer, 1, 1, 0, /*
4615 Return the certificate issuer of CERT (an evp-pkey object),
4616 that is the organisation which signed the certificate.
4618 This will return a string in LDAP syntax.
4624 CHECK_EVPPKEY(cert);
4626 pk509 = XEVPPKEY(cert)->x509;
4629 X509_NAME *iss = X509_get_issuer_name(pk509);
4630 return build_string(X509_NAME_oneline(iss, NULL, 0));
4635 DEFUN("ossl-x509-serial", Fossl_x509_serial, 1, 1, 0, /*
4636 Return the certificate serial of CERT (an evp-pkey object).
4642 CHECK_EVPPKEY(cert);
4644 pk509 = XEVPPKEY(cert)->x509;
4647 ASN1_INTEGER *ser = X509_get_serialNumber(pk509);
4648 return make_integer(ASN1_INTEGER_get(ser));
4653 DEFUN("ossl-x509-not-before", Fossl_x509_not_before, 1, 1, 0, /*
4654 Return the certificate valid-not-before time of CERT.
4660 CHECK_EVPPKEY(cert);
4662 pk509 = XEVPPKEY(cert)->x509;
4665 ASN1_TIME *nbf = X509_get_notBefore(pk509);
4666 return build_string((char*)nbf->data);
4671 DEFUN("ossl-x509-not-after", Fossl_x509_not_after, 1, 1, 0, /*
4672 Return the certificate valid-not-after time of CERT.
4678 CHECK_EVPPKEY(cert);
4680 pk509 = XEVPPKEY(cert)->x509;
4683 ASN1_TIME *nbf = X509_get_notAfter(pk509);
4684 return build_string((char*)nbf->data);
4689 DEFUN("ossl-x509-signature-type", Fossl_x509_signature_type, 1, 1, 0, /*
4690 Return the signature type of CERT.
4696 CHECK_EVPPKEY(cert);
4698 pk509 = XEVPPKEY(cert)->x509;
4701 int ty = X509_get_signature_type(pk509);
4702 Lisp_Object result = Qnil;
4706 result = intern("none");
4708 #ifndef OPENSSL_NO_RSA
4710 result = intern("rsa");
4713 result = intern("rsa2");
4716 #ifndef OPENSSL_NO_DSA
4718 result = intern("dsa");
4721 result = intern("dsa1");
4724 result = intern("dsa2");
4727 result = intern("dsa3");
4730 result = intern("dsa4");
4733 #ifndef OPENSSL_NO_DH
4735 result = intern("dh");
4738 #ifndef OPENSSL_NO_EC
4740 result = intern("ec");
4744 result = intern("unknown");
4759 * Initialisation stuff
4762 void syms_of_openssl(void)
4764 INIT_LRECORD_IMPLEMENTATION(evp_pkey);
4765 INIT_LRECORD_IMPLEMENTATION(ssl_conn);
4767 defsymbol(&Qopenssl, "openssl");
4768 defsymbol(&Qevp_pkeyp, "ossl-pkey-p");
4770 DEFSUBR(Fossl_version);
4771 DEFSUBR(Fossl_available_digests);
4772 DEFSUBR(Fossl_available_ciphers);
4773 DEFSUBR(Fossl_digest_size);
4774 DEFSUBR(Fossl_digest_bits);
4775 DEFSUBR(Fossl_digest_block_size);
4776 DEFSUBR(Fossl_cipher_key_length);
4777 DEFSUBR(Fossl_cipher_bits);
4778 DEFSUBR(Fossl_cipher_iv_length);
4779 DEFSUBR(Fossl_cipher_block_size);
4780 DEFSUBR(Fossl_cipher_mode);
4782 DEFSUBR(Fossl_rand_bytes);
4783 DEFSUBR(Fossl_rand_bytes_egd);
4785 DEFSUBR(Fossl_digest);
4786 DEFSUBR(Fossl_digest_file);
4788 DEFSUBR(Fossl_hmac);
4789 DEFSUBR(Fossl_hmac_file);
4791 DEFSUBR(Fossl_bytes_to_key);
4792 DEFSUBR(Fossl_encrypt);
4793 DEFSUBR(Fossl_encrypt_file);
4794 DEFSUBR(Fossl_decrypt);
4795 DEFSUBR(Fossl_decrypt_file);
4798 DEFSUBR(Fossl_pkey_p);
4799 DEFSUBR(Fossl_pkey_size);
4800 DEFSUBR(Fossl_pkey_private_p);
4801 DEFSUBR(Fossl_pkey_get_public);
4803 #ifndef OPENSSL_NO_RSA
4805 DEFSUBR(Fossl_rsa_generate_key);
4806 DEFSUBR(Fossl_rsa_pkey_p);
4807 DEFSUBR(Fossl_rsa_subkey_p);
4808 #endif /* OPENSSL_NO_RSA */
4809 #ifndef OPENSSL_NO_DSA
4811 DEFSUBR(Fossl_dsa_generate_key);
4812 DEFSUBR(Fossl_dsa_pkey_p);
4813 DEFSUBR(Fossl_dsa_subkey_p);
4814 #endif /* OPENSSL_NO_DSA */
4815 #ifndef OPENSSL_NO_EC
4817 DEFSUBR(Fossl_ec_available_curves);
4818 DEFSUBR(Fossl_ec_generate_key);
4819 DEFSUBR(Fossl_ec_pkey_p);
4820 #endif /* OPENSSL_NO_EC */
4821 #ifndef OPENSSL_NO_DH
4823 /* DEFSUBR(Fossl_ec_generate_key); */
4824 DEFSUBR(Fossl_dh_pkey_p);
4826 DEFSUBR(Fossl_seal);
4827 DEFSUBR(Fossl_open);
4829 DEFSUBR(Fossl_sign);
4830 DEFSUBR(Fossl_verify);
4833 DEFSUBR(Fossl_pem_read_public_key);
4834 DEFSUBR(Fossl_pem_read_key);
4835 DEFSUBR(Fossl_pem_write_public_key);
4836 DEFSUBR(Fossl_pem_write_key);
4837 DEFSUBR(Fossl_pem_public_key);
4838 DEFSUBR(Fossl_pem_key);
4841 defsymbol(&Qssl_connp, "ossl-ssl-conn-p");
4842 defsymbol(&Qssl2, "ssl2");
4843 defsymbol(&Qssl23, "ssl23");
4844 defsymbol(&Qssl3, "ssl3");
4845 defsymbol(&Qtls1, "tls1");
4847 DEFSUBR(Fossl_ssl_handshake);
4848 DEFSUBR(Fossl_ssl_inject_ca);
4849 DEFSUBR(Fossl_ssl_inject_cert);
4850 DEFSUBR(Fossl_ssl_proselytise_process);
4851 DEFSUBR(Fossl_ssl_unproselytise_process);
4852 DEFSUBR(Fossl_ssl_connect);
4853 DEFSUBR(Fossl_ssl_finish);
4854 DEFSUBR(Fossl_ssl_read);
4855 DEFSUBR(Fossl_ssl_write);
4856 DEFSUBR(Fossl_ssl_parent);
4857 DEFSUBR(Fossl_ssl_cert);
4858 DEFSUBR(Fossl_ssl_peer_cert);
4859 DEFSUBR(Fossl_ssl_peer_cert_chain);
4860 DEFSUBR(Fossl_ssl_verify_certificate);
4861 DEFSUBR(Fossl_ssl_cipher_version);
4862 DEFSUBR(Fossl_ssl_cipher_name);
4863 DEFSUBR(Fossl_ssl_cipher_names);
4864 DEFSUBR(Fossl_ssl_cipher_bits);
4865 DEFSUBR(Fossl_ssl_cipher_description);
4868 DEFSUBR(Fossl_x509_subject);
4869 DEFSUBR(Fossl_x509_issuer);
4870 DEFSUBR(Fossl_x509_serial);
4871 DEFSUBR(Fossl_x509_not_before);
4872 DEFSUBR(Fossl_x509_not_after);
4873 DEFSUBR(Fossl_x509_signature_type);
4876 void vars_of_openssl(void)
4880 #ifndef OPENSSL_NO_RSA
4881 Fprovide(intern("openssl-rsa"));
4883 #ifndef OPENSSL_NO_DSA
4884 Fprovide(intern("openssl-dsa"));
4886 #ifndef OPENSSL_NO_EC
4887 Fprovide(intern("openssl-ec"));
4889 #ifndef OPENSSL_NO_DH
4890 Fprovide(intern("openssl-dh"));
4893 Fprovide(intern("openssl-ssl"));