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, n;
871 CHECK_SYMBOL(digest);
875 file = Fexpand_file_name(file, Qnil);
877 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
878 (fseek(fp, 0, SEEK_SET)))
879 return wrong_type_argument(Qfile_readable_p, file);
882 OpenSSL_add_all_digests();
883 md = EVP_get_digestbyname(
884 (char *)string_data(XSYMBOL(digest)->name));
888 error ("no such digest");
891 mdctx = xnew(EVP_MD_CTX);
892 EVP_MD_CTX_init(mdctx);
893 md_blocksize = (unsigned int)(EVP_MD_block_size(md) / 8);
895 EVP_DigestInit_ex(mdctx, md, NULL);
897 /* we reuse md_value here for streaming over fp */
899 n = fread(md_value, 1, EVP_MAX_MD_SIZE, fp);
904 error("file corrupted");
907 EVP_DigestUpdate(mdctx, md_value, n);
910 EVP_DigestFinal_ex(mdctx, md_value, &md_len);
911 EVP_MD_CTX_cleanup(mdctx);
917 return make_ext_string((char *)md_value, md_len, OSSL_CODING);
923 * HMAC (aka keyed hashes)
926 DEFUN("ossl-hmac", Fossl_hmac, 3, 3, 0, /*
927 Return the message authentication code of MSG
928 using the hash function DIGEST and the key PASSWORD.
930 Note: You probably want to put a wrapping encoder function
931 \(like `base16-encode-string'\) around it, since this returns
934 (digest, msg, password))
939 /* buffer for the ciphertext */
940 unsigned char outbuf[EVP_MAX_MD_SIZE];
942 /* buffer for external password */
944 unsigned int password_len;
946 /* buffer for external message */
948 unsigned int msg_len;
951 CHECK_SYMBOL(digest);
953 CHECK_STRING(password);
955 OpenSSL_add_all_digests();
956 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
960 error ("no such digest");
963 TO_EXTERNAL_FORMAT (LISP_STRING, password,
964 C_STRING_ALLOCA, password_ext, OSSL_CODING);
965 password_len = OSSL_STRING_LENGTH(password);
967 #if 0 /* i wonder why */
968 TO_EXTERNAL_FORMAT (LISP_STRING, msg,
969 C_STRING_ALLOCA, msg_ext, OSSL_CODING);
970 msg_len = OSSL_STRING_LENGTH(msg);
973 hmacctx = xnew(HMAC_CTX);
974 HMAC_CTX_init(hmacctx);
975 HMAC_Init(hmacctx, password_ext, password_len, md);
976 HMAC_Update(hmacctx, (unsigned char*)XSTRING_DATA(msg),
977 XSTRING_LENGTH(msg));
978 HMAC_Final(hmacctx, outbuf, &outlen);
979 HMAC_CTX_cleanup(hmacctx);
984 return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
987 DEFUN("ossl-hmac-file", Fossl_hmac_file, 3, 3, 0, /*
988 Return the message authentication code of the contents of FILE
989 using the hash function DIGEST and the key PASSWORD.
991 Note: You probably want to put a wrapping encoder function
992 \(like `base16-encode-string'\) around it, since this returns
995 (digest, file, password))
1000 /* buffer for the ciphertext */
1001 unsigned char outbuf[EVP_MAX_MD_SIZE];
1002 unsigned int outlen, n;
1003 /* buffer for external password */
1005 unsigned int password_len;
1009 CHECK_SYMBOL(digest);
1011 CHECK_STRING(password);
1013 file = Fexpand_file_name(file, Qnil);
1015 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1016 (fseek(fp, 0, SEEK_SET)))
1017 return wrong_type_argument(Qfile_readable_p, file);
1020 OpenSSL_add_all_digests();
1021 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
1025 error ("no such digest");
1028 TO_EXTERNAL_FORMAT (LISP_STRING, password,
1029 C_STRING_ALLOCA, password_ext, OSSL_CODING);
1030 password_len = OSSL_STRING_LENGTH(password);
1032 hmacctx = xnew(HMAC_CTX);
1033 HMAC_CTX_init(hmacctx);
1034 HMAC_Init(hmacctx, password_ext, password_len, md);
1036 /* we reuse md_value here for streaming over fp */
1038 n = fread(outbuf, 1, EVP_MAX_MD_SIZE, fp);
1043 error("file corrupted");
1046 HMAC_Update(hmacctx, outbuf, n);
1049 HMAC_Final(hmacctx, outbuf, &outlen);
1050 HMAC_CTX_cleanup(hmacctx);
1055 return make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1064 DEFUN("ossl-bytes-to-key", Fossl_bytes_to_key, 5, 5, 0, /*
1065 Derive a key and initialisation vector (iv) suitable for a cipher.
1066 Return a string KEY being the key. The initialisation vector is
1067 put into KEY's property list as 'iv.
1069 CIPHER \(a symbol\) is the cipher to derive the key and IV for.
1070 Valid ciphers can be obtained by `ossl-available-ciphers'.
1072 DIGEST \(a symbol\) is the message digest to use.
1073 Valid digests can be obtained by `ossl-available-digests'.
1075 SALT \(string or `nil'\) is used as a salt in the derivation.
1076 Use `nil' here to indicate that no salt is used.
1078 PASSWORD is an arbitrary string which is processed to derive a
1081 COUNT \(a positive integer\) is the iteration count to use. This
1082 indicates how often the hash algorithm is called recursively.
1084 Note: You probably want to put a wrapping encoder function
1085 \(like `base16-encode-string'\) around it, since this returns
1088 (cipher, digest, salt, password, count))
1091 const EVP_CIPHER *ciph;
1092 const char *salt_ext;
1095 unsigned int password_len;
1097 char key[EVP_MAX_KEY_LENGTH];
1098 char iv[EVP_MAX_IV_LENGTH];
1102 CHECK_STRING(password);
1103 CHECK_SYMBOL(cipher);
1104 CHECK_SYMBOL(digest);
1105 CHECK_NATNUM(count);
1109 error ("count has to be a non-zero positive integer");
1111 OpenSSL_add_all_algorithms();
1112 md = EVP_get_digestbyname(
1113 (char *)string_data(XSYMBOL(digest)->name));
1114 ciph = EVP_get_cipherbyname(
1115 (char *)string_data(XSYMBOL(cipher)->name));
1119 error ("no such cipher");
1124 error ("no such digest");
1131 TO_EXTERNAL_FORMAT (LISP_STRING, salt,
1132 C_STRING_ALLOCA, salt_ext, OSSL_CODING);
1136 TO_EXTERNAL_FORMAT (LISP_STRING, password,
1137 C_STRING_ALLOCA, password_ext, OSSL_CODING);
1138 password_len = OSSL_STRING_LENGTH(password);
1140 EVP_BytesToKey(ciph, md, (const unsigned char *)salt_ext,
1141 (const unsigned char *)password_ext, password_len,
1143 (unsigned char *)key,
1144 (unsigned char *)iv);
1148 result = make_ext_string(key, EVP_CIPHER_key_length(ciph), OSSL_CODING);
1149 Fput(result, intern("iv"),
1150 make_ext_string(iv, EVP_CIPHER_iv_length(ciph), OSSL_CODING));
1156 DEFUN("ossl-encrypt", Fossl_encrypt, 3, 4, 0, /*
1157 Return the cipher of STRING computed by CIPHER under KEY.
1159 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1160 you have compiled. See `ossl-available-ciphers'.
1162 STRING is the text to be encrypted.
1164 KEY should be a key generated suitably for this cipher, for example
1165 by `ossl-bytes-to-key'.
1167 Optional fourth argument IV should be an initialisation vector
1168 suitable for this cipher. Normally the initialisation vector from
1169 KEY's property list is used. However, if IV is
1170 non-nil, use this IV instead.
1172 Note: You probably want to put a wrapping encoder function
1173 \(like `base16-encode-string'\) around it, since this returns
1176 (cipher, string, key, iv))
1178 /* buffer for the external string */
1180 unsigned int string_len;
1181 /* buffer for the ciphertext */
1184 Lisp_Object l_outbuf;
1185 /* buffer for key */
1190 /* declarations for the cipher */
1191 const EVP_CIPHER *ciph;
1192 EVP_CIPHER_CTX *ciphctx;
1195 int speccount = specpdl_depth();
1198 /* frob the IV from the plist of key maybe */
1200 iv = Fget(key, intern("iv"), Qnil);
1202 CHECK_SYMBOL(cipher);
1203 CHECK_STRING(string);
1207 TO_EXTERNAL_FORMAT(LISP_STRING, string,
1208 C_STRING_ALLOCA, string_ext, OSSL_CODING);
1209 string_len = OSSL_STRING_LENGTH(string);
1211 if (string_len <= 0)
1212 error ("string must be of non-zero positive length.");
1214 OpenSSL_add_all_algorithms();
1215 /* ENGINE_load_builtin_engines(); */
1216 /* atm, no support for different engines */
1217 ciph = EVP_get_cipherbyname(
1218 (char *)string_data(XSYMBOL(cipher)->name));
1222 error ("no such cipher");
1225 /* now allocate some output buffer externally
1226 * this one has to be at least EVP_CIPHER_block_size bigger
1227 * since block algorithms merely operate blockwise
1229 alloclen = XSTRING_LENGTH(string) + EVP_CIPHER_block_size(ciph);
1230 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
1232 TO_EXTERNAL_FORMAT(LISP_STRING, key,
1233 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1234 TO_EXTERNAL_FORMAT(LISP_STRING, iv,
1235 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1237 ciphctx = xnew(EVP_CIPHER_CTX);
1238 EVP_CIPHER_CTX_init(ciphctx);
1239 if (!EVP_EncryptInit(ciphctx, ciph,
1240 (unsigned char *)key_ext,
1241 (unsigned char *)iv_ext)) {
1244 error ("error in EncryptInit");
1246 if (!EVP_EncryptUpdate(ciphctx,
1247 (unsigned char *)outbuf, &outlen,
1248 (unsigned char *)string_ext, string_len)) {
1251 error ("error in EncryptUpdate");
1253 /* Buffer passed to EVP_EncryptFinal() must be after data just
1254 * encrypted to avoid overwriting it.
1256 if (!EVP_EncryptFinal(ciphctx,
1257 (unsigned char *)outbuf+outlen, &tmplen)) {
1260 error ("error in EncryptFinal");
1262 /* added probable padding space to the length of the output buffer */
1264 EVP_CIPHER_CTX_cleanup(ciphctx);
1266 l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1267 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1275 DEFUN("ossl-encrypt-file", Fossl_encrypt_file, 3, 5, 0, /*
1276 Return the encrypted contents of FILE computed by CIPHER under KEY.
1278 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1279 you have compiled. See `ossl-available-ciphers'.
1281 FILE is the file to be encrypted.
1283 Third argument KEY should be a key generated suitably for this
1284 cipher, for example by `ossl-bytes-to-key'.
1286 Optional fourth argument IV should be an initialisation vector
1287 suitable for this cipher. Normally the initialisation vector from
1288 KEY's property list is used. However, if IV is
1289 non-nil, use this IV instead.
1291 Optional fifth argument OUTFILE may specify a file to have the
1292 encrypted data redirected.
1294 Note: You probably want to put a wrapping encoder function
1295 \(like `base16-encode-string'\) around it, since this returns
1298 (cipher, file, key, iv, outfile))
1300 /* buffer for the external string */
1301 unsigned char string_in[1024];
1302 unsigned int string_len;
1303 unsigned int block_len;
1304 unsigned long file_size;
1305 /* buffer for the ciphertext */
1306 unsigned char *outbuf;
1309 Lisp_Object l_outbuf;
1310 /* buffer for key */
1320 /* declarations for the cipher */
1321 const EVP_CIPHER *ciph;
1322 EVP_CIPHER_CTX *ciphctx;
1325 int speccount = specpdl_depth();
1328 /* frob the IV from the plist of key maybe */
1330 iv = Fget(key, intern("iv"), Qnil);
1332 CHECK_SYMBOL(cipher);
1337 if (!NILP(outfile)) {
1338 CHECK_STRING(outfile);
1339 outfile = Fexpand_file_name(outfile, Qnil);
1340 if ((of = fopen((char *)XSTRING_DATA(outfile),"wb")) == NULL)
1341 return wrong_type_argument(Qfile_writable_p, outfile);
1346 file = Fexpand_file_name(file, Qnil);
1347 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1348 (fseek(fp, 0, SEEK_SET)))
1349 return wrong_type_argument(Qfile_readable_p, file);
1351 fseek(fp, 0, SEEK_END);
1352 file_size = ftell(fp);
1353 fseek(fp, 0, SEEK_SET);
1356 OpenSSL_add_all_algorithms();
1357 /* ENGINE_load_builtin_engines(); */
1358 /* atm, no support for different engines */
1359 ciph = EVP_get_cipherbyname(
1360 (char *)string_data(XSYMBOL(cipher)->name));
1364 error ("no such cipher");
1367 /* now allocate some output buffer externally
1368 * this one has to be at least EVP_CIPHER_block_size bigger
1369 * since block algorithms merely operate blockwise
1371 block_len = EVP_CIPHER_block_size(ciph);
1372 if (UNLIKELY(of != NULL)) {
1375 alloclen = file_size + block_len;
1377 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
1379 TO_EXTERNAL_FORMAT(LISP_STRING, key,
1380 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1381 TO_EXTERNAL_FORMAT(LISP_STRING, iv,
1382 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1384 ciphctx = xnew(EVP_CIPHER_CTX);
1385 EVP_CIPHER_CTX_init(ciphctx);
1386 if (!EVP_EncryptInit(ciphctx, ciph,
1387 (unsigned char *)key_ext,
1388 (unsigned char *)iv_ext)) {
1391 error("error in EncryptInit");
1397 string_len = fread(string_in, 1, 1024, fp);
1398 if (string_len < 0) {
1402 error("file corrupted");
1407 if (string_len > 0 &&
1408 !EVP_EncryptUpdate(ciphctx,
1410 string_in, string_len)) {
1413 error("error in EncryptUpdate");
1417 fwrite(obp, 1, tmplen, of);
1422 } while (string_len > 0);
1424 /* Buffer passed to EVP_EncryptFinal() must be after data just
1425 * encrypted to avoid overwriting it.
1427 if (!EVP_EncryptFinal(ciphctx, obp, &tmplen)) {
1430 error("error in EncryptFinal");
1434 fwrite(obp, 1, tmplen, of);
1436 /* added probable padding space to the length of the output buffer */
1438 EVP_CIPHER_CTX_cleanup(ciphctx);
1440 if (UNLIKELY(of != NULL)) {
1443 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1445 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1456 (setq k (ossl-bytes-to-key 'AES-256-OFB 'SHA1 nil "password" 1))
1457 (ossl-encrypt-file 'AES-256-OFB "~/.gnus" k nil "/tmp/gnus-enc")
1458 (ossl-decrypt-file 'AES-256-OFB "/tmp/gnus-enc" k nil "/tmp/gnus-dec")
1462 DEFUN("ossl-decrypt", Fossl_decrypt, 3, 4, 0, /*
1463 Return the deciphered version of STRING computed by CIPHER under KEY.
1465 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1466 you have compiled. See `ossl-available-ciphers'.
1468 STRING is the text to be decrypted.
1470 KEY should be a key generated suitably for this
1471 cipher, for example by `ossl-bytes-to-key'.
1473 Optional fourth argument IV should be an initialisation vector
1474 suitable for this cipher. Normally the initialisation vector from
1475 KEY's property list is used. However, if IV is
1476 non-nil, use this IV instead.
1478 (cipher, string, key, iv))
1480 /* buffer for the external string */
1482 unsigned int string_len;
1483 /* buffer for the deciphered text */
1486 Lisp_Object l_outbuf;
1487 /* buffer for key */
1492 /* declarations for the decipher */
1493 const EVP_CIPHER *ciph;
1494 EVP_CIPHER_CTX *ciphctx;
1497 int speccount = specpdl_depth();
1500 /* frob the IV from the plist of key maybe */
1502 iv = Fget(key, intern("iv"), Qnil);
1504 CHECK_SYMBOL(cipher);
1505 CHECK_STRING(string);
1509 TO_EXTERNAL_FORMAT(LISP_STRING, string,
1510 C_STRING_ALLOCA, string_ext, OSSL_CODING);
1511 string_len = OSSL_STRING_LENGTH(string);
1514 error ("string must be of non-zero positive length.");
1516 OpenSSL_add_all_algorithms();
1517 /* ENGINE_load_builtin_engines(); */
1518 /* atm, no support for different engines */
1519 ciph = EVP_get_cipherbyname(
1520 (char *)string_data(XSYMBOL(cipher)->name));
1524 error ("no such cipher");
1527 /* now allocate some output buffer externally */
1528 alloclen = XSTRING_LENGTH(string);
1529 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, char);
1531 TO_EXTERNAL_FORMAT (LISP_STRING, key,
1532 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1533 TO_EXTERNAL_FORMAT (LISP_STRING, iv,
1534 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1536 ciphctx = xnew(EVP_CIPHER_CTX);
1537 EVP_CIPHER_CTX_init(ciphctx);
1538 if (!EVP_DecryptInit(ciphctx, ciph,
1539 (unsigned char *)key_ext,
1540 (unsigned char *)iv_ext)) {
1543 error ("error in DecryptInit");
1545 if (!EVP_DecryptUpdate(ciphctx,
1546 (unsigned char *)outbuf, &outlen,
1547 (unsigned char *)string_ext,string_len)) {
1550 error ("error in DecryptUpdate");
1552 /* Buffer passed to EVP_EncryptFinal() must be after data just
1553 * encrypted to avoid overwriting it.
1555 if (!EVP_DecryptFinal(ciphctx,
1556 (unsigned char *)outbuf+outlen, &tmplen)) {
1559 error ("error in DecryptFinal");
1561 /* added probable padding space to the length of the output buffer */
1563 EVP_CIPHER_CTX_cleanup(ciphctx);
1565 l_outbuf = make_ext_string(outbuf, outlen, OSSL_CODING);
1566 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1574 DEFUN("ossl-decrypt-file", Fossl_decrypt_file, 3, 5, 0, /*
1575 Return the deciphered version of FILE computed by CIPHER under KEY.
1577 CIPHER \(a symbol\) may be one of the OpenSSL cipher algorithms
1578 you have compiled. See `ossl-available-ciphers'.
1580 FILE is the file to be decrypted.
1582 Third argument KEY should be a key generated suitably for this
1583 cipher, for example by `ossl-bytes-to-key'.
1585 Optional fourth argument IV should be an initialisation vector
1586 suitable for this cipher. Normally the initialisation vector from
1587 KEY's property list is used. However, if IV is
1588 non-nil, use this IV instead.
1590 Optional fifth argument OUTFILE may specify a file to have the
1591 encrypted data redirected.
1593 (cipher, file, key, iv, outfile))
1595 /* buffer for the external string */
1596 unsigned char string_in[1024];
1597 unsigned int string_len;
1598 unsigned int block_len;
1599 unsigned long file_size;
1600 /* buffer for the deciphered text */
1601 unsigned char *outbuf;
1604 Lisp_Object l_outbuf;
1605 /* buffer for key */
1615 /* declarations for the decipher */
1616 const EVP_CIPHER *ciph;
1617 EVP_CIPHER_CTX *ciphctx;
1620 int speccount = specpdl_depth();
1623 /* frob the IV from the plist of key maybe */
1625 iv = Fget(key, intern("iv"), Qnil);
1627 CHECK_SYMBOL(cipher);
1632 if (!NILP(outfile)) {
1633 CHECK_STRING(outfile);
1634 outfile = Fexpand_file_name(outfile, Qnil);
1635 if ((of = fopen((char *)XSTRING_DATA(outfile),"wb")) == NULL)
1636 return wrong_type_argument(Qfile_writable_p, outfile);
1641 file = Fexpand_file_name(file, Qnil);
1642 if (((fp = fopen((char *)XSTRING_DATA(file),"rb")) == NULL) ||
1643 (fseek(fp, 0, SEEK_SET)))
1644 return wrong_type_argument(Qfile_readable_p, file);
1646 fseek(fp, 0, SEEK_END);
1647 file_size = ftell(fp);
1648 fseek(fp, 0, SEEK_SET);
1651 OpenSSL_add_all_algorithms();
1652 /* ENGINE_load_builtin_engines(); */
1653 /* atm, no support for different engines */
1654 ciph = EVP_get_cipherbyname(
1655 (char *)string_data(XSYMBOL(cipher)->name));
1659 error ("no such cipher");
1662 /* now allocate some output buffer externally */
1663 block_len = EVP_CIPHER_block_size(ciph);
1664 if (UNLIKELY(of != NULL)) {
1667 alloclen = file_size + block_len;
1669 XMALLOC_ATOMIC_OR_ALLOCA(outbuf, alloclen, unsigned char);
1671 TO_EXTERNAL_FORMAT (LISP_STRING, key,
1672 C_STRING_ALLOCA, key_ext, OSSL_CODING);
1673 TO_EXTERNAL_FORMAT (LISP_STRING, iv,
1674 C_STRING_ALLOCA, iv_ext, OSSL_CODING);
1676 ciphctx = xnew(EVP_CIPHER_CTX);
1677 EVP_CIPHER_CTX_init(ciphctx);
1678 if (!EVP_DecryptInit(ciphctx, ciph,
1679 (unsigned char *)key_ext,
1680 (unsigned char *)iv_ext)) {
1683 error ("error in DecryptInit");
1689 string_len = fread(string_in, 1, 1024, fp);
1690 if (string_len < 0) {
1694 error("file corrupted");
1699 if (string_len > 0 &&
1700 !EVP_DecryptUpdate(ciphctx,
1702 string_in, string_len)) {
1705 error ("error in DecryptUpdate");
1709 fwrite(obp, 1, tmplen, of);
1714 } while (string_len > 0);
1716 /* Buffer passed to EVP_EncryptFinal() must be after data just
1717 * encrypted to avoid overwriting it.
1719 if (!EVP_DecryptFinal(ciphctx, obp, &tmplen)) {
1722 error ("error in DecryptFinal");
1726 fwrite(obp, 1, tmplen, of);
1728 /* added probable padding space to the length of the output buffer */
1730 EVP_CIPHER_CTX_cleanup(ciphctx);
1732 if (UNLIKELY(of != NULL)) {
1735 l_outbuf = make_ext_string((char*)outbuf, outlen, OSSL_CODING);
1737 XMALLOC_UNBIND(outbuf, alloclen, speccount);
1754 /* This is an opaque object for storing PKEYs in lisp */
1755 Lisp_Object Qevp_pkeyp;
1758 mark_evp_pkey(Lisp_Object obj)
1760 /* avoid some warning */
1766 print_evp_pkey(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1772 pkey = XEVPPKEY(obj)->evp_pkey;
1773 x509 = XEVPPKEY(obj)->x509;
1775 write_c_string("#<OpenSSL", printcharfun);
1778 X509_NAME *iss = X509_get_issuer_name(x509);
1779 X509_NAME *sub = X509_get_subject_name(x509);
1780 write_c_string(" X509 Certificate", printcharfun);
1781 write_c_string(" iss:", printcharfun);
1782 write_c_string(X509_NAME_oneline(sub, NULL, 0), printcharfun);
1783 write_c_string(" sub:", printcharfun);
1784 write_c_string(X509_NAME_oneline(iss, NULL, 0), printcharfun);
1789 write_c_string(";", printcharfun);
1791 if (rsa_pkey_p(pkey))
1792 write_c_string(" RSA", printcharfun);
1793 else if (dsa_pkey_p(pkey))
1794 write_c_string(" DSA", printcharfun);
1795 else if (ec_pkey_p(pkey))
1796 write_c_string(" EC", printcharfun);
1798 if (ossl_pkey_has_private_data(pkey))
1799 write_c_string(" private/public key", printcharfun);
1800 else if (ossl_pkey_has_public_data(pkey))
1801 write_c_string(" public key", printcharfun);
1803 write_c_string(" empty key", printcharfun);
1805 if (EVP_PKEY_size(pkey) > 0) {
1806 snprintf(buf, 256, ", size %d", EVP_PKEY_size(pkey)*8);
1807 write_c_string(buf, printcharfun);
1811 write_c_string(">", printcharfun);
1813 /* avoid some warning */
1817 static Lisp_EVP_PKEY *
1818 allocate_evp_pkey(void)
1820 Lisp_EVP_PKEY *evp_pkey =
1821 alloc_lcrecord_type(Lisp_EVP_PKEY, &lrecord_evp_pkey);
1822 evp_pkey->evp_pkey = NULL;
1823 evp_pkey->x509 = NULL;
1828 finalise_evp_pkey(void *header, int for_disksave)
1830 Lisp_EVP_PKEY *evp_pkey = (Lisp_EVP_PKEY *) header;
1832 if (evp_pkey->evp_pkey) {
1833 EVP_PKEY_free(evp_pkey->evp_pkey);
1834 evp_pkey->evp_pkey = NULL;
1836 if (evp_pkey->x509) {
1837 X509_free(evp_pkey->x509);
1838 evp_pkey->x509 = NULL;
1841 /* avoid some warning */
1845 DEFINE_LRECORD_IMPLEMENTATION("evp_pkey", evp_pkey,
1846 mark_evp_pkey, print_evp_pkey,
1852 make_evp_pkey(EVP_PKEY *pkey, X509 *x509)
1854 Lisp_EVP_PKEY *lisp_pkey = allocate_evp_pkey();
1856 lisp_pkey->evp_pkey = pkey;
1857 lisp_pkey->x509 = x509;
1859 return wrap_evppkey(lisp_pkey);
1863 make_evp_pkey_pk(EVP_PKEY *pkey)
1865 return make_evp_pkey(pkey, NULL);
1869 make_evp_pkey_x509(X509 *x509)
1871 return make_evp_pkey(X509_get_pubkey(x509), x509);
1874 DEFUN("ossl-pkey-p", Fossl_pkey_p, 1, 1, 0, /*
1875 Return t iff OBJECT is a pkey, nil otherwise.
1879 if (EVPPKEYP(object))
1885 DEFUN("ossl-pkey-size", Fossl_pkey_size, 1, 1, 0, /*
1886 Return the size a public key PKEY in bits.
1892 CHECK_EVPPKEY(pkey);
1894 pk = (XEVPPKEY(pkey))->evp_pkey;
1896 return make_int(EVP_PKEY_size(pk)*8);
1900 ossl_pkey_has_public_data(EVP_PKEY *pkey)
1902 if (rsa_pkey_p(pkey)) {
1903 #ifndef OPENSSL_NO_RSA
1904 return rsa_pkey_has_public_data((pkey->pkey).rsa);
1908 } else if (dsa_pkey_p(pkey)) {
1909 #ifndef OPENSSL_NO_DSA
1910 return dsa_pkey_has_public_data((pkey->pkey).dsa);
1914 } else if (ec_pkey_p(pkey)) {
1915 #ifndef OPENSSL_NO_EC
1916 return ec_pkey_has_public_data((pkey->pkey).ec);
1920 } else if (dh_pkey_p(pkey)) {
1921 #ifndef OPENSSL_NO_DH
1922 return dh_pkey_has_public_data((pkey->pkey).dh);
1930 ossl_pkey_has_private_data(EVP_PKEY *pkey)
1932 if (rsa_pkey_p(pkey)) {
1933 #ifndef OPENSSL_NO_RSA
1934 return rsa_pkey_has_private_data((pkey->pkey).rsa);
1938 } else if (dsa_pkey_p(pkey)) {
1939 #ifndef OPENSSL_NO_DSA
1940 return dsa_pkey_has_private_data((pkey->pkey).dsa);
1944 } else if (ec_pkey_p(pkey)) {
1945 #ifndef OPENSSL_NO_EC
1946 return ec_pkey_has_private_data((pkey->pkey).ec);
1950 } else if (dh_pkey_p(pkey)) {
1951 #ifndef OPENSSL_NO_DH
1952 return dh_pkey_has_private_data((pkey->pkey).dh);
1960 DEFUN("ossl-pkey-private-p", Fossl_pkey_private_p, 1, 1, 0, /*
1961 Return non-nil if PKEY contains private data.
1963 This function is not native OpenSSL.
1969 if (!(EVPPKEYP(pkey)))
1972 pk = (XEVPPKEY(pkey))->evp_pkey;
1974 if (ossl_pkey_has_private_data(pk))
1980 DEFUN("ossl-pkey-get-public", Fossl_pkey_get_public, 1, 1, 0, /*
1981 Return a copy of PKEY stripped by the private data.
1983 This function is not native OpenSSL.
1990 CHECK_EVPPKEY(pkey);
1992 pk = (XEVPPKEY(pkey))->evp_pkey;
1993 if (!(ossl_pkey_has_public_data(pk)))
1994 error ("key must have public data");
1996 pkout = EVP_PKEY_new();
1997 if (rsa_pkey_p(pk)) {
1998 #ifndef OPENSSL_NO_RSA
1999 EVP_PKEY_assign_RSA(pkout, RSAPublicKey_dup((pk->pkey).rsa));
2001 } else if (dsa_pkey_p(pk)) {
2002 #ifndef OPENSSL_NO_DSA
2003 EVP_PKEY_assign_DSA(pkout, dsa_get_public(pk));
2005 } else if (ec_pkey_p(pk)) {
2006 #ifndef OPENSSL_NO_EC
2007 EVP_PKEY_assign_EC_KEY(pkout, ec_get_public(pk));
2010 error ("no method to strip private data yet");
2012 return make_evp_pkey_pk(pkout);
2017 rsa_pkey_p(EVP_PKEY *pkey)
2021 type = EVP_PKEY_type(pkey->type);
2023 #ifndef OPENSSL_NO_RSA
2024 return ((type == EVP_PKEY_RSA) ||
2025 (type == EVP_PKEY_RSA2));
2030 #ifndef OPENSSL_NO_RSA
2032 rsa_pkey_has_public_data(RSA *rsakey)
2034 return (!(rsakey->n == NULL) &&
2035 !(rsakey->e == NULL));
2038 rsa_pkey_has_private_data(RSA *rsakey)
2040 return (rsa_pkey_has_public_data(rsakey) &&
2041 !(rsakey->d == NULL));
2044 DEFUN("ossl-rsa-generate-key", Fossl_rsa_generate_key, 2, 2, 0, /*
2045 Return an RSA public key with of length BITS and exponent EXPO.
2057 error ("modulus size must be a non-zero positive integer");
2058 if (!(XINT(expo) % 2))
2059 error ("exponent must be an odd positive integer");
2061 pkey = EVP_PKEY_new();
2062 rsakey = RSA_generate_key(XINT(bits), XINT(expo), NULL, NULL);
2063 EVP_PKEY_assign_RSA(pkey, rsakey);
2065 return make_evp_pkey_pk(pkey);
2068 DEFUN("ossl-rsa-pkey-p", Fossl_rsa_pkey_p, 1, 1, 0, /*
2069 Return t iff PKEY is of RSA type.
2075 if (!EVPPKEYP(pkey))
2078 pk = (XEVPPKEY(pkey))->evp_pkey;
2086 DEFUN("ossl-rsa-subkey-p", Fossl_rsa_subkey_p, 2, 2, 0, /*
2087 Return t iff PKEY1 is a subkey of PKEY2.
2088 I.e. if PKEY1 has the same public key data as PKEY2 and
2089 PKEY2 has all private data.
2091 This function is not native OpenSSL.
2100 CHECK_EVPPKEY(pkey1);
2101 CHECK_EVPPKEY(pkey2);
2103 pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2104 pk2 = (XEVPPKEY(pkey2))->evp_pkey;
2106 /* perform a type check first */
2107 if (!rsa_pkey_p(pk1))
2108 error ("pkey1 must be of RSA type");
2109 if (!rsa_pkey_p(pk2))
2110 error ("pkey2 must be of RSA type");
2112 rk1 = (pk1->pkey).rsa;
2113 rk2 = (pk2->pkey).rsa;
2115 if (rsa_pkey_has_private_data(rk2) &&
2116 rsa_pkey_has_public_data(rk1) &&
2117 (!BN_cmp(rk1->n, rk2->n)) &&
2118 (!BN_cmp(rk1->e, rk2->e)))
2123 #endif /* OPENSSL_NO_RSA */
2128 dsa_pkey_p(EVP_PKEY *pkey)
2132 type = EVP_PKEY_type(pkey->type);
2134 #ifndef OPENSSL_NO_DSA
2135 return ((type == EVP_PKEY_DSA) ||
2136 (type == EVP_PKEY_DSA1) ||
2137 (type == EVP_PKEY_DSA2) ||
2138 (type == EVP_PKEY_DSA3) ||
2139 (type == EVP_PKEY_DSA4));
2144 #ifndef OPENSSL_NO_DSA
2146 dsa_pkey_has_public_data(DSA *dsakey)
2148 return (!(dsakey->p == NULL) &&
2149 !(dsakey->q == NULL) &&
2150 !(dsakey->g == NULL) &&
2151 !(dsakey->pub_key == NULL));
2154 dsa_pkey_has_private_data(DSA *dsakey)
2156 return (dsa_pkey_has_public_data(dsakey) &&
2157 !(dsakey->priv_key == NULL));
2160 DEFUN("ossl-dsa-generate-key", Fossl_dsa_generate_key, 1, 2, 0, /*
2161 Return a DSA public key with of length BITS seeded with (optional) SEED.
2170 unsigned_long h_ret;
2177 error ("prime number size must be a non-zero positive integer");
2184 TO_EXTERNAL_FORMAT (LISP_STRING, seed,
2185 C_STRING_ALLOCA, seed_ext, OSSL_CODING);
2186 seed_len = OSSL_STRING_LENGTH(seed);
2189 pkey = EVP_PKEY_new();
2190 dsakey = DSA_generate_parameters(XINT(bits),
2191 (unsigned char*)seed_ext, seed_len,
2192 &counter_ret, &h_ret,
2194 if (!DSA_generate_key(dsakey))
2195 error ("error during generation of DSA key");
2197 EVP_PKEY_assign_DSA(pkey, dsakey);
2199 return make_evp_pkey_pk(pkey);
2202 DEFUN("ossl-dsa-pkey-p", Fossl_dsa_pkey_p, 1, 1, 0, /*
2203 Return t iff PKEY is of DSA type.
2209 if (!EVPPKEYP(pkey))
2212 pk = (XEVPPKEY(pkey))->evp_pkey;
2220 dsa_get_public(EVP_PKEY *pk)
2225 memcpy(key, (pk->pkey).dsa, sizeof(DSA));
2227 /* now kill the private data */
2228 key->priv_key = NULL;
2233 DEFUN("ossl-dsa-subkey-p", Fossl_dsa_subkey_p, 2, 2, 0, /*
2234 Return t iff PKEY1 is a subkey of PKEY2.
2235 I.e. if PKEY1 has the same public key data as PKEY2 and
2236 PKEY2 has all private data.
2238 This function is not native OpenSSL.
2247 CHECK_EVPPKEY(pkey1);
2248 CHECK_EVPPKEY(pkey2);
2250 pk1 = (XEVPPKEY(pkey1))->evp_pkey;
2251 pk2 = (XEVPPKEY(pkey2))->evp_pkey;
2253 /* perform a type check first */
2254 if (!dsa_pkey_p(pk1))
2255 error ("pkey1 must be of DSA type");
2256 if (!dsa_pkey_p(pk2))
2257 error ("pkey2 must be of DSA type");
2259 dk1 = (pk1->pkey).dsa;
2260 dk2 = (pk2->pkey).dsa;
2262 if (dsa_pkey_has_private_data(dk2) &&
2263 dsa_pkey_has_public_data(dk1) &&
2264 (!BN_cmp(dk1->p, dk2->p)) &&
2265 (!BN_cmp(dk1->q, dk2->q)) &&
2266 (!BN_cmp(dk1->g, dk2->g)) &&
2267 (!BN_cmp(dk1->pub_key, dk2->pub_key)))
2272 #endif /* OPENSSL_NO_DSA */
2277 ec_pkey_p(EVP_PKEY *pkey)
2281 type = EVP_PKEY_type(pkey->type);
2283 #ifndef OPENSSL_NO_EC
2284 return (type == EVP_PKEY_EC);
2289 #ifndef OPENSSL_NO_EC
2291 ec_pkey_has_public_data(EC_KEY *ec_key)
2293 return (!(EC_KEY_get0_group(ec_key) == NULL) &&
2294 !(EC_KEY_get0_public_key(ec_key) == NULL));
2297 ec_pkey_has_private_data(EC_KEY *ec_key)
2299 return (ec_pkey_has_public_data(ec_key) &&
2300 !(EC_KEY_get0_private_key(ec_key) == NULL));
2303 DEFUN("ossl-ec-available-curves", Fossl_ec_available_curves, 0, 0, 0, /*
2304 Return a list of builtin elliptic curves.
2308 EC_builtin_curve *curves = NULL;
2309 size_t crv_len = 0, n = 0;
2310 Lisp_Object lcurves;
2314 crv_len = EC_get_builtin_curves(NULL, 0);
2315 curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
2318 error ("no curves defined");
2320 if (!EC_get_builtin_curves(curves, crv_len)) {
2321 OPENSSL_free(curves);
2322 error ("error during initialisation of curves");
2325 for (n = 0; n < crv_len; n++) {
2326 int nid = curves[n].nid;
2327 lcurves = Fcons(intern(OBJ_nid2sn(nid)), lcurves);
2330 OPENSSL_free(curves);
2336 ec_curve_by_name(char *name)
2338 return OBJ_sn2nid(name);
2341 DEFUN("ossl-ec-generate-key", Fossl_ec_generate_key, 1, 1, 0, /*
2342 Return a EC public key on CURVE.
2343 CURVE may be any symbol from `ossl-ec-available-curves'.
2345 At the moment we do not support creating custom curves.
2350 EC_KEY *eckey = EC_KEY_new();
2352 CHECK_SYMBOL(curve);
2354 pkey = EVP_PKEY_new();
2355 eckey = EC_KEY_new_by_curve_name(
2356 ec_curve_by_name((char *)string_data(XSYMBOL(curve)->name)));
2358 if ((eckey == NULL)) {
2359 error ("no such curve");
2362 if (!EC_KEY_generate_key(eckey))
2363 error ("error during generation of EC key");
2365 EVP_PKEY_assign_EC_KEY(pkey, eckey);
2367 return make_evp_pkey_pk(pkey);
2370 DEFUN("ossl-ec-pkey-p", Fossl_ec_pkey_p, 1, 1, 0, /*
2371 Return t iff PKEY is of EC type.
2378 if (!EVPPKEYP(pkey))
2381 pk = (XEVPPKEY(pkey))->evp_pkey;
2382 type = EVP_PKEY_type(pk->type);
2383 if (type == EVP_PKEY_EC)
2390 ec_get_public(EVP_PKEY *pk)
2394 key = EC_KEY_dup((pk->pkey).ec);
2396 /* now kill the private data */
2397 EC_KEY_set_private_key(key, NULL);
2401 #endif /* OPENSSL_NO_EC */
2406 dh_pkey_p(EVP_PKEY *pkey)
2410 type = EVP_PKEY_type(pkey->type);
2412 #ifndef OPENSSL_NO_DH
2413 return (type == EVP_PKEY_DH);
2418 #ifndef OPENSSL_NO_DH
2420 dh_pkey_has_public_data(DH *dhkey)
2422 return (!(dhkey->p == NULL) &&
2423 !(dhkey->g == NULL) &&
2424 !(dhkey->pub_key == NULL));
2427 dh_pkey_has_private_data(DH *dhkey)
2429 return (dh_pkey_has_public_data(dhkey) &&
2430 !(dhkey->priv_key == NULL));
2433 DEFUN("ossl-dh-pkey-p", Fossl_dh_pkey_p, 1, 1, 0, /*
2434 Return t iff PKEY is of DH type.
2440 if (!EVPPKEYP(pkey))
2443 pk = (XEVPPKEY(pkey))->evp_pkey;
2451 #endif /* OPENSSL_NO_DH */
2454 /* more general access functions */
2455 DEFUN("ossl-seal", Fossl_seal, 3, 3, 0, /*
2456 Return an envelope derived from encrypting STRING by CIPHER under PKEY
2457 with the hybrid technique.
2459 That is, create a random key/iv pair for the symmetric encryption with
2460 CIPHER and encrypt that key/iv asymmetrically with the provided public
2463 The envelope returned is a list
2464 \(encrypted_string encrypted_key encrypted_iv\)
2466 `encrypted_string' is the (symmetrically) encrypted message
2467 `encrypted_key' is the (asymmetrically) encrypted random key
2468 `encrypted_iv' is the (asymmetrically) encrypted random iv
2470 Note: You probably want to put a wrapping encoder function
2471 (like `base16-encode-string') around it, since this function
2472 returns binary string data.
2474 (cipher, string, pkey))
2476 /* declarations for the cipher */
2477 const EVP_CIPHER *ciph;
2478 EVP_CIPHER_CTX ciphctx;
2479 /* declarations for the pkey */
2482 unsigned char *ekey;
2485 /* buffer for the generated IV */
2486 char iv[EVP_MAX_IV_LENGTH];
2488 /* buffer for output */
2489 unsigned char *outbuf;
2490 unsigned int outlen;
2491 Lisp_Object l_outbuf;
2492 /* buffer for external string data */
2499 CHECK_SYMBOL(cipher);
2500 CHECK_STRING(string);
2501 CHECK_EVPPKEY(pkey);
2504 pk[0] = (XEVPPKEY(pkey))->evp_pkey;
2505 if (!ossl_pkey_has_public_data(pk[0])) {
2506 error ("cannot seal, key has no public key data");
2510 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2511 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2512 string_len = OSSL_STRING_LENGTH(string);
2514 OpenSSL_add_all_algorithms();
2515 ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2519 error ("no such cipher");
2523 /* alloc ekey buffer */
2524 ekey = (unsigned char*)xmalloc_atomic(EVP_PKEY_size(pk[0]));
2526 /* now allocate some output buffer externally
2527 * this one has to be at least EVP_CIPHER_block_size bigger
2528 * since block algorithms merely operate blockwise
2530 outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string) +
2531 EVP_CIPHER_block_size(ciph));
2533 EVP_CIPHER_CTX_init(&ciphctx);
2534 if (!(EVP_SealInit(&ciphctx, ciph,
2536 (unsigned char *)&iv,
2537 (EVP_PKEY **)&pk, npubk)==npubk)) {
2541 error ("error in SealInit");
2544 if (!EVP_SealUpdate(&ciphctx, outbuf, (int *)&outlen,
2545 (unsigned char*)string_ext, string_len)) {
2549 error ("error in SealUpdate");
2552 if (!EVP_SealFinal(&ciphctx, (unsigned char*)outbuf+outlen, &tmplen)) {
2556 error ("error in SealFinal");
2559 /* added probable padding space to the length of the output buffer */
2561 EVP_CIPHER_CTX_cleanup(&ciphctx);
2563 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2564 l_ekey = make_ext_string((char *)ekey, ekey_len, OSSL_CODING);
2565 l_iv = make_ext_string(iv,EVP_CIPHER_iv_length(ciph), OSSL_CODING);
2570 return list3(l_outbuf, l_ekey, l_iv);
2574 DEFUN("ossl-open", Fossl_open, 4, 5, 0, /*
2575 Return the deciphered message STRING from an envelope
2576 obtained by `ossl-seal'.
2578 CIPHER is the cipher to use (the same as in `ossl-seal')
2579 STRING is the encrypted message
2580 PKEY is the private key
2581 EKEY is the encrypted random key
2582 EIV is the encrypted iv
2584 (cipher, string, pkey, ekey, eiv))
2586 /* declarations for the cipher */
2587 const EVP_CIPHER *ciph;
2588 EVP_CIPHER_CTX ciphctx;
2589 /* declarations for the pkey */
2591 /* buffer for external ekey data */
2594 /* buffer for external eiv data */
2596 /* buffer for output */
2597 unsigned char *outbuf;
2598 unsigned int outlen;
2599 Lisp_Object l_outbuf;
2600 /* buffer for external string data */
2607 CHECK_SYMBOL(cipher);
2608 CHECK_STRING(string);
2609 CHECK_EVPPKEY(pkey);
2613 pk = (XEVPPKEY(pkey))->evp_pkey;
2614 if (!ossl_pkey_has_private_data(pk))
2615 error ("cannot open, key has no private key data");
2617 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2618 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2619 string_len = OSSL_STRING_LENGTH(string);
2620 TO_EXTERNAL_FORMAT (LISP_STRING, ekey,
2621 C_STRING_ALLOCA, ekey_ext, OSSL_CODING);
2622 ekey_len = OSSL_STRING_LENGTH(ekey);
2624 OpenSSL_add_all_algorithms();
2625 ciph = EVP_get_cipherbyname((char*)string_data(XSYMBOL(cipher)->name));
2629 error ("no such cipher");
2637 TO_EXTERNAL_FORMAT (LISP_STRING, eiv,
2638 C_STRING_ALLOCA, eiv_ext, OSSL_CODING);
2641 /* now allocate some output buffer externally */
2642 outbuf = (unsigned char *)xmalloc_atomic(XSTRING_LENGTH(string));
2644 EVP_CIPHER_CTX_init(&ciphctx);
2645 if (!EVP_OpenInit(&ciphctx, ciph,
2646 (unsigned char*)ekey_ext,
2647 (unsigned int)ekey_len,
2648 (unsigned char*)eiv_ext, pk)) {
2651 error ("error in OpenInit");
2654 if (!EVP_OpenUpdate(&ciphctx, outbuf, (int *)&outlen,
2655 (unsigned char*)string_ext,
2656 (unsigned int)string_len)) {
2659 error ("error in OpenUpdate");
2662 if (!EVP_OpenFinal(&ciphctx, outbuf+outlen, &tmplen)) {
2665 error ("error in OpenFinal");
2668 /* added probable padding space to the length of the output buffer */
2670 EVP_CIPHER_CTX_cleanup(&ciphctx);
2672 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2681 DEFUN("ossl-sign", Fossl_sign, 3, 3, 0, /*
2682 Return a signature obtained by signing STRING under DIGEST with PKEY.
2684 That is, hash the message STRING with the message digest DIGEST and
2685 encrypt the result with the private key PKEY.
2687 Note: Due to some relationship between the public key system and the
2688 message digest you cannot use every digest algorithm with every
2690 The most certain results will be achieved using
2691 RSA keys with RSA-* digests, DSA keys with DSA-* digests.
2693 See `ossl-available-digests'.
2695 Note: You probably want to put a wrapping encoder function
2696 (like `base16-encode-string') around it, since this returns
2699 (digest, string, pkey))
2701 /* declarations for the cipher */
2704 /* declarations for the pkey */
2706 /* buffer for output */
2707 unsigned char *outbuf;
2708 unsigned int outlen;
2709 Lisp_Object l_outbuf;
2710 /* buffer for external string data */
2715 CHECK_SYMBOL(digest);
2716 CHECK_STRING(string);
2717 CHECK_EVPPKEY(pkey);
2720 pk = (XEVPPKEY(pkey))->evp_pkey;
2721 if (!ossl_pkey_has_private_data(pk)) {
2722 error ("cannot sign, key has no private key data");
2725 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2726 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2727 string_len = OSSL_STRING_LENGTH(string);
2729 OpenSSL_add_all_algorithms();
2730 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2734 error ("no such digest");
2738 /* now allocate some output buffer externally */
2739 outbuf = (unsigned char *)xmalloc_atomic(EVP_PKEY_size(pk));
2741 EVP_MD_CTX_init(&mdctx);
2742 if (!(EVP_SignInit(&mdctx, md))) {
2745 error ("error in SignInit");
2748 if (!EVP_SignUpdate(&mdctx, string_ext, string_len)) {
2751 error ("error in SignUpdate");
2754 if (!EVP_SignFinal(&mdctx, outbuf, &outlen, pk)) {
2757 error ("error in SignFinal");
2760 EVP_MD_CTX_cleanup(&mdctx);
2762 l_outbuf = make_ext_string((char *)outbuf, outlen, OSSL_CODING);
2770 DEFUN("ossl-verify", Fossl_verify, 4, 4, 0, /*
2771 Return t iff SIG is a valid signature of STRING under DIGEST obtained by PKEY.
2773 That is, hash the message STRING with the message digest DIGEST, then
2774 decrypt the signature SIG with the public key PKEY.
2775 Compare the results and return t iff both hashes are equal.
2777 DIGEST is the digest to use (the same as in `ossl-sign')
2778 STRING is the message
2779 SIG is the signature of message
2780 PKEY is the public key
2782 (digest, string, sig, pkey))
2784 /* declarations for the cipher */
2787 /* declarations for the pkey */
2789 /* buffer for external signature data */
2792 /* buffer for external string data */
2799 CHECK_SYMBOL(digest);
2800 CHECK_STRING(string);
2802 CHECK_EVPPKEY(pkey);
2805 pk = (XEVPPKEY(pkey))->evp_pkey;
2806 if (!ossl_pkey_has_public_data(pk))
2807 error ("cannot verify, key has no public key data");
2809 OpenSSL_add_all_algorithms();
2810 md = EVP_get_digestbyname((char*)string_data(XSYMBOL(digest)->name));
2814 error ("no such digest");
2818 TO_EXTERNAL_FORMAT (LISP_STRING, string,
2819 C_STRING_ALLOCA, string_ext, OSSL_CODING);
2820 string_len = OSSL_STRING_LENGTH(string);
2821 TO_EXTERNAL_FORMAT (LISP_STRING, sig,
2822 C_STRING_ALLOCA, sig_ext, OSSL_CODING);
2823 sig_len = OSSL_STRING_LENGTH(sig);
2825 EVP_MD_CTX_init(&mdctx);
2826 if (!EVP_VerifyInit(&mdctx, md)) {
2828 error ("error in VerifyInit");
2831 if (!EVP_VerifyUpdate(&mdctx, string_ext, string_len)) {
2833 error ("error in VerifyUpdate");
2836 result = EVP_VerifyFinal(&mdctx, (unsigned char*)sig_ext, sig_len, pk);
2839 error ("error in VerifyFinal");
2842 EVP_MD_CTX_cleanup(&mdctx);
2846 return result ? Qt : Qnil;
2855 DEFUN("ossl-pem-read-public-key", Fossl_pem_read_public_key, 1, 1, 0, /*
2856 Return a key (the public part) stored in a PEM structure from FILE.
2860 /* declarations for the pkey */
2869 file = Fexpand_file_name(file, Qnil);
2871 if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2872 error ("error opening file.");
2874 pk509 = PEM_read_X509(fp, NULL, NULL, NULL);
2875 pk = PEM_read_PUBKEY(fp, NULL, NULL, NULL);
2879 return make_evp_pkey(pk, pk509);
2882 DEFUN("ossl-pem-read-key", Fossl_pem_read_key, 1, 2, 0, /*
2883 Return a key stored in a PEM structure from FILE.
2884 If the (private part of the) key is protected with a password
2885 provide (optional) PASSWORD.
2889 /* declarations for the pkey */
2893 /* password pointer */
2898 file = Fexpand_file_name(file, Qnil);
2900 if ((fp = fopen((char *)XSTRING_DATA(file), "r")) == NULL)
2901 error ("error opening file.");
2903 if (NILP(password)) {
2906 CHECK_STRING(password);
2907 pass = (char *)XSTRING_DATA(password);
2910 pk = PEM_read_PrivateKey(fp, NULL, NULL, pass);
2913 /* now maybe it is a public key only */
2914 return Fossl_pem_read_public_key(file);
2917 return make_evp_pkey_pk(pk);
2920 DEFUN("ossl-pem-write-public-key", Fossl_pem_write_public_key, 2, 2, 0, /*
2921 Write PKEY (the public part) in a PEM structure to FILE.
2925 /* declarations for the pkey */
2932 CHECK_EVPPKEY(pkey);
2934 file = Fexpand_file_name(file, Qnil);
2936 pk = XEVPPKEY(pkey)->evp_pkey;
2937 pk509 = XEVPPKEY(pkey)->x509;
2939 if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL)
2940 error ("error opening file.");
2942 if (!PEM_write_PUBKEY(fp, pk)) {
2944 error ("error writing PEM file.");
2952 DEFUN("ossl-pem-write-key", Fossl_pem_write_key, 2, 4, 0, /*
2953 Write PKEY in a PEM structure to FILE. The key itself is
2954 protected by (optional) CIPHER with PASSWORD.
2956 CIPHER can be set to nil and the key will not be encrypted.
2957 PASSWORD is ignored in this case.
2959 (file, pkey, cipher, password))
2961 const EVP_CIPHER *ciph;
2962 /* declarations for the pkey */
2967 /* password pointer */
2971 CHECK_EVPPKEY(pkey);
2973 file = Fexpand_file_name(file, Qnil);
2975 pk = XEVPPKEY(pkey)->evp_pkey;
2976 pk509 = XEVPPKEY(pkey)->x509;
2978 if (!ossl_pkey_has_private_data(pk))
2979 return Fossl_pem_write_public_key(file, pkey);
2981 CHECK_SYMBOL(cipher);
2983 OpenSSL_add_all_algorithms();
2989 ciph = EVP_get_cipherbyname(
2990 (char *)string_data(XSYMBOL(cipher)->name));
2993 error ("no such cipher");
2997 if (NILP(password)) {
3001 CHECK_STRING(password);
3002 pass = (char *)XSTRING_DATA(password);
3005 if ((fp = fopen((char *)XSTRING_DATA(file), "w")) == NULL) {
3007 error ("error opening file.");
3010 if (!PEM_write_PKCS8PrivateKey(fp, pk, ciph, NULL, 0, NULL, pass)) {
3013 error ("error writing PEM file.");
3023 ossl_pem_pkey_cb(BIO *bio, int cmd, const char *argp,
3024 int argi, long argl, long ret)
3027 void *foo = BIO_get_callback_arg(bio);
3029 if (!(key = (Lisp_Object)foo)) {
3033 if (BIO_CB_RETURN & cmd) {
3039 key = concat2(key, make_ext_string(argp, argi, OSSL_CODING));
3040 BIO_set_callback_arg(bio, (void*)key);
3048 DEFUN("ossl-pem-public-key",Fossl_pem_public_key, 1, 1, 0, /*
3049 Return PKEY as PEM encoded string.
3053 /* This function can GC */
3054 /* declarations for the pkey */
3060 struct gcpro gcpro1;
3064 CHECK_EVPPKEY(pkey);
3066 pk = (XEVPPKEY(pkey))->evp_pkey;
3068 if (!(b = BIO_new(BIO_s_null()))) {
3070 error("cannot open memory buffer");
3074 result = build_string("");
3075 BIO_set_callback(b, ossl_pem_pkey_cb);
3076 BIO_set_callback_arg(b, (void*)result);
3078 if (!PEM_write_bio_PUBKEY(b, pk)) {
3082 error ("error creating PEM string");
3087 void *foo = BIO_get_callback_arg(b);
3088 if (!(result = (Lisp_Object)foo)) {
3099 DEFUN("ossl-pem-key",Fossl_pem_key, 1, 3, 0, /*
3100 Return PKEY as PEM encoded string. The key itself is
3101 protected by (optional) CIPHER with PASSWORD.
3103 CIPHER can be set to nil and the key will not be encrypted.
3104 PASSWORD is ignored in this case.
3106 (pkey, cipher, password))
3108 /* This function can GC */
3109 /* declarations for the pkey */
3112 const EVP_CIPHER *ciph;
3116 struct gcpro gcpro1, gcpro2, gcpro3;
3118 GCPRO3(pkey, cipher, password);
3120 CHECK_EVPPKEY(pkey);
3122 pk = (XEVPPKEY(pkey))->evp_pkey;
3124 if (!ossl_pkey_has_private_data(pk)) {
3126 return Fossl_pem_public_key(pkey);
3129 CHECK_SYMBOL(cipher);
3131 OpenSSL_add_all_algorithms();
3137 ciph = EVP_get_cipherbyname(
3138 (char *)string_data(XSYMBOL(cipher)->name));
3142 error ("no such cipher");
3147 if (NILP(password)) {
3151 CHECK_STRING(password);
3152 pass = (char *)XSTRING_DATA(password);
3155 if (!(b = BIO_new(BIO_s_null()))) {
3157 error("cannot open memory buffer");
3161 result = build_string("");
3162 BIO_set_callback(b, ossl_pem_pkey_cb);
3163 BIO_set_callback_arg(b, (void*)result);
3165 if (!PEM_write_bio_PKCS8PrivateKey(b, pk, ciph, NULL, 0, NULL, pass)) {
3169 error ("error creating PEM string");
3174 void *foo = BIO_get_callback_arg(b);
3176 if (!(result = (Lisp_Object)foo)) {
3191 * The SSL support in this API is sorta high level since having
3192 * server hellos, handshakes and stuff like that is not what you want
3196 /* This is an opaque object for storing PKEYs in lisp */
3197 Lisp_Object Qssl_connp;
3200 make_ssl_conn(Lisp_SSL_CONN *ssl_conn)
3202 Lisp_Object lisp_ssl_conn;
3203 XSETSSLCONN(lisp_ssl_conn, ssl_conn);
3204 return lisp_ssl_conn;
3208 mark_ssl_conn(Lisp_Object obj)
3210 mark_object(XSSLCONN(obj)->parent);
3211 mark_object(XSSLCONN(obj)->pipe_instream);
3212 mark_object(XSSLCONN(obj)->pipe_outstream);
3214 mark_object(XSSLCONN(obj)->coding_instream);
3215 mark_object(XSSLCONN(obj)->coding_outstream);
3222 print_ssl_conn(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
3227 conn = XSSLCONN(obj)->ssl_conn;
3228 parent = XSSLCONN(obj)->parent;
3230 write_c_string("#<OpenSSL socket layer: ", printcharfun);
3232 write_c_string("dead", printcharfun);
3234 write_c_string(SSL_get_version(conn), printcharfun);
3237 if (PROCESSP(parent)) {
3238 write_c_string(" on top of ", printcharfun);
3239 print_internal(parent, printcharfun, escapeflag);
3241 #endif /* HAVE_SOCKETS */
3243 #ifdef HAVE_POSTGRESQL
3244 if (PGCONNP(parent) &&
3245 PQstatus(XPGCONN(parent)->pgconn) == CONNECTION_OK) {
3246 write_c_string(" on top of ", printcharfun);
3247 print_internal(parent, printcharfun, escapeflag);
3249 #endif /* HAVE_POSTGRESQL */
3250 write_c_string(">", printcharfun);
3254 allocate_ssl_conn(void)
3256 Lisp_SSL_CONN *ssl_conn =
3257 alloc_lcrecord_type(Lisp_SSL_CONN, &lrecord_ssl_conn);
3259 /* the network process stuff */
3260 ssl_conn->parent = Qnil;
3261 ssl_conn->infd = -1;
3262 ssl_conn->outfd = -1;
3264 ssl_conn->connected_p = 0;
3265 ssl_conn->protected_p = 0;
3267 ssl_conn->pipe_instream = Qnil;
3268 ssl_conn->pipe_outstream = Qnil;
3270 ssl_conn->coding_instream = Qnil;
3271 ssl_conn->coding_outstream = Qnil;
3278 finalise_ssl_conn(void *header, int for_disksave)
3280 Lisp_SSL_CONN *ssl_conn = (Lisp_SSL_CONN *) header;
3282 if (!(ssl_conn->ssl_conn == NULL)) {
3283 if (ssl_conn->connected_p)
3284 SSL_shutdown(ssl_conn->ssl_conn);
3285 SSL_free(ssl_conn->ssl_conn);
3286 ssl_conn->ssl_conn = NULL;
3288 if (!(ssl_conn->ssl_ctx == NULL)) {
3289 SSL_CTX_free(ssl_conn->ssl_ctx);
3290 ssl_conn->ssl_ctx = NULL;
3292 ssl_conn->ssl_bio = NULL;
3294 if (PROCESSP(ssl_conn->parent)) {
3295 XPROCESS(ssl_conn->parent)->process_type = PROCESS_TYPE_NETWORK;
3296 XPROCESS(ssl_conn->parent)->process_type_data = Qnil;
3298 /* we leave the process alive, it's not our fault, but
3299 * we nullify its pointer
3301 ssl_conn->parent = Qnil;
3302 ssl_conn->infd = -1;
3303 ssl_conn->outfd = -1;
3305 ssl_conn->connected_p = 0;
3306 ssl_conn->protected_p = 0;
3308 /* free the lstream resources */
3309 #if 0 /* will lead to problems */
3310 if (LSTREAMP(ssl_conn->pipe_instream))
3311 Lstream_delete(XLSTREAM(ssl_conn->pipe_instream));
3312 if (LSTREAMP(ssl_conn->pipe_outstream))
3313 Lstream_delete(XLSTREAM(ssl_conn->pipe_outstream));
3315 ssl_conn->pipe_instream = Qnil;
3316 ssl_conn->pipe_outstream = Qnil;
3318 #if 0 /* will lead to problems */
3319 if (LSTREAMP(ssl_conn->coding_instream))
3320 Lstream_delete(XLSTREAM(ssl_conn->coding_instream));
3321 if (LSTREAMP(ssl_conn->coding_outstream))
3322 Lstream_delete(XLSTREAM(ssl_conn->coding_outstream));
3324 ssl_conn->coding_instream = Qnil;
3325 ssl_conn->coding_outstream = Qnil;
3328 /* avoid some warning */
3332 DEFINE_LRECORD_IMPLEMENTATION("ssl_conn", ssl_conn,
3333 mark_ssl_conn, print_ssl_conn,
3335 NULL, NULL, 0, Lisp_SSL_CONN);
3338 ssl_conn_alive_p(Lisp_SSL_CONN *ssl_conn)
3340 return ssl_conn->connected_p;
3344 get_process_infd(Lisp_Process * p)
3346 Lisp_Object instr, outstr;
3347 get_process_streams(p, &instr, &outstr);
3348 return Lstream_get_fd(XLSTREAM(instr));
3351 get_process_outfd(Lisp_Process * p)
3353 Lisp_Object instr, outstr;
3354 get_process_streams(p, &instr, &outstr);
3355 return Lstream_get_fd(XLSTREAM(outstr));
3359 event_stream_ssl_create_stream_pair(
3361 Lisp_Object *instream, Lisp_Object *outstream, int flags)
3363 *instream = make_ssl_input_stream(conn, flags);
3364 *outstream = make_ssl_output_stream(conn, flags);
3370 init_ssl_io_handles(Lisp_SSL_CONN *s, int flags)
3372 event_stream_ssl_create_stream_pair(
3373 s->ssl_conn, &s->pipe_instream, &s->pipe_outstream, flags);
3376 s->coding_instream = make_decoding_input_stream(
3377 XLSTREAM(s->pipe_instream), Fget_coding_system(
3378 Vcoding_system_for_read));
3379 Lstream_set_character_mode(XLSTREAM(s->coding_instream));
3380 s->coding_outstream = make_encoding_output_stream(
3381 XLSTREAM(s->pipe_outstream), Fget_coding_system(
3382 Vcoding_system_for_write));
3383 #endif /* FILE_CODING */
3386 /* Advanced step-by-step initialisation */
3387 #define OSSL_CHECK_PROCESS(process) \
3389 /* Make sure the process is really alive. */ \
3390 if (!EQ(XPROCESS(process)->status_symbol, Qrun)) \
3391 error("Network stream %s not alive", \
3392 XSTRING_DATA(XPROCESS(process)->name)); \
3393 /* Make sure the process is a network stream. */ \
3394 if (!network_connection_p(process)) \
3395 error("Process %s is not a network stream", \
3396 XSTRING_DATA(XPROCESS(process)->name)); \
3399 #ifdef OSSL_DEBUG_FLAG
3401 ossl_bio_dump_callback(BIO *bio, int cmd, const char *argp,
3402 int argi, long argl, long ret)
3406 out=(BIO *)BIO_get_callback_arg(bio);
3407 if (out == NULL) return(ret);
3409 if (cmd == (BIO_CB_READ|BIO_CB_RETURN))
3411 BIO_printf(out,"read from %p [%p] (%d bytes => %ld (0x%lX))\n",
3412 (void *)bio,argp,argi,ret,ret);
3413 BIO_dump(out,argp,(int)ret);
3416 else if (cmd == (BIO_CB_WRITE|BIO_CB_RETURN))
3418 BIO_printf(out,"write to %p [%p] (%d bytes => %ld (0x%lX))\n",
3419 (void *)bio,argp,argi,ret,ret);
3420 BIO_dump(out,argp,(int)ret);
3427 ossl_ssl_prepare_cmeth(Lisp_Object method)
3429 SSL_METHOD *meth = NULL;
3430 Lisp_SSL_CONN *lisp_ssl_conn;
3432 /* start preparing the conn object */
3434 SSL_load_error_strings();
3437 else if (EQ(method, Qssl2))
3438 meth = (SSL_METHOD *)SSLv2_client_method();
3439 else if (EQ(method, Qssl3))
3440 meth = (SSL_METHOD *)SSLv3_client_method();
3441 else if (EQ(method, Qssl23))
3442 meth = (SSL_METHOD *)SSLv23_client_method();
3443 else if (EQ(method, Qtls1))
3444 meth = (SSL_METHOD *)TLSv1_client_method();
3446 meth = (SSL_METHOD *)TLSv1_client_method();
3449 error("OSSL: not enough random data");
3451 /* now allocate this stuff, pump it and return */
3452 lisp_ssl_conn = allocate_ssl_conn();
3453 lisp_ssl_conn->ssl_meth = meth;
3454 lisp_ssl_conn->ssl_ctx = NULL;
3455 lisp_ssl_conn->ssl_conn = NULL;
3456 lisp_ssl_conn->ssl_bio = NULL;
3458 return make_ssl_conn(lisp_ssl_conn);
3462 ossl_ssl_prepare_smeth(Lisp_Object method)
3464 SSL_METHOD *meth = NULL;
3465 Lisp_SSL_CONN *lisp_ssl_conn;
3467 /* start preparing the conn object */
3469 SSL_load_error_strings();
3472 else if (EQ(method, Qssl2))
3473 meth = (SSL_METHOD *)SSLv2_server_method();
3474 else if (EQ(method, Qssl3))
3475 meth = (SSL_METHOD *)SSLv3_server_method();
3476 else if (EQ(method, Qssl23))
3477 meth = (SSL_METHOD *)SSLv23_server_method();
3478 else if (EQ(method, Qtls1))
3479 meth = (SSL_METHOD *)TLSv1_server_method();
3481 meth = (SSL_METHOD *)SSLv23_server_method();
3484 error("OSSL: not enough random data");
3486 /* now allocate this stuff, pump it and return */
3487 lisp_ssl_conn = allocate_ssl_conn();
3488 lisp_ssl_conn->ssl_meth = meth;
3489 lisp_ssl_conn->ssl_ctx = NULL;
3490 lisp_ssl_conn->ssl_conn = NULL;
3491 lisp_ssl_conn->ssl_bio = NULL;
3493 return make_ssl_conn(lisp_ssl_conn);
3497 ossl_ssl_prepare_ctx(Lisp_Object ssl_conn)
3499 /* SSL connection stuff */
3500 SSL_CTX *ctx = NULL;
3501 Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3503 ctx = SSL_CTX_new(lisp_ssl_conn->ssl_meth);
3505 error("OSSL: context initialisation failed");
3507 /* OpenSSL contains code to work-around lots of bugs and flaws in
3508 * various SSL-implementations. SSL_CTX_set_options() is used to enabled
3509 * those work-arounds. The man page for this option states that
3510 * SSL_OP_ALL enables all the work-arounds and that "It is usually safe
3511 * to use SSL_OP_ALL to enable the bug workaround options if
3512 * compatibility with somewhat broken implementations is desired."
3514 SSL_CTX_set_options(ctx, SSL_OP_ALL);
3516 lisp_ssl_conn->ssl_ctx = ctx;
3522 ossl_ssl_prepare(Lisp_Object ssl_conn, void(*fun)(SSL*))
3524 /* SSL connection stuff */
3527 #ifdef OSSL_DEBUG_FLAG
3528 BIO *bio_c_out = NULL;
3530 Lisp_SSL_CONN *lisp_ssl_conn = XSSLCONN(ssl_conn);
3532 /* now initialise a new connection context */
3533 conn = SSL_new(lisp_ssl_conn->ssl_ctx);
3534 if (conn == NULL || fun == NULL)
3535 error("OSSL: connection initialisation failed");
3537 /* always renegotiate */
3538 SSL_set_mode(conn, SSL_MODE_AUTO_RETRY);
3540 /* initialise the main connection BIO */
3541 bio = BIO_new(BIO_s_socket());
3543 #ifdef OSSL_DEBUG_FLAG
3544 /* this is a debug BIO which pukes tons of stuff to stderr */
3545 bio_c_out = BIO_new_fp(stderr, BIO_NOCLOSE);
3546 BIO_set_callback(bio, ossl_bio_dump_callback);
3547 BIO_set_callback_arg(bio, bio_c_out);
3550 /* connect SSL with the bio */
3551 SSL_set_bio(conn, bio, bio);
3552 /* turn into client or server */
3555 /* now allocate this stuff, pump it and return */
3556 lisp_ssl_conn->ssl_conn = conn;
3557 lisp_ssl_conn->ssl_bio = bio;
3559 /* create lstream handles */
3560 init_ssl_io_handles(lisp_ssl_conn, STREAM_NETWORK_CONNECTION);
3565 /* Injection of CA certificates */
3566 int ossl_ssl_inject_ca(Lisp_Object ssl_conn, Lisp_Object cacert)
3572 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3573 cert = XEVPPKEY(cacert)->evp_pkey;
3574 xc509 = XEVPPKEY(cacert)->x509;
3576 if (cert && !xc509) {
3578 X509_set_pubkey(xc509, cert);
3579 XEVPPKEY(cacert)->x509 = xc509;
3584 /* what about coding system issues? */
3585 if (!SSL_CTX_add_client_CA(ctx, xc509))
3591 int ossl_ssl_inject_ca_file(Lisp_Object ssl_conn, Lisp_Object cafile)
3595 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3597 /* what about coding system issues? */
3598 if (!SSL_CTX_load_verify_locations(
3599 ctx, (char*)XSTRING_DATA(cafile), NULL))
3605 int ossl_ssl_inject_ca_path(Lisp_Object ssl_conn, Lisp_Object capath)
3609 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3611 /* what about coding system issues? */
3612 if (!SSL_CTX_load_verify_locations(
3613 ctx, NULL, (char*)XSTRING_DATA(capath)))
3619 int ossl_ssl_inject_cert(Lisp_Object ssl_conn,
3620 Lisp_Object cert, Lisp_Object key)
3627 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3628 pkey = XEVPPKEY(key)->evp_pkey;
3629 xcert = XEVPPKEY(cert)->evp_pkey;
3630 xc509 = XEVPPKEY(cert)->x509;
3632 if (xcert && !xc509) {
3634 X509_set_pubkey(xc509, xcert);
3635 XEVPPKEY(cert)->x509 = xc509;
3640 if (SSL_CTX_use_certificate(ctx, xc509) <= 0)
3643 if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0)
3645 if (!SSL_CTX_check_private_key(ctx))
3651 int ossl_ssl_inject_cert_file(Lisp_Object ssl_conn,
3652 Lisp_Object cert, Lisp_Object key)
3656 ctx = XSSLCONN(ssl_conn)->ssl_ctx;
3658 if (SSL_CTX_use_certificate_file(
3659 ctx, (char*)XSTRING_DATA(cert), SSL_FILETYPE_PEM) <= 0)
3661 if (SSL_CTX_use_PrivateKey_file(
3662 ctx, (char*)XSTRING_DATA(key), SSL_FILETYPE_PEM) <= 0)
3664 if (!SSL_CTX_check_private_key(ctx))
3670 Lisp_Object ossl_ssl_handshake(Lisp_Object ssl_conn, Lisp_Object process)
3672 /* This function can GC */
3673 /* SSL connection stuff */
3676 #if 0 && defined(OSSL_DEBUG_FLAG)
3677 BIO *bio_c_out = NULL;
3679 int ret, err, infd, outfd;
3681 struct gcpro gcpro1, gcpro2;
3683 /* Make sure we have a process, the alive check should be done in the
3684 function calling this here */
3685 CHECK_PROCESS(process);
3687 GCPRO2(ssl_conn, process);
3689 /* set the alternate one */
3690 event_stream_unselect_process(XPROCESS(process));
3693 /* just announce that we are very binary */
3694 Fset_process_coding_system(process, Qbinary, Qbinary);
3697 /* initialise the process' buffer for type-specific data,
3698 * we will store process input there */
3699 XPROCESS(process)->process_type_data = Qnil;
3701 /* retrieve the sockets of the process */
3702 infd = get_process_infd(XPROCESS(process));
3703 outfd = get_process_outfd(XPROCESS(process));
3705 /* push data to ssl_conn */
3706 XSSLCONN(ssl_conn)->parent = process;
3707 XSSLCONN(ssl_conn)->infd = infd;
3708 XSSLCONN(ssl_conn)->outfd = outfd;
3710 /* frob vars from ssl_conn */
3711 conn = XSSLCONN(ssl_conn)->ssl_conn;
3712 bio = XSSLCONN(ssl_conn)->ssl_bio;
3714 /* initialise the main connection BIO */
3715 BIO_set_fd(bio, infd, 0);
3717 /* now perform the actual handshake
3718 * this is a loop because of the genuine openssl concept to not handle
3719 * non-blocking I/O correctly */
3723 ret = SSL_do_handshake(conn);
3724 err = SSL_get_error(conn, ret);
3726 /* perform select() with timeout
3727 * 1 second at the moment */
3731 if (err == SSL_ERROR_NONE) {
3733 } else if (err == SSL_ERROR_WANT_READ) {
3735 OSSL_DEBUG("WANT_READ\n");
3738 FD_SET(infd, &read_fds);
3740 /* wait for socket to be readable */
3741 if (!(ret = select(infd+1, &read_fds, 0, NULL, &to))) {
3743 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3744 error("timeout during handshake");
3747 } else if (err == SSL_ERROR_WANT_WRITE) {
3749 OSSL_DEBUG("WANT_WRITE\n");
3750 FD_ZERO(&write_fds);
3751 FD_SET(outfd, &write_fds);
3753 /* wait for socket to be writable */
3754 if (!(ret = select(infd+1, &write_fds, 0, NULL, &to))) {
3756 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3757 error("timeout during handshake");
3760 } else if (err == SSL_ERROR_SSL) {
3761 /* close down the process object */
3762 Fdelete_process(process);
3765 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3766 error("handshake failed");
3769 OSSL_CRITICAL("\nUnknown error: %d\n"
3771 "sxemacs-devel@sxemacs.org\n\n", err);
3774 /* we used to check whether the connection is
3775 still alive, but this was perhaps a bad idea */
3776 try = BIO_read(bio, buf, 2);
3778 (try < 0 && !BIO_should_retry(bio))) {
3779 /* Handle closed connection */
3780 XPROCESS(process)->exit_code = 256;
3781 XPROCESS(process)->status_symbol = Qexit;
3784 /* close down the process object */
3785 Fdelete_process(process);
3789 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
3790 error("unknown handshake error");
3795 /* marry the socket layer now */
3796 ossl_ssl_proselytise_process(ssl_conn, process);
3798 /* declare the whole pig connected */
3799 XSSLCONN(ssl_conn)->connected_p = 1;
3801 event_stream_select_process(XPROCESS(process));
3807 DEFUN("ossl-ssl-inject-cert", Fossl_ssl_inject_cert, 2, 3, 0, /*
3808 Add CERT as the local certificate of SSL-CONN.
3809 Optional argument KEY specifies a key file or evp-pkey, if
3810 CERT does not contain it.
3812 Both, CERT and KEY may be either a filename pointing to a
3813 PEM-encoded certificate and key respectively, or may be an
3816 (ssl_conn, cert, key))
3818 /* This function can GC */
3819 int (*fun)(Lisp_Object, Lisp_Object, Lisp_Object) = NULL;
3820 struct gcpro gcpro1, gcpro2, gcpro3;
3822 GCPRO3(ssl_conn, cert, key);
3824 CHECK_SSLCONN(ssl_conn);
3827 CHECK_EVPPKEY(cert);
3832 /* certificate and key preparation */
3833 if (STRINGP(cert)) {
3834 cert = Fexpand_file_name(cert, Qnil);
3835 if (NILP(Ffile_readable_p(cert)))
3840 key = Fexpand_file_name(key, Qnil);
3841 if (NILP(Ffile_readable_p(key)))
3845 if (STRINGP(cert) && NILP(key))
3847 else if (EVPPKEYP(cert) && NILP(key))
3850 /* certificate and key injection */
3851 if (!NILP(cert) && !NILP(key) &&
3852 STRINGP(cert) && STRINGP(key))
3853 fun = ossl_ssl_inject_cert_file;
3854 else if (!NILP(cert) && !NILP(key) &&
3855 EVPPKEYP(cert) && EVPPKEYP(key))
3856 fun = ossl_ssl_inject_cert;
3858 if (fun && fun(ssl_conn, cert, key)) {
3867 DEFUN("ossl-ssl-inject-ca", Fossl_ssl_inject_ca, 2, 2, 0, /*
3868 Add CA to the pile of certificate authorities of SSL-CONN.
3869 Also force a \(re\)verification of the remote peer certificate
3870 against CA. Return `t' if the injection was successful,
3873 CA may be either a file name pointing to a PEM-encoded
3874 CA certificate, or may be a directory containing a valid
3875 bunch of CA certificates according to OpenSSL's CA path
3876 layout, or may also be an evp-pkey object.
3880 /* This function can GC */
3881 int (*fun)(Lisp_Object, Lisp_Object) = NULL;
3883 struct gcpro gcpro1, gcpro2;
3885 GCPRO2(ssl_conn, ca);
3887 CHECK_SSLCONN(ssl_conn);
3893 ca = Fexpand_file_name(ca, Qnil);
3894 if (NILP(Ffile_readable_p(ca)))
3898 if (!NILP(ca) && STRINGP(ca)) {
3899 if (NILP(Ffile_directory_p(ca)))
3900 fun = ossl_ssl_inject_ca_file;
3902 fun = ossl_ssl_inject_ca_path;
3903 } else if (!NILP(ca) && EVPPKEYP(ca))
3904 fun = ossl_ssl_inject_ca;
3906 if (fun && fun(ssl_conn, ca) &&
3907 (conn = XSSLCONN(ssl_conn)->ssl_conn)) {
3908 ssl_verify_cert_chain(conn, SSL_get_peer_cert_chain(conn));
3917 DEFUN("ossl-ssl-handshake", Fossl_ssl_handshake, 1, 6, 0, /*
3918 Perform a handshake on the network connection PROCESS.
3920 Return a ssl-conn object, or `nil' if the handshake failed.
3921 In the latter case, most likely the remote site cannot handle
3922 the specified method, requires a client certificate, or cannot
3925 Optional argument METHOD indicates the SSL connection method,
3926 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
3928 Optional argument CA indicates a CA certificate.
3929 See `ossl-ssl-inject-ca'.
3931 Optional arguments CERT and KEY indicate a peer certificate
3932 and possibly a separate key file respectively.
3933 See `ossl-ssl-inject-peer-cert'.
3935 Optional argument SERVERP indicates whether to perform the
3936 handshake as a server if non-nil, and as a client otherwise.
3937 Note: In case of a handshake as server it is mandatory to provide
3938 a valid certificate and a corresponding key.
3940 (process, method, ca, cert, key, serverp))
3942 /* This function can GC */
3944 Lisp_Object ssl_conn, result;
3946 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
3948 GCPRO6(process, method, ca, cert, key, serverp);
3950 /* Make sure the process is really alive. */
3951 CHECK_PROCESS(process);
3952 OSSL_CHECK_PROCESS(process);
3954 /* create a ssl_conn object first */
3956 ssl_conn = ossl_ssl_prepare_cmeth(method);
3958 ssl_conn = ossl_ssl_prepare_smeth(method);
3960 /* create the context */
3961 ossl_ssl_prepare_ctx(ssl_conn);
3963 /* certificate and key preparation */
3964 Fossl_ssl_inject_cert(ssl_conn, cert, key);
3965 /* certificate authority preparation */
3966 Fossl_ssl_inject_ca(ssl_conn, ca);
3968 /* prepare for handshake */
3970 ossl_ssl_prepare(ssl_conn, SSL_set_connect_state);
3972 ossl_ssl_prepare(ssl_conn, SSL_set_accept_state);
3974 result = ossl_ssl_handshake(ssl_conn, process);
3980 DEFUN("ossl-ssl-connect", Fossl_ssl_connect, 0, MANY, 0, /*
3981 Perform a TLS or SSL handshake, return a ssl-conn object on
3982 success, or `nil' if the handshake failed.
3983 In the latter case, most likely the remote site cannot handle
3984 the specified method, requires a client certificate, or cannot
3995 Optional argument METHOD indicates the SSL connection method,
3996 it can be one of `tls1' \(default\), `ssl23', `ssl2', or `ssl3'.
3998 (int nargs, Lisp_Object *args))
4002 for (i = 0; i < nargs; i++);
4008 ossl_swap_process_streams(Lisp_SSL_CONN *s, Lisp_Process *p)
4010 Lisp_Object in, out;
4012 in = p->pipe_instream;
4013 out = p->pipe_outstream;
4015 p->pipe_instream = s->pipe_instream;
4016 p->pipe_outstream = s->pipe_outstream;
4018 s->pipe_instream = in;
4019 s->pipe_outstream = out;
4022 in = p->coding_instream;
4023 out = p->coding_outstream;
4025 p->coding_instream = s->coding_instream;
4026 p->coding_outstream = s->coding_outstream;
4028 s->coding_instream = in;
4029 s->coding_outstream = out;
4034 ossl_ssl_proselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4036 Lisp_Process *p = XPROCESS(process);
4037 Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4039 event_stream_unselect_process(p);
4041 /* put the streams we have in the ssl-conn object into the process
4042 object; actually these swap their places */
4043 if (p->process_type != PROCESS_TYPE_SSL)
4044 ossl_swap_process_streams(s, p);
4046 /* somehow we gotta link the network-process with the ss-layer
4047 * otherwise it'd be easy to open a network stream then
4048 * a ss-layer on top of it and then via `delete-process'
4049 * all the work is void while the ss-layer still exists
4051 p->process_type = PROCESS_TYPE_SSL;
4052 p->process_type_data = ssl_conn;
4054 event_stream_select_process(p);
4060 ossl_ssl_unproselytise_process(Lisp_Object ssl_conn, Lisp_Object process)
4062 Lisp_Process *p = XPROCESS(process);
4063 Lisp_SSL_CONN *s = XSSLCONN(ssl_conn);
4065 /* put the streams we have in the ssl-conn object into the process
4066 object (they should be the former process streams) */
4067 if (p->process_type == PROCESS_TYPE_SSL)
4068 ossl_swap_process_streams(s, p);
4070 /* somehow we gotta link the network-process with the ss-layer
4071 * otherwise it'd be easy to open a network stream then
4072 * a ss-layer on top of it and then via `delete-process'
4073 * all the work is void while the ss-layer still exists
4075 XPROCESS(process)->process_type = PROCESS_TYPE_NETWORK;
4076 XPROCESS(process)->process_type_data = Qnil;
4081 DEFUN("ossl-ssl-proselytise-process", Fossl_ssl_proselytise_process,
4083 Convert the underlying process of SSL-CONN into a secure
4084 network connection object.
4088 Lisp_Object process;
4090 CHECK_SSLCONN(ssl_conn);
4092 process = XSSLCONN(ssl_conn)->parent;
4093 if (!PROCESSP(process)) {
4094 error("no process associated with this connection");
4098 /* Make sure the process is really alive. */
4099 OSSL_CHECK_PROCESS(process);
4101 ossl_ssl_proselytise_process(ssl_conn, process);
4106 DEFUN("ossl-ssl-unproselytise-process", Fossl_ssl_unproselytise_process,
4108 Convert the underlying process of SSL-CONN into an ordinary
4109 network connection object.
4113 Lisp_Object process;
4115 CHECK_SSLCONN(ssl_conn);
4117 process = XSSLCONN(ssl_conn)->parent;
4118 if (!PROCESSP(process)) {
4119 error("no process associated with this connection");
4123 /* Make sure the process is really alive. */
4124 OSSL_CHECK_PROCESS(process);
4126 /* Castrate the process and make it a network process again */
4127 ossl_ssl_unproselytise_process(ssl_conn, process);
4132 DEFUN("ossl-ssl-finish", Fossl_ssl_finish, 1, 1, 0, /*
4133 Finish an SSL connection SSL-CONN.
4135 Note: This may also finish the network connection.
4139 Lisp_Object process;
4141 CHECK_SSLCONN(ssl_conn);
4143 if (XSSLCONN(ssl_conn)->protected_p)
4144 error ("Cannot finish protected SSL connection");
4146 process = XSSLCONN(ssl_conn)->parent;
4147 if (PROCESSP(process))
4148 ossl_ssl_unproselytise_process(ssl_conn, process);
4150 finalise_ssl_conn(XSSLCONN(ssl_conn), 0);
4154 DEFUN("ossl-ssl-read", Fossl_ssl_read, 2, 2, 0, /*
4155 Return the cleartext of STRING which is assumed to be a complete
4156 block of data sent through SSL-CONN.
4160 /* network stream stuff */
4162 Lisp_Object process;
4164 Lisp_Object result = Qnil;
4166 CHECK_SSLCONN(ssl_conn);
4167 CHECK_STRING(string);
4169 if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4170 error("SSL connection dead");
4172 conn = XSSLCONN(ssl_conn)->ssl_conn;
4173 process = XSSLCONN(ssl_conn)->parent;
4175 /* Make sure the process is really alive. */
4176 OSSL_CHECK_PROCESS(process);
4181 DEFUN("ossl-ssl-write", Fossl_ssl_write, 2, 2, 0, /*
4182 Send STRING to the tunnel SSL-CONN.
4186 /* network stream stuff */
4188 Lisp_Object process, proc_filter;
4193 CHECK_SSLCONN(ssl_conn);
4194 CHECK_STRING(string);
4196 if (!ssl_conn_alive_p(XSSLCONN(ssl_conn)))
4197 error("SSL connection dead");
4199 conn = XSSLCONN(ssl_conn)->ssl_conn;
4200 process = XSSLCONN(ssl_conn)->parent;
4202 /* Make sure the process is really alive. */
4203 OSSL_CHECK_PROCESS(process);
4205 switch (XPROCESS(process)->process_type) {
4206 case PROCESS_TYPE_NETWORK:
4207 /* ssl streams reside in ssl-conn object atm */
4208 out = XLSTREAM(DATA_OUTSTREAM(XSSLCONN(ssl_conn)));
4210 case PROCESS_TYPE_SSL:
4211 /* ssl streams reside in process object, snarf from there */
4212 out = XLSTREAM(DATA_OUTSTREAM(XPROCESS(process)));
4216 error("unable to write");
4219 /* store the original process filter */
4220 proc_filter = XPROCESS(process)->filter;
4222 ret = Lstream_write(out, XSTRING_DATA(string), XSTRING_LENGTH(string));
4225 switch (SSL_get_error(conn, ret)) {
4226 case SSL_ERROR_NONE:
4228 case SSL_ERROR_WANT_WRITE:
4229 error("Connection wants write");
4230 case SSL_ERROR_WANT_READ:
4231 error("Connection wants read");
4233 error("Severe SSL connection error");
4236 /* restore the original process filter */
4237 return (SSL_pending(conn) == 0) ? Qt : Qnil;
4240 /* convenience functions */
4241 DEFUN("ossl-ssl-parent", Fossl_ssl_parent, 1, 1, 0, /*
4242 Return the underlying parent layer of SSL-CONN.
4246 CHECK_SSLCONN(ssl_conn);
4248 return XSSLCONN(ssl_conn)->parent;
4251 DEFUN("ossl-ssl-cert", Fossl_ssl_cert, 1, 1, 0, /*
4252 Return the local peer's certificate of SSL-CONN if present,
4257 /* SSL connection stuff */
4261 CHECK_SSLCONN(ssl_conn);
4263 conn = XSSLCONN(ssl_conn)->ssl_conn;
4264 cert = SSL_get_certificate(conn);
4267 return make_evp_pkey_x509(cert);
4272 DEFUN("ossl-ssl-peer-cert", Fossl_ssl_peer_cert, 1, 1, 0, /*
4273 Return the remote peer's certificate of SSL-CONN if present,
4278 /* SSL connection stuff */
4282 CHECK_SSLCONN(ssl_conn);
4284 conn = XSSLCONN(ssl_conn)->ssl_conn;
4285 cert = SSL_get_peer_certificate(conn);
4288 return make_evp_pkey_x509(cert);
4293 DEFUN("ossl-ssl-peer-cert-chain", Fossl_ssl_peer_cert_chain, 1, 1, 0, /*
4294 Return the certificate chain of SSL-CONN as a list of
4300 /* SSL connection stuff */
4304 Lisp_Object result = Qnil;
4306 CHECK_SSLCONN(ssl_conn);
4308 conn = XSSLCONN(ssl_conn)->ssl_conn;
4309 sk = SSL_get_peer_cert_chain(conn);
4314 for (i=0; i<sk_X509_num(sk); i++) {
4315 X509 *cert = sk_X509_value(sk, i);
4317 result = Fcons(make_evp_pkey_x509(cert), result);
4324 DEFUN("ossl-ssl-cert-store", Fossl_ssl_cert_store, 1, 1, 0, /*
4325 Return the X509 cert store of SSL-CONN.
4329 X509_STORE *sto = NULL;
4335 #if 0 /* just thoughts */
4336 int SSL_get_verify_mode(const SSL *s);
4337 int SSL_get_verify_depth(const SSL *s);
4340 DEFUN("ossl-ssl-verify-certificate", Fossl_ssl_verify_certificate,
4342 Return a verify code of SSL-CONN.
4344 The result is a cons cell with the numeric verify code in
4345 the car and a verbose string in the cdr.
4350 /* SSL connection stuff */
4353 Lisp_Object result = Qnil;
4355 CHECK_SSLCONN(ssl_conn);
4357 conn = XSSLCONN(ssl_conn)->ssl_conn;
4358 vrc = SSL_get_verify_result(conn);
4362 build_string(X509_verify_cert_error_string(vrc)));
4367 DEFUN("ossl-ssl-cipher-version", Fossl_ssl_cipher_version, 1, 1, 0, /*
4368 Return the protocol version of the tunnel SSL-CONN.
4372 /* SSL connection stuff */
4375 /* network stream stuff */
4376 Lisp_SSL_CONN *lisp_ssl_conn;
4378 CHECK_SSLCONN(ssl_conn);
4379 lisp_ssl_conn = XSSLCONN(ssl_conn);
4381 conn = lisp_ssl_conn->ssl_conn;
4385 ciph = SSL_get_current_cipher(conn);
4387 if (!(ciph == NULL))
4388 return Fmake_symbol(
4389 build_string(SSL_CIPHER_get_version(ciph)));
4394 DEFUN("ossl-ssl-cipher-name", Fossl_ssl_cipher_name, 1, 1, 0, /*
4395 Return the name of the current cipher used in the tunnel SSL-CONN.
4399 /* SSL connection stuff */
4402 /* network stream stuff */
4403 Lisp_SSL_CONN *lisp_ssl_conn;
4405 CHECK_SSLCONN(ssl_conn);
4406 lisp_ssl_conn = XSSLCONN(ssl_conn);
4408 conn = lisp_ssl_conn->ssl_conn;
4412 ciph = SSL_get_current_cipher(conn);
4414 if (!(ciph == NULL))
4415 return intern(SSL_CIPHER_get_name(ciph));
4420 DEFUN("ossl-ssl-cipher-names", Fossl_ssl_cipher_names, 1, 1, 0, /*
4421 Return the names of all supported ciphers in the tunnel SSL-CONN.
4426 /* SSL connection stuff */
4428 STACK_OF(SSL_CIPHER) *ciphs;
4429 Lisp_Object result = Qnil;
4431 CHECK_SSLCONN(ssl_conn);
4433 conn = XSSLCONN(ssl_conn)->ssl_conn;
4437 ciphs = SSL_get_ciphers(conn);
4439 for (i=sk_SSL_CIPHER_num(ciphs)-1; i>=0; i--) {
4440 SSL_CIPHER *ciph = sk_SSL_CIPHER_value(ciphs, i);
4442 result = Fcons(intern(SSL_CIPHER_get_name(ciph)), result);
4448 DEFUN("ossl-ssl-cipher-bits", Fossl_ssl_cipher_bits, 1, 1, 0, /*
4449 Return the number of effective bits of the current cipher in SSL-CONN.
4453 /* SSL connection stuff */
4456 int alg_bits, strength_bits;
4457 /* network stream stuff */
4458 Lisp_SSL_CONN *lisp_ssl_conn;
4460 CHECK_SSLCONN(ssl_conn);
4461 lisp_ssl_conn = XSSLCONN(ssl_conn);
4463 conn = lisp_ssl_conn->ssl_conn;
4467 ciph = SSL_get_current_cipher(conn);
4469 if (!(ciph == NULL)) {
4470 strength_bits = SSL_CIPHER_get_bits(ciph, &alg_bits);
4471 /* what do we want to do with alg_bits? */
4472 return make_int(strength_bits);
4477 DEFUN("ossl-ssl-cipher-description", Fossl_ssl_cipher_description, 1, 1, 0, /*
4478 Return a description of the current cipher used in the tunnel SSL-CONN.
4482 /* SSL connection stuff */
4485 /* network stream stuff */
4486 Lisp_SSL_CONN *lisp_ssl_conn;
4488 CHECK_SSLCONN(ssl_conn);
4489 lisp_ssl_conn = XSSLCONN(ssl_conn);
4491 conn = lisp_ssl_conn->ssl_conn;
4495 ciph = SSL_get_current_cipher(conn);
4497 if (!(ciph == NULL))
4498 return build_string(SSL_CIPHER_description(ciph, NULL, 0));
4504 /* X509 cert handling */
4505 DEFUN("ossl-x509-subject", Fossl_x509_subject, 1, 1, 0, /*
4506 Return the certificate subject of CERT (an evp-pkey object).
4508 This will return a string in LDAP syntax.
4514 CHECK_EVPPKEY(cert);
4516 pk509 = XEVPPKEY(cert)->x509;
4519 X509_NAME *sub = X509_get_subject_name(pk509);
4520 return build_string(X509_NAME_oneline(sub, NULL, 0));
4525 DEFUN("ossl-x509-issuer", Fossl_x509_issuer, 1, 1, 0, /*
4526 Return the certificate issuer of CERT (an evp-pkey object),
4527 that is the organisation which signed the certificate.
4529 This will return a string in LDAP syntax.
4535 CHECK_EVPPKEY(cert);
4537 pk509 = XEVPPKEY(cert)->x509;
4540 X509_NAME *iss = X509_get_issuer_name(pk509);
4541 return build_string(X509_NAME_oneline(iss, NULL, 0));
4546 DEFUN("ossl-x509-serial", Fossl_x509_serial, 1, 1, 0, /*
4547 Return the certificate serial of CERT (an evp-pkey object).
4553 CHECK_EVPPKEY(cert);
4555 pk509 = XEVPPKEY(cert)->x509;
4558 ASN1_INTEGER *ser = X509_get_serialNumber(pk509);
4559 return make_integer(ASN1_INTEGER_get(ser));
4564 DEFUN("ossl-x509-not-before", Fossl_x509_not_before, 1, 1, 0, /*
4565 Return the certificate valid-not-before time of CERT.
4571 CHECK_EVPPKEY(cert);
4573 pk509 = XEVPPKEY(cert)->x509;
4576 ASN1_TIME *nbf = X509_get_notBefore(pk509);
4577 return build_string((char*)nbf->data);
4582 DEFUN("ossl-x509-not-after", Fossl_x509_not_after, 1, 1, 0, /*
4583 Return the certificate valid-not-after time of CERT.
4589 CHECK_EVPPKEY(cert);
4591 pk509 = XEVPPKEY(cert)->x509;
4594 ASN1_TIME *nbf = X509_get_notAfter(pk509);
4595 return build_string((char*)nbf->data);
4600 DEFUN("ossl-x509-signature-type", Fossl_x509_signature_type, 1, 1, 0, /*
4601 Return the signature type of CERT.
4607 CHECK_EVPPKEY(cert);
4609 pk509 = XEVPPKEY(cert)->x509;
4612 int ty = X509_get_signature_type(pk509);
4613 Lisp_Object result = Qnil;
4617 result = intern("none");
4619 #ifndef OPENSSL_NO_RSA
4621 result = intern("rsa");
4624 result = intern("rsa2");
4627 #ifndef OPENSSL_NO_DSA
4629 result = intern("dsa");
4632 result = intern("dsa1");
4635 result = intern("dsa2");
4638 result = intern("dsa3");
4641 result = intern("dsa4");
4644 #ifndef OPENSSL_NO_DH
4646 result = intern("dh");
4649 #ifndef OPENSSL_NO_EC
4651 result = intern("ec");
4655 result = intern("unknown");
4670 * Initialisation stuff
4673 void syms_of_openssl(void)
4675 INIT_LRECORD_IMPLEMENTATION(evp_pkey);
4676 INIT_LRECORD_IMPLEMENTATION(ssl_conn);
4678 defsymbol(&Qopenssl, "openssl");
4679 defsymbol(&Qevp_pkeyp, "ossl-pkey-p");
4681 DEFSUBR(Fossl_version);
4682 DEFSUBR(Fossl_available_digests);
4683 DEFSUBR(Fossl_available_ciphers);
4684 DEFSUBR(Fossl_digest_size);
4685 DEFSUBR(Fossl_digest_bits);
4686 DEFSUBR(Fossl_digest_block_size);
4687 DEFSUBR(Fossl_cipher_key_length);
4688 DEFSUBR(Fossl_cipher_bits);
4689 DEFSUBR(Fossl_cipher_iv_length);
4690 DEFSUBR(Fossl_cipher_block_size);
4691 DEFSUBR(Fossl_cipher_mode);
4693 DEFSUBR(Fossl_rand_bytes);
4694 DEFSUBR(Fossl_rand_bytes_egd);
4696 DEFSUBR(Fossl_digest);
4697 DEFSUBR(Fossl_digest_file);
4699 DEFSUBR(Fossl_hmac);
4700 DEFSUBR(Fossl_hmac_file);
4702 DEFSUBR(Fossl_bytes_to_key);
4703 DEFSUBR(Fossl_encrypt);
4704 DEFSUBR(Fossl_encrypt_file);
4705 DEFSUBR(Fossl_decrypt);
4706 DEFSUBR(Fossl_decrypt_file);
4709 DEFSUBR(Fossl_pkey_p);
4710 DEFSUBR(Fossl_pkey_size);
4711 DEFSUBR(Fossl_pkey_private_p);
4712 DEFSUBR(Fossl_pkey_get_public);
4714 #ifndef OPENSSL_NO_RSA
4716 DEFSUBR(Fossl_rsa_generate_key);
4717 DEFSUBR(Fossl_rsa_pkey_p);
4718 DEFSUBR(Fossl_rsa_subkey_p);
4719 #endif /* OPENSSL_NO_RSA */
4720 #ifndef OPENSSL_NO_DSA
4722 DEFSUBR(Fossl_dsa_generate_key);
4723 DEFSUBR(Fossl_dsa_pkey_p);
4724 DEFSUBR(Fossl_dsa_subkey_p);
4725 #endif /* OPENSSL_NO_DSA */
4726 #ifndef OPENSSL_NO_EC
4728 DEFSUBR(Fossl_ec_available_curves);
4729 DEFSUBR(Fossl_ec_generate_key);
4730 DEFSUBR(Fossl_ec_pkey_p);
4731 #endif /* OPENSSL_NO_EC */
4732 #ifndef OPENSSL_NO_DH
4734 /* DEFSUBR(Fossl_ec_generate_key); */
4735 DEFSUBR(Fossl_dh_pkey_p);
4737 DEFSUBR(Fossl_seal);
4738 DEFSUBR(Fossl_open);
4740 DEFSUBR(Fossl_sign);
4741 DEFSUBR(Fossl_verify);
4744 DEFSUBR(Fossl_pem_read_public_key);
4745 DEFSUBR(Fossl_pem_read_key);
4746 DEFSUBR(Fossl_pem_write_public_key);
4747 DEFSUBR(Fossl_pem_write_key);
4748 DEFSUBR(Fossl_pem_public_key);
4749 DEFSUBR(Fossl_pem_key);
4752 defsymbol(&Qssl_connp, "ossl-ssl-conn-p");
4753 defsymbol(&Qssl2, "ssl2");
4754 defsymbol(&Qssl23, "ssl23");
4755 defsymbol(&Qssl3, "ssl3");
4756 defsymbol(&Qtls1, "tls1");
4758 DEFSUBR(Fossl_ssl_handshake);
4759 DEFSUBR(Fossl_ssl_inject_ca);
4760 DEFSUBR(Fossl_ssl_inject_cert);
4761 DEFSUBR(Fossl_ssl_proselytise_process);
4762 DEFSUBR(Fossl_ssl_unproselytise_process);
4763 DEFSUBR(Fossl_ssl_connect);
4764 DEFSUBR(Fossl_ssl_finish);
4765 DEFSUBR(Fossl_ssl_read);
4766 DEFSUBR(Fossl_ssl_write);
4767 DEFSUBR(Fossl_ssl_parent);
4768 DEFSUBR(Fossl_ssl_cert);
4769 DEFSUBR(Fossl_ssl_peer_cert);
4770 DEFSUBR(Fossl_ssl_peer_cert_chain);
4771 DEFSUBR(Fossl_ssl_verify_certificate);
4772 DEFSUBR(Fossl_ssl_cipher_version);
4773 DEFSUBR(Fossl_ssl_cipher_name);
4774 DEFSUBR(Fossl_ssl_cipher_names);
4775 DEFSUBR(Fossl_ssl_cipher_bits);
4776 DEFSUBR(Fossl_ssl_cipher_description);
4779 DEFSUBR(Fossl_x509_subject);
4780 DEFSUBR(Fossl_x509_issuer);
4781 DEFSUBR(Fossl_x509_serial);
4782 DEFSUBR(Fossl_x509_not_before);
4783 DEFSUBR(Fossl_x509_not_after);
4784 DEFSUBR(Fossl_x509_signature_type);
4787 void vars_of_openssl(void)
4791 #ifndef OPENSSL_NO_RSA
4792 Fprovide(intern("openssl-rsa"));
4794 #ifndef OPENSSL_NO_DSA
4795 Fprovide(intern("openssl-dsa"));
4797 #ifndef OPENSSL_NO_EC
4798 Fprovide(intern("openssl-ec"));
4800 #ifndef OPENSSL_NO_DH
4801 Fprovide(intern("openssl-dh"));
4804 Fprovide(intern("openssl-ssl"));