14ee2ad04344446e610172a0e73949212923014dfSebastian Redl/* crypto/engine/eng_openssl.c */
22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * project 2000.
42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor */
52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* ====================================================================
62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * Redistribution and use in source and binary forms, with or without
92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * modification, are permitted provided that the following conditions
10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl * are met:
112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * 1. Redistributions of source code must retain the above copyright
132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *    notice, this list of conditions and the following disclaimer.
147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redl *
150eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis * 2. Redistributions in binary form must reproduce the above copyright
16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor *    notice, this list of conditions and the following disclaimer in
17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor *    the documentation and/or other materials provided with the
182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *    distribution.
192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * 3. All advertising materials mentioning features or use of this
212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall *    software must display the following acknowledgment:
220b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor *    "This product includes software developed by the OpenSSL Project
237a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
25a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
266ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl *    endorse or promote products derived from this software without
277c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner *    prior written permission. For written permission, please contact
286a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor *    licensing@OpenSSL.org.
297c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner *
3083d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff * 5. Products derived from this software may not be called "OpenSSL"
3114f79002e58556798e86168c63e48d533287eda5Douglas Gregor *    nor may "OpenSSL" appear in their names without prior written
323251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor *    permission of the OpenSSL Project.
3314f79002e58556798e86168c63e48d533287eda5Douglas Gregor *
34bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor * 6. Redistributions of any form whatsoever must retain the following
352bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor *    acknowledgment:
36ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor *    "This product includes software developed by the OpenSSL Project
3717fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3817fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor *
392596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4114f79002e58556798e86168c63e48d533287eda5Douglas Gregor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42b64c19365deab788753d29c9bc881253c3f16f37Douglas Gregor * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
433c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
458538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
462cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * OF THE POSSIBILITY OF SUCH DAMAGE.
51ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * ====================================================================
52ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl *
53ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * This product includes cryptographic software written by Eric Young
54ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * (eay@cryptsoft.com).  This product includes software written by Tim
55ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl * Hudson (tjh@cryptsoft.com).
562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *
572cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor */
582cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* ====================================================================
5912b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * ECDH support in OpenSSL originally developed by
613397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl */
63a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl
642cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <stdio.h>
662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/crypto.h>
678538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#include "cryptlib.h"
682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/engine.h>
693397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#include <openssl/dso.h>
708538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#include <openssl/pem.h>
712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/evp.h>
722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/rand.h>
732cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef OPENSSL_NO_RSA
742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/rsa.h>
752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef OPENSSL_NO_DSA
772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/dsa.h>
782cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef OPENSSL_NO_DH
802cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/dh.h>
812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
823397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* This testing gunk is implemented (and explained) lower down. It also assumes
842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * the application explicitly calls "ENGINE_load_openssl()" because this is no
852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * longer automatic in ENGINE_load_builtin_engines(). */
863397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#define TEST_ENG_OPENSSL_RC4
872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#define TEST_ENG_OPENSSL_PKEY
888538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl/* #define TEST_ENG_OPENSSL_RC4_OTHERS */
892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#define TEST_ENG_OPENSSL_RC4_P_INIT
902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */
913397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#define TEST_ENG_OPENSSL_SHA
922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* #define TEST_ENG_OPENSSL_SHA_OTHERS */
938538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl/* #define TEST_ENG_OPENSSL_SHA_P_INIT */
942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */
952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */
963397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/* Now check what of those algorithms are actually enabled */
988538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#ifdef OPENSSL_NO_RC4
992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#undef TEST_ENG_OPENSSL_RC4
1002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#undef TEST_ENG_OPENSSL_RC4_OTHERS
1013397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#undef TEST_ENG_OPENSSL_RC4_P_INIT
1022cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#undef TEST_ENG_OPENSSL_RC4_P_CIPHER
1038538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif
1042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#if defined(OPENSSL_NO_SHA) || defined(OPENSSL_NO_SHA0) || defined(OPENSSL_NO_SHA1)
1052cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#undef TEST_ENG_OPENSSL_SHA
1063397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#undef TEST_ENG_OPENSSL_SHA_OTHERS
1072cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#undef TEST_ENG_OPENSSL_SHA_P_INIT
1088538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#undef TEST_ENG_OPENSSL_SHA_P_UPDATE
1092cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#undef TEST_ENG_OPENSSL_SHA_P_FINAL
1102cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1113397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#ifdef TEST_ENG_OPENSSL_RC4
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpstatic int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
1148538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl				const int **nids, int nid);
1152cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifdef TEST_ENG_OPENSSL_SHA
1173397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlstatic int openssl_digests(ENGINE *e, const EVP_MD **digest,
1182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor				const int **nids, int nid);
1192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1200953e767ff7817f97b3ab20896b229891eeff45bJohn McCall
1212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifdef TEST_ENG_OPENSSL_PKEY
1222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
1233397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	UI_METHOD *ui_method, void *callback_data);
1242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1268538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl/* The constants used when creating the ENGINE */
1272cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic const char *engine_openssl_id = "openssl";
1282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic const char *engine_openssl_name = "Software engine support";
1293397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl
1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* This internal function is used by ENGINE_openssl() and possibly by the
1318538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl * "dynamic" ENGINE support too */
1322cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic int bind_helper(ENGINE *e)
1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	{
1343397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	if(!ENGINE_set_id(e, engine_openssl_id)
1352cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_name(e, engine_openssl_name)
1367e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS
1377e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor#ifndef OPENSSL_NO_RSA
138c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor			|| !ENGINE_set_RSA(e, RSA_get_default_method())
1398538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif
1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef OPENSSL_NO_DSA
1412cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_DSA(e, DSA_get_default_method())
1423397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#endif
1432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifndef OPENSSL_NO_ECDH
1442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_ECDH(e, ECDH_OpenSSL())
145788b0fd67e1992f23555454efcdb16a19dfefac3Chris Lattner#endif
1468538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#ifndef OPENSSL_NO_ECDSA
1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_ECDSA(e, ECDSA_OpenSSL())
1482cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1493397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#ifndef OPENSSL_NO_DH
1502cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_DH(e, DH_get_default_method())
1518538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif
1522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_RAND(e, RAND_SSLeay())
1532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifdef TEST_ENG_OPENSSL_RC4
1543397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl			|| !ENGINE_set_ciphers(e, openssl_ciphers)
1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
156264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola#ifdef TEST_ENG_OPENSSL_SHA
157264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola			|| !ENGINE_set_digests(e, openssl_digests)
158425ef72306d4ff6b3698b744353e5f0e56b4b884Rafael Espindola#endif
159ab8bbf4ebd3e3e6eab913cb044772a62b7581941Douglas Gregor#endif
160264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola#ifdef TEST_ENG_OPENSSL_PKEY
1612cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor			|| !ENGINE_set_load_privkey_function(e, openssl_load_privkey)
1622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
1633397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl			)
1642cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor		return 0;
1658538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	/* If we add errors to this ENGINE, ensure the error handling is setup here */
1662cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	/* openssl_load_error_strings(); */
1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	return 1;
1683397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	}
1692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1702cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic ENGINE *engine_openssl(void)
1712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	{
1722cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	ENGINE *ret = ENGINE_new();
1732cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	if(!ret)
1742cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor		return NULL;
175465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl	if(!bind_helper(ret))
176465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl		{
177465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl		ENGINE_free(ret);
178465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl		return NULL;
179465226e23a3008bd68973513dda1f9e3cd27dbddSebastian Redl		}
1808538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	return ret;
1812cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	}
1822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1833397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlvoid ENGINE_load_openssl(void)
184ed97649e9574b9d854fa4d6109c9333ae0993554John McCall	{
1858538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	ENGINE *toadd = engine_openssl();
186ed97649e9574b9d854fa4d6109c9333ae0993554John McCall	if(!toadd) return;
187ed97649e9574b9d854fa4d6109c9333ae0993554John McCall	ENGINE_add(toadd);
1883397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	/* If the "add" worked, it gets a structural reference. So either way,
1892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	 * we release our just-created reference. */
1909763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis	ENGINE_free(toadd);
1919763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis	ERR_clear_error();
1928538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	}
1932cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
1942cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor/* This stuff is needed if this ENGINE is being compiled into a self-contained
1953397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl * shared-library. */
196c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor#ifdef ENGINE_DYNAMIC_SUPPORT
1978538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlstatic int bind_fn(ENGINE *e, const char *id)
1982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	{
1992cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	if(id && (strcmp(id, engine_openssl_id) != 0))
2003397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl		return 0;
2012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	if(!bind_helper(e))
2028538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl		return 0;
2032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	return 1;
2042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	}
2053397c5570369f19b2d6c52e898f708d75ceede1fSebastian RedlIMPLEMENT_DYNAMIC_CHECK_FN()
206395b475a4474f1c7574d927ad142ca0c7997cbcaAnders CarlssonIMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
2078538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif /* ENGINE_DYNAMIC_SUPPORT */
208395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson
209395b475a4474f1c7574d927ad142ca0c7997cbcaAnders Carlsson#ifdef TEST_ENG_OPENSSL_RC4
2103397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl/* This section of code compiles an "alternative implementation" of two modes of
211be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4"
2122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor * should under normal circumstances go via this support rather than the default
2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump * EVP support. There are other symbols to tweak the testing;
2142cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *    TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time
2152cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *        we're asked for a cipher we don't support (should not happen).
2162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *    TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time
2173397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl *        the "init_key" handler is called.
2182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor *    TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler.
2198538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl */
2202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include <openssl/rc4.h>
2212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#define TEST_RC4_KEY_SIZE		16
2223397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlstatic int test_cipher_nids[] = {NID_rc4,NID_rc4_40};
2232cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic int test_cipher_nids_number = 2;
2248538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redltypedef struct {
2252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	unsigned char key[TEST_RC4_KEY_SIZE];
2262cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	RC4_KEY ks;
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump	} TEST_RC4_KEY;
2283397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#define test(ctx) ((TEST_RC4_KEY *)(ctx)->cipher_data)
22949a832bd499d6f61c23655f1fac99f0dd229756eJohn McCallstatic int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
23049a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall			const unsigned char *iv, int enc)
23149a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall	{
2328538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#ifdef TEST_ENG_OPENSSL_RC4_P_INIT
23349a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall	fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n");
23449a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall#endif
23549a832bd499d6f61c23655f1fac99f0dd229756eJohn McCall	memcpy(&test(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx));
2363397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	RC4_set_key(&test(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),
2372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor		test(ctx)->key);
238be191100e034b23a3e13053757a57b7f5068c24aArgyrios Kyrtzidis	return 1;
23990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	}
24090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidisstatic int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
24190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis		      const unsigned char *in, size_t inl)
24290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	{
24390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis#ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER
2449763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis	fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n");
2459763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis#endif
2469763e221e16026ddf487d2564ed349d2c874a1a1Argyrios Kyrtzidis	RC4(&test(ctx)->ks,inl,in,out);
2478538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	return 1;
24890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	}
24990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidisstatic const EVP_CIPHER test_r4_cipher=
25090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	{
2513397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	NID_rc4,
252ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis	1,TEST_RC4_KEY_SIZE,0,
253ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis	EVP_CIPH_VARIABLE_LENGTH,
254ae8b17f1d5d303af53db5a4f4a375ea6b9356566Argyrios Kyrtzidis	test_rc4_init_key,
2558538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	test_rc4_cipher,
25690b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
25790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	sizeof(TEST_RC4_KEY),
25890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
2593397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	NULL,
26090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
26190b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL
26290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	};
26390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidisstatic const EVP_CIPHER test_r4_40_cipher=
26490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	{
26590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NID_rc4_40,
2663397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	1,5 /* 40 bit */,0,
26790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	EVP_CIPH_VARIABLE_LENGTH,
26890b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	test_rc4_init_key,
26990b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	test_rc4_cipher,
27090b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
2718538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	sizeof(TEST_RC4_KEY),
27290b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
27390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
27490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	NULL,
2753397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	NULL
2768dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis	};
2778dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidisstatic int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
2788dfbd8b252ba4e6cf4b7a3422f6ef0ca21312dfeArgyrios Kyrtzidis			const int **nids, int nid)
279f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis	{
280f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis	if(!cipher)
281f48d45e3e36c132bdee3373beec4e8b19ae3f9c4Argyrios Kyrtzidis		{
2828538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl		/* We are returning a list of supported nids */
28390b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis		*nids = test_cipher_nids;
28490b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis		return test_cipher_nids_number;
28590b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis		}
2863397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	/* We are being asked for a specific cipher */
28790b715e0df34eae2b50b9b43ec60828ed31dcf94Argyrios Kyrtzidis	if(nid == NID_rc4)
2883acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis		*cipher = &test_r4_cipher;
2893acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis	else if(nid == NID_rc4_40)
2903acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis		*cipher = &test_r4_40_cipher;
2913acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis	else
2923acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis		{
2933acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis#ifdef TEST_ENG_OPENSSL_RC4_OTHERS
2943acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis		fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for "
2958538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl				"nid %d\n", nid);
2962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#endif
2972cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor		*cipher = NULL;
2983397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl		return 0;
299465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara		}
3003acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis	return 1;
3013acad62a239448bef0f5848b2a0d5f7dfefd3d14Argyrios Kyrtzidis	}
3028538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif
3032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor
3042cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifdef TEST_ENG_OPENSSL_SHA
3053397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */
3063cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall#include <openssl/sha.h>
30731f17ecbef57b5679c017c375db330546b7b5145John McCallstatic int test_digest_nids[] = {NID_sha1};
3088538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlstatic int test_digest_nids_number = 1;
3093cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCallstatic int test_sha1_init(EVP_MD_CTX *ctx)
3103cb0ebd5f76abcb776f7cb4062bd79e3268c0dc4John McCall	{
3113397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl#ifdef TEST_ENG_OPENSSL_SHA_P_INIT
312deacbdca554298ccdf636f19c6094a8825ec6b34Douglas Gregor	fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n");
3138538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl#endif
314c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall	return SHA1_Init(ctx->md_data);
315c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall	}
3163397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redlstatic int test_sha1_update(EVP_MD_CTX *ctx,const void *data,size_t count)
317c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall	{
3182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE
319c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall	fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n");
320446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff#endif
321446ee4eb4fc4c705a59365252df7a5c253daafa1Steve Naroff	return SHA1_Update(ctx->md_data,data,count);
3228538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	}
3232cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic int test_sha1_final(EVP_MD_CTX *ctx,unsigned char *md)
3242cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	{
325d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff#ifdef TEST_ENG_OPENSSL_SHA_P_FINAL
3263397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl	fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n");
3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#endif
3288538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl	return SHA1_Final(md,ctx->md_data);
3292cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor	}
3302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorstatic const EVP_MD test_sha_md=
331a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	{
332a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	NID_sha1,
333a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	NID_sha1WithRSAEncryption,
334a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl	SHA_DIGEST_LENGTH,
335a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl	0,
336a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	test_sha1_init,
337a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	test_sha1_update,
338a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl	test_sha1_final,
339a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	NULL,
340a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	NULL,
34151bd803fbdade51d674598ed45da3d54190a656cJohn McCall	EVP_PKEY_RSA_method,
342a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	SHA_CBLOCK,
34351bd803fbdade51d674598ed45da3d54190a656cJohn McCall	sizeof(EVP_MD *)+sizeof(SHA_CTX),
344a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	};
345a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallstatic int openssl_digests(ENGINE *e, const EVP_MD **digest,
34651bd803fbdade51d674598ed45da3d54190a656cJohn McCall			const int **nids, int nid)
34751bd803fbdade51d674598ed45da3d54190a656cJohn McCall	{
348a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall	if(!digest)
349a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall		{
350a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall		/* We are returning a list of supported nids */
351a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCall		*nids = test_digest_nids;
35251bd803fbdade51d674598ed45da3d54190a656cJohn McCall		return test_digest_nids_number;
35351bd803fbdade51d674598ed45da3d54190a656cJohn McCall		}
35451bd803fbdade51d674598ed45da3d54190a656cJohn McCall	/* We are being asked for a specific digest */
35551bd803fbdade51d674598ed45da3d54190a656cJohn McCall	if(nid == NID_sha1)
356ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor		*digest = &test_sha_md;
357ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor	else
358ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor		{
359ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor#ifdef TEST_ENG_OPENSSL_SHA_OTHERS
360ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor		fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for "
361ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor				"nid %d\n", nid);
362ddf889a2ad2888f1dea573987bbe952d9912c1a0Douglas Gregor#endif
36351bd803fbdade51d674598ed45da3d54190a656cJohn McCall		*digest = NULL;
36451bd803fbdade51d674598ed45da3d54190a656cJohn McCall		return 0;
36551bd803fbdade51d674598ed45da3d54190a656cJohn McCall		}
36651bd803fbdade51d674598ed45da3d54190a656cJohn McCall	return 1;
36751bd803fbdade51d674598ed45da3d54190a656cJohn McCall	}
36851bd803fbdade51d674598ed45da3d54190a656cJohn McCall#endif
36951bd803fbdade51d674598ed45da3d54190a656cJohn McCall
37051bd803fbdade51d674598ed45da3d54190a656cJohn McCall#ifdef TEST_ENG_OPENSSL_PKEY
37151bd803fbdade51d674598ed45da3d54190a656cJohn McCallstatic EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
37251bd803fbdade51d674598ed45da3d54190a656cJohn McCall	UI_METHOD *ui_method, void *callback_data)
37351bd803fbdade51d674598ed45da3d54190a656cJohn McCall	{
37451bd803fbdade51d674598ed45da3d54190a656cJohn McCall	BIO *in;
37551bd803fbdade51d674598ed45da3d54190a656cJohn McCall	EVP_PKEY *key;
37651bd803fbdade51d674598ed45da3d54190a656cJohn McCall	fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", key_id);
37751bd803fbdade51d674598ed45da3d54190a656cJohn McCall	in = BIO_new_file(key_id, "r");
37851bd803fbdade51d674598ed45da3d54190a656cJohn McCall	if (!in)
37951bd803fbdade51d674598ed45da3d54190a656cJohn McCall		return NULL;
38051bd803fbdade51d674598ed45da3d54190a656cJohn McCall	key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
38151bd803fbdade51d674598ed45da3d54190a656cJohn McCall	BIO_free(in);
38251bd803fbdade51d674598ed45da3d54190a656cJohn McCall	return key;
38351bd803fbdade51d674598ed45da3d54190a656cJohn McCall	}
38451bd803fbdade51d674598ed45da3d54190a656cJohn McCall#endif
38551bd803fbdade51d674598ed45da3d54190a656cJohn McCall