summaryrefslogtreecommitdiffstats
path: root/crypto/openssl/demos
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2003-01-28 21:43:22 +0000
committermarkm <markm@FreeBSD.org>2003-01-28 21:43:22 +0000
commitaad1d64cb5a8d9b503d9199642363dc1e92d2f9b (patch)
tree610a51c6e3965764fb0f1629c1376e2d23afffe8 /crypto/openssl/demos
parenteba366e36e93f5da8ae5c744eb337c3ef6872641 (diff)
downloadFreeBSD-src-aad1d64cb5a8d9b503d9199642363dc1e92d2f9b.zip
FreeBSD-src-aad1d64cb5a8d9b503d9199642363dc1e92d2f9b.tar.gz
Vendor import of OpenSSL release 0.9.7. This release includes
support for AES and OpenBSD's hardware crypto.
Diffstat (limited to 'crypto/openssl/demos')
-rw-r--r--crypto/openssl/demos/asn1/README.ASN17
-rw-r--r--crypto/openssl/demos/asn1/ocsp.c366
-rw-r--r--crypto/openssl/demos/b64.c2
-rw-r--r--crypto/openssl/demos/bio/saccept.c5
-rw-r--r--crypto/openssl/demos/bio/sconnect.c5
-rw-r--r--crypto/openssl/demos/easy_tls/Makefile123
-rw-r--r--crypto/openssl/demos/easy_tls/README65
-rw-r--r--crypto/openssl/demos/easy_tls/cacerts.pem18
-rw-r--r--crypto/openssl/demos/easy_tls/cert.pem31
-rw-r--r--crypto/openssl/demos/easy_tls/easy-tls.c1240
-rw-r--r--crypto/openssl/demos/easy_tls/easy-tls.h57
-rw-r--r--crypto/openssl/demos/easy_tls/test.c244
-rw-r--r--crypto/openssl/demos/easy_tls/test.h11
-rw-r--r--crypto/openssl/demos/engines/cluster_labs/Makefile114
-rw-r--r--crypto/openssl/demos/engines/cluster_labs/cluster_labs.h35
-rw-r--r--crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.c721
-rw-r--r--crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.ec8
-rw-r--r--crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.c151
-rw-r--r--crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.h95
-rw-r--r--crypto/openssl/demos/engines/ibmca/Makefile114
-rw-r--r--crypto/openssl/demos/engines/ibmca/hw_ibmca.c920
-rw-r--r--crypto/openssl/demos/engines/ibmca/hw_ibmca.ec8
-rw-r--r--crypto/openssl/demos/engines/ibmca/hw_ibmca_err.c154
-rw-r--r--crypto/openssl/demos/engines/ibmca/hw_ibmca_err.h98
-rw-r--r--crypto/openssl/demos/engines/ibmca/ica_openssl_api.h189
-rw-r--r--crypto/openssl/demos/engines/rsaref/Makefile135
-rw-r--r--crypto/openssl/demos/engines/rsaref/README22
-rw-r--r--crypto/openssl/demos/engines/rsaref/build.com85
-rw-r--r--crypto/openssl/demos/engines/rsaref/rsaref.c685
-rw-r--r--crypto/openssl/demos/engines/rsaref/rsaref.ec8
-rw-r--r--crypto/openssl/demos/engines/rsaref/rsaref_err.c161
-rw-r--r--crypto/openssl/demos/engines/rsaref/rsaref_err.h109
-rw-r--r--crypto/openssl/demos/engines/zencod/Makefile114
-rw-r--r--crypto/openssl/demos/engines/zencod/hw_zencod.c1739
-rw-r--r--crypto/openssl/demos/engines/zencod/hw_zencod.ec8
-rw-r--r--crypto/openssl/demos/engines/zencod/hw_zencod.h160
-rw-r--r--crypto/openssl/demos/engines/zencod/hw_zencod_err.c151
-rw-r--r--crypto/openssl/demos/engines/zencod/hw_zencod_err.h95
-rw-r--r--crypto/openssl/demos/maurice/example1.c6
-rw-r--r--crypto/openssl/demos/maurice/example3.c6
-rw-r--r--crypto/openssl/demos/maurice/loadkeys.c9
-rw-r--r--crypto/openssl/demos/sign/sign.c4
-rw-r--r--crypto/openssl/demos/spkigen.c3
-rw-r--r--crypto/openssl/demos/ssl/cli.cpp4
-rw-r--r--crypto/openssl/demos/ssl/inetdsrv.cpp4
-rw-r--r--crypto/openssl/demos/ssl/serv.cpp4
-rw-r--r--crypto/openssl/demos/state_machine/state_machine.c47
-rw-r--r--crypto/openssl/demos/tunala/A-client.pem84
-rw-r--r--crypto/openssl/demos/tunala/A-server.pem84
-rw-r--r--crypto/openssl/demos/tunala/CA.pem24
-rw-r--r--crypto/openssl/demos/tunala/INSTALL107
-rw-r--r--crypto/openssl/demos/tunala/Makefile41
-rw-r--r--crypto/openssl/demos/tunala/Makefile.am7
-rw-r--r--crypto/openssl/demos/tunala/README233
-rwxr-xr-xcrypto/openssl/demos/tunala/autogunk.sh25
-rwxr-xr-xcrypto/openssl/demos/tunala/autoungunk.sh18
-rw-r--r--crypto/openssl/demos/tunala/breakage.c66
-rw-r--r--crypto/openssl/demos/tunala/buffer.c205
-rw-r--r--crypto/openssl/demos/tunala/cb.c133
-rw-r--r--crypto/openssl/demos/tunala/configure.in28
-rw-r--r--crypto/openssl/demos/tunala/ip.c146
-rw-r--r--crypto/openssl/demos/tunala/sm.c151
-rw-r--r--crypto/openssl/demos/tunala/tunala.c1093
-rw-r--r--crypto/openssl/demos/tunala/tunala.h214
-rw-r--r--crypto/openssl/demos/x509/README3
-rw-r--r--crypto/openssl/demos/x509/mkcert.c168
-rw-r--r--crypto/openssl/demos/x509/mkreq.c157
67 files changed, 11290 insertions, 37 deletions
diff --git a/crypto/openssl/demos/asn1/README.ASN1 b/crypto/openssl/demos/asn1/README.ASN1
new file mode 100644
index 0000000..ac497be
--- /dev/null
+++ b/crypto/openssl/demos/asn1/README.ASN1
@@ -0,0 +1,7 @@
+This is a demo of the new ASN1 code. Its an OCSP ASN1 module. Doesn't
+do much yet other than demonstrate what the new ASN1 modules might look
+like.
+
+It wont even compile yet: the new code isn't in place.
+
+
diff --git a/crypto/openssl/demos/asn1/ocsp.c b/crypto/openssl/demos/asn1/ocsp.c
new file mode 100644
index 0000000..0199fe1
--- /dev/null
+++ b/crypto/openssl/demos/asn1/ocsp.c
@@ -0,0 +1,366 @@
+/* ocsp.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509v3.h>
+
+
+
+
+/* Example of new ASN1 code, OCSP request
+
+ OCSPRequest ::= SEQUENCE {
+ tbsRequest TBSRequest,
+ optionalSignature [0] EXPLICIT Signature OPTIONAL }
+
+ TBSRequest ::= SEQUENCE {
+ version [0] EXPLICIT Version DEFAULT v1,
+ requestorName [1] EXPLICIT GeneralName OPTIONAL,
+ requestList SEQUENCE OF Request,
+ requestExtensions [2] EXPLICIT Extensions OPTIONAL }
+
+ Signature ::= SEQUENCE {
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING,
+ certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+
+ Version ::= INTEGER { v1(0) }
+
+ Request ::= SEQUENCE {
+ reqCert CertID,
+ singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL }
+
+ CertID ::= SEQUENCE {
+ hashAlgorithm AlgorithmIdentifier,
+ issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ issuerKeyHash OCTET STRING, -- Hash of Issuers public key
+ serialNumber CertificateSerialNumber }
+
+ OCSPResponse ::= SEQUENCE {
+ responseStatus OCSPResponseStatus,
+ responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+
+ OCSPResponseStatus ::= ENUMERATED {
+ successful (0), --Response has valid confirmations
+ malformedRequest (1), --Illegal confirmation request
+ internalError (2), --Internal error in issuer
+ tryLater (3), --Try again later
+ --(4) is not used
+ sigRequired (5), --Must sign the request
+ unauthorized (6) --Request unauthorized
+ }
+
+ ResponseBytes ::= SEQUENCE {
+ responseType OBJECT IDENTIFIER,
+ response OCTET STRING }
+
+ BasicOCSPResponse ::= SEQUENCE {
+ tbsResponseData ResponseData,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING,
+ certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+
+ ResponseData ::= SEQUENCE {
+ version [0] EXPLICIT Version DEFAULT v1,
+ responderID ResponderID,
+ producedAt GeneralizedTime,
+ responses SEQUENCE OF SingleResponse,
+ responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+
+ ResponderID ::= CHOICE {
+ byName [1] Name, --EXPLICIT
+ byKey [2] KeyHash }
+
+ KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ --(excluding the tag and length fields)
+
+ SingleResponse ::= SEQUENCE {
+ certID CertID,
+ certStatus CertStatus,
+ thisUpdate GeneralizedTime,
+ nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+
+ CertStatus ::= CHOICE {
+ good [0] IMPLICIT NULL,
+ revoked [1] IMPLICIT RevokedInfo,
+ unknown [2] IMPLICIT UnknownInfo }
+
+ RevokedInfo ::= SEQUENCE {
+ revocationTime GeneralizedTime,
+ revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+
+ UnknownInfo ::= NULL -- this can be replaced with an enumeration
+
+ ArchiveCutoff ::= GeneralizedTime
+
+ AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER
+
+ ServiceLocator ::= SEQUENCE {
+ issuer Name,
+ locator AuthorityInfoAccessSyntax }
+
+ -- Object Identifiers
+
+ id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
+ id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp }
+ id-pkix-ocsp-basic OBJECT IDENTIFIER ::= { id-pkix-ocsp 1 }
+ id-pkix-ocsp-nonce OBJECT IDENTIFIER ::= { id-pkix-ocsp 2 }
+ id-pkix-ocsp-crl OBJECT IDENTIFIER ::= { id-pkix-ocsp 3 }
+ id-pkix-ocsp-response OBJECT IDENTIFIER ::= { id-pkix-ocsp 4 }
+ id-pkix-ocsp-nocheck OBJECT IDENTIFIER ::= { id-pkix-ocsp 5 }
+ id-pkix-ocsp-archive-cutoff OBJECT IDENTIFIER ::= { id-pkix-ocsp 6 }
+ id-pkix-ocsp-service-locator OBJECT IDENTIFIER ::= { id-pkix-ocsp 7 }
+
+*/
+
+/* Request Structures */
+
+DECLARE_STACK_OF(Request)
+
+typedef struct {
+ ASN1_INTEGER *version;
+ GENERAL_NAME *requestorName;
+ STACK_OF(Request) *requestList;
+ STACK_OF(X509_EXTENSION) *requestExtensions;
+} TBSRequest;
+
+typedef struct {
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+} Signature;
+
+typedef struct {
+ TBSRequest *tbsRequest;
+ Signature *optionalSignature;
+} OCSPRequest;
+
+typedef struct {
+ X509_ALGOR *hashAlgorithm;
+ ASN1_OCTET_STRING *issuerNameHash;
+ ASN1_OCTET_STRING *issuerKeyHash;
+ ASN1_INTEGER *certificateSerialNumber;
+} CertID;
+
+typedef struct {
+ CertID *reqCert;
+ STACK_OF(X509_EXTENSION) *singleRequestExtensions;
+} Request;
+
+/* Response structures */
+
+typedef struct {
+ ASN1_OBJECT *responseType;
+ ASN1_OCTET_STRING *response;
+} ResponseBytes;
+
+typedef struct {
+ ASN1_ENUMERATED *responseStatus;
+ ResponseBytes *responseBytes;
+} OCSPResponse;
+
+typedef struct {
+ int type;
+ union {
+ X509_NAME *byName;
+ ASN1_OCTET_STRING *byKey;
+ }d;
+} ResponderID;
+
+typedef struct {
+ ASN1_INTEGER *version;
+ ResponderID *responderID;
+ ASN1_GENERALIZEDTIME *producedAt;
+ STACK_OF(SingleResponse) *responses;
+ STACK_OF(X509_EXTENSION) *responseExtensions;
+} ResponseData;
+
+typedef struct {
+ ResponseData *tbsResponseData;
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+} BasicOCSPResponse;
+
+typedef struct {
+ ASN1_GENERALIZEDTIME *revocationTime;
+ ASN1_ENUMERATED * revocationReason;
+} RevokedInfo;
+
+typedef struct {
+ int type;
+ union {
+ ASN1_NULL *good;
+ RevokedInfo *revoked;
+ ASN1_NULL *unknown;
+ } d;
+} CertStatus;
+
+typedef struct {
+ CertID *certID;
+ CertStatus *certStatus;
+ ASN1_GENERALIZEDTIME *thisUpdate;
+ ASN1_GENERALIZEDTIME *nextUpdate;
+ STACK_OF(X509_EXTENSION) *singleExtensions;
+} SingleResponse;
+
+
+typedef struct {
+ X509_NAME *issuer;
+ STACK_OF(ACCESS_DESCRIPTION) *locator;
+} ServiceLocator;
+
+
+/* Now the ASN1 templates */
+
+IMPLEMENT_COMPAT_ASN1(X509);
+IMPLEMENT_COMPAT_ASN1(X509_ALGOR);
+//IMPLEMENT_COMPAT_ASN1(X509_EXTENSION);
+IMPLEMENT_COMPAT_ASN1(GENERAL_NAME);
+IMPLEMENT_COMPAT_ASN1(X509_NAME);
+
+ASN1_SEQUENCE(X509_EXTENSION) = {
+ ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
+ ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
+ ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(X509_EXTENSION);
+
+
+ASN1_SEQUENCE(Signature) = {
+ ASN1_SIMPLE(Signature, signatureAlgorithm, X509_ALGOR),
+ ASN1_SIMPLE(Signature, signature, ASN1_BIT_STRING),
+ ASN1_SEQUENCE_OF(Signature, certs, X509)
+} ASN1_SEQUENCE_END(Signature);
+
+ASN1_SEQUENCE(CertID) = {
+ ASN1_SIMPLE(CertID, hashAlgorithm, X509_ALGOR),
+ ASN1_SIMPLE(CertID, issuerNameHash, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(CertID, issuerKeyHash, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(CertID, certificateSerialNumber, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(CertID);
+
+ASN1_SEQUENCE(Request) = {
+ ASN1_SIMPLE(Request, reqCert, CertID),
+ ASN1_EXP_SEQUENCE_OF_OPT(Request, singleRequestExtensions, X509_EXTENSION, 0)
+} ASN1_SEQUENCE_END(Request);
+
+ASN1_SEQUENCE(TBSRequest) = {
+ ASN1_EXP_OPT(TBSRequest, version, ASN1_INTEGER, 0),
+ ASN1_EXP_OPT(TBSRequest, requestorName, GENERAL_NAME, 1),
+ ASN1_SEQUENCE_OF(TBSRequest, requestList, Request),
+ ASN1_EXP_SEQUENCE_OF_OPT(TBSRequest, requestExtensions, X509_EXTENSION, 2)
+} ASN1_SEQUENCE_END(TBSRequest);
+
+ASN1_SEQUENCE(OCSPRequest) = {
+ ASN1_SIMPLE(OCSPRequest, tbsRequest, TBSRequest),
+ ASN1_EXP_OPT(OCSPRequest, optionalSignature, Signature, 0)
+} ASN1_SEQUENCE_END(OCSPRequest);
+
+
+/* Response templates */
+
+ASN1_SEQUENCE(ResponseBytes) = {
+ ASN1_SIMPLE(ResponseBytes, responseType, ASN1_OBJECT),
+ ASN1_SIMPLE(ResponseBytes, response, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(ResponseBytes);
+
+ASN1_SEQUENCE(OCSPResponse) = {
+ ASN1_SIMPLE(OCSPResponse, responseStatus, ASN1_ENUMERATED),
+ ASN1_EXP_OPT(OCSPResponse, responseBytes, ResponseBytes, 0)
+} ASN1_SEQUENCE_END(OCSPResponse);
+
+ASN1_CHOICE(ResponderID) = {
+ ASN1_EXP(ResponderID, d.byName, X509_NAME, 1),
+ ASN1_IMP(ResponderID, d.byKey, ASN1_OCTET_STRING, 2)
+} ASN1_CHOICE_END(ResponderID);
+
+ASN1_SEQUENCE(RevokedInfo) = {
+ ASN1_SIMPLE(RevokedInfo, revocationTime, ASN1_GENERALIZEDTIME),
+ ASN1_EXP_OPT(RevokedInfo, revocationReason, ASN1_ENUMERATED, 0)
+} ASN1_SEQUENCE_END(RevokedInfo);
+
+ASN1_CHOICE(CertStatus) = {
+ ASN1_IMP(CertStatus, d.good, ASN1_NULL, 0),
+ ASN1_IMP(CertStatus, d.revoked, RevokedInfo, 1),
+ ASN1_IMP(CertStatus, d.unknown, ASN1_NULL, 2)
+} ASN1_CHOICE_END(CertStatus);
+
+ASN1_SEQUENCE(SingleResponse) = {
+ ASN1_SIMPLE(SingleResponse, certID, CertID),
+ ASN1_SIMPLE(SingleResponse, certStatus, CertStatus),
+ ASN1_SIMPLE(SingleResponse, thisUpdate, ASN1_GENERALIZEDTIME),
+ ASN1_EXP_OPT(SingleResponse, nextUpdate, ASN1_GENERALIZEDTIME, 0),
+ ASN1_EXP_SEQUENCE_OF_OPT(SingleResponse, singleExtensions, X509_EXTENSION, 1)
+} ASN1_SEQUENCE_END(SingleResponse);
+
+ASN1_SEQUENCE(ResponseData) = {
+ ASN1_EXP_OPT(ResponseData, version, ASN1_INTEGER, 0),
+ ASN1_SIMPLE(ResponseData, responderID, ResponderID),
+ ASN1_SIMPLE(ResponseData, producedAt, ASN1_GENERALIZEDTIME),
+ ASN1_SEQUENCE_OF(ResponseData, responses, SingleResponse),
+ ASN1_EXP_SEQUENCE_OF_OPT(ResponseData, responseExtensions, X509_EXTENSION, 1)
+} ASN1_SEQUENCE_END(ResponseData);
+
+ASN1_SEQUENCE(BasicOCSPResponse) = {
+ ASN1_SIMPLE(BasicOCSPResponse, tbsResponseData, ResponseData),
+ ASN1_SIMPLE(BasicOCSPResponse, signatureAlgorithm, X509_ALGOR),
+ ASN1_SIMPLE(BasicOCSPResponse, signature, ASN1_BIT_STRING),
+ ASN1_EXP_SEQUENCE_OF_OPT(BasicOCSPResponse, certs, X509, 0)
+} ASN1_SEQUENCE_END(BasicOCSPResponse);
+
diff --git a/crypto/openssl/demos/b64.c b/crypto/openssl/demos/b64.c
index 113da89..efdd444 100644
--- a/crypto/openssl/demos/b64.c
+++ b/crypto/openssl/demos/b64.c
@@ -83,7 +83,6 @@ char **argv;
unsigned char *buff=NULL,*bufsize=NULL;
int bsize=BSIZE,verbose=0;
int ret=1,inl;
- unsigned char key[24],iv[MD5_DIGEST_LENGTH];
char *str=NULL;
char *hkey=NULL,*hiv=NULL;
int enc=1,printkey=0,i,base64=0;
@@ -92,7 +91,6 @@ char **argv;
char *inf=NULL,*outf=NULL;
BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL;
#define PROG_NAME_SIZE 39
- char pname[PROG_NAME_SIZE+1];
apps_startup();
diff --git a/crypto/openssl/demos/bio/saccept.c b/crypto/openssl/demos/bio/saccept.c
index 933d669..40cd4da 100644
--- a/crypto/openssl/demos/bio/saccept.c
+++ b/crypto/openssl/demos/bio/saccept.c
@@ -45,6 +45,11 @@ char *argv[];
SSL_load_error_strings();
+#ifdef WATT32
+ dbug_init();
+ sock_init();
+#endif
+
/* Add ciphers and message digests */
OpenSSL_add_ssl_algorithms();
diff --git a/crypto/openssl/demos/bio/sconnect.c b/crypto/openssl/demos/bio/sconnect.c
index 87b380b..880344e 100644
--- a/crypto/openssl/demos/bio/sconnect.c
+++ b/crypto/openssl/demos/bio/sconnect.c
@@ -32,6 +32,11 @@ char *argv[];
else
host=argv[1];
+#ifdef WATT32
+ dbug_init();
+ sock_init();
+#endif
+
/* Lets get nice error messages */
SSL_load_error_strings();
diff --git a/crypto/openssl/demos/easy_tls/Makefile b/crypto/openssl/demos/easy_tls/Makefile
new file mode 100644
index 0000000..2080700
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/Makefile
@@ -0,0 +1,123 @@
+# Makefile for easy-tls example application (rudimentary client and server)
+# $Id: Makefile,v 1.2 2001/09/18 09:15:40 bodo Exp $
+
+SOLARIS_CFLAGS=-Wall -pedantic -g -O2
+SOLARIS_LIBS=-lxnet
+
+LINUX_CFLAGS=-Wall -pedantic -g -O2
+LINUX_LIBS=
+
+
+auto-all:
+ case `uname -s` in \
+ SunOS) echo Using SunOS configuration; \
+ make SYSCFLAGS="$(SOLARIS_CFLAGS)" SYSLIBS="$(SOLARIS_LIBS)" all;; \
+ Linux) echo Using Linux configuration; \
+ make SYSCFLAGS="$(LINUX_CFLAGS)" SYSLIBS="$(LINUX_LIBS)" all;; \
+ *) echo "unknown system"; exit 1;; \
+ esac
+
+all: test TAGS
+
+# For adapting this Makefile to a different system, only the following
+# definitions should need customizing:
+
+OPENSSLDIR=../..
+CC=gcc
+
+SYSCFLAGS=whatever
+SYSLIBS=whatever
+
+
+#############################################################################
+#
+# SSLeay/OpenSSL imports
+#
+# OPENSSLDIR (set above) can be either the directory where OpenSSL is
+# installed or the directory where it was compiled.
+
+# We rely on having a new OpenSSL release where include files
+# have names like <openssl/ssl.h> (not just <ssl.h>).
+OPENSSLINCLUDES=-I$(OPENSSLDIR)/include
+
+# libcrypto.a and libssl.a are directly in $(OPENSSLDIR) if this is
+# the compile directory, or in $(OPENSSLDIR)/lib if we use an installed
+# library. With the following definition, we can handle either case.
+OPENSSLLIBS=-L$(OPENSSLDIR) -L$(OPENSSLDIR)/lib -lssl -lcrypto
+
+
+#############################################################################
+#
+# Stuff for handling the source files
+#
+
+SOURCES=easy-tls.c test.c
+HEADERS=easy-tls.h test.h
+DOCSandEXAMPLESetc=Makefile cert.pem cacerts.pem
+EVERYTHING=$(SOURCES) $(HEADERS) $(DOCSandEXAMPLESetc)
+
+ls: ls-l
+ls-l:
+ ls -l $(EVERYTHING)
+# For RCS:
+tag:
+ -rcs -n_`date +%y%m%d`: $(EVERYTHING)
+ rcs -nMYTAG $(EVERYTHING)
+ rcs -nMYTAG: $(EVERYTHING)
+diff:
+ -rcsdiff -rMYTAG -u $(EVERYTHING)
+today:
+ -rcsdiff -r_`date +%y%m%d` -u $(EVERYTHING)
+ident:
+ for a in $(EVERYTHING); do ident $$a; done
+
+# Distribution .tar:
+easy-tls.tar.gz: $(EVERYTHING)
+ tar cvf - $(EVERYTHING) | \
+ gzip -9 > easy-tls.tar.gz
+
+# Working .tar:
+tls.tgz: $(EVERYTHING)
+ tar cfv - `find . -type f -a ! -name '*.tgz' -a ! -name '*.tar.gz'` | \
+ gzip -9 > tls.tgz
+
+# For emacs:
+etags: TAGS
+TAGS: $(SOURCES) $(HEADERS)
+ -etags $(SOURCES) $(HEADERS)
+
+
+#############################################################################
+#
+# Compilation
+#
+# The following definitions are system dependent (and hence defined
+# at the beginning of this Makefile, where they are more easily found):
+
+### CC=gcc
+### SYSCFLAGS=-Wall -pedantic -g -O2
+### SYSLIBS=-lxnet
+
+EXTRACFLAGS=-DTLS_APP=\"test.h\"
+# EXTRACFLAGS=-DTLS_APP=\"test.h\" -DDEBUG_TLS
+
+#
+# The rest shouldn't need to be touched.
+#
+LDFLAGS=$(SYSLIBS) $(OPENSSLLIBS)
+INCLUDES=$(OPENSSLINCLUDES)
+CFLAGS=$(SYSCFLAGS) $(EXTRACFLAGS) $(INCLUDES)
+
+OBJS=easy-tls.o test.o
+
+clean:
+ @rm -f test
+ @rm -f TAGS
+ @rm -f *.o
+ @rm -f core
+
+test: $(OBJS)
+ $(CC) $(OBJS) $(LDFLAGS) -o test
+
+test.o: $(HEADERS)
+easy-tls.o: $(HEADERS)
diff --git a/crypto/openssl/demos/easy_tls/README b/crypto/openssl/demos/easy_tls/README
new file mode 100644
index 0000000..816a580
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/README
@@ -0,0 +1,65 @@
+easy_tls - generic SSL/TLS proxy
+========
+
+(... and example for non-blocking SSL/TLS I/O multiplexing.)
+
+
+ easy_tls.c, easy_tls.h:
+
+ Small generic SSL/TLS proxy library: With a few function calls,
+ an application socket will be replaced by a pipe handled by a
+ separate SSL/TLS proxy process. This allows easily adding
+ SSL/TLS support to many programs not originally designed for it.
+
+ [Actually easy_tls.c is not a proper library: Customization
+ requires defining preprocessor macros while compiling it.
+ This is quite confusing, so I'll probably change it.]
+
+ These files may be used under the OpenSSL license.
+
+
+
+ test.c, test.h, Makefile, cert.pem, cacerts.pem:
+
+ Rudimentary example program using the easy_tls library, and
+ example key and certificates for it. Usage examples:
+
+ $ ./test 8443 # create server listening at port 8443
+ $ ./test 127.0.0.1 8443 # create client, connect to port 8443
+ # at IP address 127.0.0.1
+
+ 'test' will not automatically do SSL/TLS, or even read or write
+ data -- it must be told to do so on input lines starting
+ with a command letter. 'W' means write a line, 'R' means
+ read a line, 'C' means close the connection, 'T' means
+ start an SSL/TLS proxy. E.g. (user input tagged with '*'):
+
+ * R
+ <<< 220 mail.example.net
+ * WSTARTTLS
+ >>> STARTTLS
+ * R
+ <<< 220 Ready to start TLS
+ * T
+ test_process_init(fd = 3, client_p = 1, apparg = (nil))
+ +++ `E:self signed certificate in certificate chain'
+ +++ `<... certificate info ...>'
+ * WHELO localhost
+ >>> HELO localhost
+ R
+ <<< 250 mail.example.net
+
+ You can even do SSL/TLS over SSL/TLS over SSL/TLS ... by using
+ 'T' multiple times. I have no idea why you would want to though.
+
+
+This code is rather old. When I find time I will update anything that
+should be changed, and improve code comments. To compile the sample
+program 'test' on platforms other then Linux or Solaris, you will have
+to edit the Makefile.
+
+As noted above, easy_tls.c will be changed to become a library one
+day, which means that future revisions will not be fully compatible to
+the current version.
+
+Bodo Möller <bodo@openssl.org>
diff --git a/crypto/openssl/demos/easy_tls/cacerts.pem b/crypto/openssl/demos/easy_tls/cacerts.pem
new file mode 100644
index 0000000..acc70ba
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/cacerts.pem
@@ -0,0 +1,18 @@
+$Id: cacerts.pem,v 1.1 2001/09/17 19:06:57 bodo Exp $
+
+issuer= /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test PCA (1024 bit)
+subject=/C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit)
+-----BEGIN CERTIFICATE-----
+MIICJjCCAY8CAQAwDQYJKoZIhvcNAQEEBQAwXDELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRwwGgYD
+VQQDExNUZXN0IFBDQSAoMTAyNCBiaXQpMB4XDTk3MDYwOTEzNTc0M1oXDTAxMDYw
+OTEzNTc0M1owWzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClF1ZWVuc2xhbmQxGjAY
+BgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYDVQQDExJUZXN0IENBICgxMDI0
+IGJpdCkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKO7o8t116VP6cgybTsZ
+DCZhr95nYlZuya3aCi1IKoztqwWnjbmDFIriOqGFPrZQ+moMETC9D59iRW/dFXSv
+1F65ka/XY2hLh9exCCo7XuUcDs53Qp3bI3AmMqHjgzE8oO3ajyJAzJkTTOUecQU2
+mw/gI4tMM0LqWMQS7luTy4+xAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAM7achv3v
+hLQJcv/65eGEpBXM40ZDVoFQFFJWaY5p883HTqLB1x4FdzsXHH0QKBTcKpWwqyu4
+YDm3fb8oDugw72bCzfyZK/zVZPR/hVlqI/fvU109Qoc+7oPvIXWky71HfcK6ZBCA
+q30KIqGM/uoM60INq97qjDmCJapagcNBGQs=
+-----END CERTIFICATE-----
diff --git a/crypto/openssl/demos/easy_tls/cert.pem b/crypto/openssl/demos/easy_tls/cert.pem
new file mode 100644
index 0000000..364fe10
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/cert.pem
@@ -0,0 +1,31 @@
+$Id: cert.pem,v 1.1 2001/09/17 19:06:57 bodo Exp $
+
+Example certificate and key.
+
+-----BEGIN CERTIFICATE-----
+MIIB1jCCAT8CAQEwDQYJKoZIhvcNAQEEBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
+ZDAeFw05OTA1MDEwMTI2MzVaFw05OTA1MzEwMTI2MzVaMCIxCzAJBgNVBAYTAkRF
+MRMwEQYDVQQDEwpUZXN0c2VydmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQD6I3oDKiexwwlkzjar69AIFnVUaG85LtCege2R+CtIDlkQYw68/8MbT3ou0pdF
+AcL9IGiYY3Y0SHM9PqF00RO1MCtNpqTnF3ScLpbmggGjKilmWYn2ai7emdjMjXVL
+tzWW2xGgIGATWQN32KgfJng4jXi1UjEiyLhkw0Zf1I/ggwIDAQABMA0GCSqGSIb3
+DQEBBAUAA4GBAMgM+sbAk8DfjSfa+Rf2gcGXmbrvZAzKzC+5RU3kaq/NyxIXAGco
+9dZjozzWfN/xuGup5boFk+KrP+xdgsaqGHsyzlgEoqz4ekqLjQeVbnoj339hVFU9
+MhPi6JULPxjXKumjfX2LLNkikW5puz8Df3UiX0EiaJvd7EwP8J75tiUT
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQD6I3oDKiexwwlkzjar69AIFnVUaG85LtCege2R+CtIDlkQYw68
+/8MbT3ou0pdFAcL9IGiYY3Y0SHM9PqF00RO1MCtNpqTnF3ScLpbmggGjKilmWYn2
+ai7emdjMjXVLtzWW2xGgIGATWQN32KgfJng4jXi1UjEiyLhkw0Zf1I/ggwIDAQAB
+AoGANST8c1etf1MU19oIO5aqaE19OCXIG7oakNLCCtVTPMfvnE+vffBJH7BPIUuU
+4BBzwRv1nQrkvk72TPjVjOAu81B1SStKQueun2flVuYxp9NyupNWCBley4QdohlP
+I92ml2tzTSPmNIoA6jdGyNzFcGchapRRmejsC39F1RUbHQECQQD9KX81Wt8ZOrri
+dWiEXja1L3X8Bkb9vvUjVMQDTJJPxBJjehC6eurgE6PP6SJD5p/f3RHPCcLr8tSM
+D4P/OpKhAkEA/PFNlhIZUDKK6aTvG2mn7qQ5phbadOoyN1Js3ttWG5OMOZ6b/QlC
+Wvp84h44506BIlv+Tg2YAI0AdBUrf7oEowJAM4joAVd/ROaEtqbJ4PBA2L9RmD06
+5FqkEk4mHLnQqvYx/BgUIbH18ClvVlqSBBqFfw/EmU3WZSuogt6Bs0ocIQJBAOxB
+AoPiYcxbeQ5kZIVJOXaX49SzUdaUDNVJYrEBUzsspHQJJo/Avz606kJVkjbSR6Ft
+JWmIHuqcyMikIV4KxFsCQQCU2evoVjVsqkkbHi7W28f73PGBsyu0KIwlK7nu4h08
+Daf7TAI+A6jW/WRUsJ6dFhUYi7/Jvkcdrlnbgm2fxziX
+-----END RSA PRIVATE KEY-----
diff --git a/crypto/openssl/demos/easy_tls/easy-tls.c b/crypto/openssl/demos/easy_tls/easy-tls.c
new file mode 100644
index 0000000..9c1d982
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/easy-tls.c
@@ -0,0 +1,1240 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+/*
+ * easy-tls.c -- generic TLS proxy.
+ * $Id: easy-tls.c,v 1.2.2.2 2002/03/05 09:06:57 bodo Exp $
+ */
+/*
+ (c) Copyright 1999 Bodo Moeller. All rights reserved.
+
+ This is free software; you can redistributed and/or modify it
+ unter the terms of either
+ - the GNU General Public License as published by the
+ Free Software Foundation, version 1, or (at your option)
+ any later version,
+ or
+ - the following license:
+*/
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that each of the following
+ * conditions is met:
+ *
+ * 1. Redistributions qualify as "freeware" or "Open Source Software" under
+ * one of the following terms:
+ *
+ * (a) Redistributions are made at no charge beyond the reasonable cost of
+ * materials and delivery.
+ *
+ * (b) Redistributions are accompanied by a copy of the Source Code
+ * or by an irrevocable offer to provide a copy of the Source Code
+ * for up to three years at the cost of materials and delivery.
+ * Such redistributions must allow further use, modification, and
+ * redistribution of the Source Code under substantially the same
+ * terms as this license.
+ *
+ * 2. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 3. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 4. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by Bodo Moeller."
+ * (If available, substitute umlauted o for oe.)
+ *
+ * 5. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by Bodo Moeller."
+ *
+ * THIS SOFTWARE IS PROVIDED BY BODO MOELLER ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BODO MOELLER OR
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Attribution for OpenSSL library:
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ * This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)
+ */
+
+static char const rcsid[] =
+"$Id: easy-tls.c,v 1.2.2.2 2002/03/05 09:06:57 bodo Exp $";
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include <openssl/crypto.h>
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/opensslv.h>
+#include <openssl/pem.h>
+#include <openssl/rand.h>
+#ifndef NO_RSA
+ #include <openssl/rsa.h>
+#endif
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x00904000L /* 0.9.4-dev */
+# error "This program needs OpenSSL 0.9.4 or later."
+#endif
+
+#include "easy-tls.h" /* include after <openssl/ssl.h> if both are needed */
+
+#if TLS_INFO_SIZE > PIPE_BUF
+# if PIPE_BUF < 512
+# error "PIPE_BUF < 512" /* non-POSIX */
+# endif
+# error "TLS_INFO_SIZE > PIPE_BUF"
+#endif
+
+/*****************************************************************************/
+
+#ifdef TLS_APP
+# include TLS_APP
+#endif
+
+/* Applications can define:
+ * TLS_APP_PROCESS_INIT -- void ...(int fd, int client_p, void *apparg)
+ * TLS_CUMULATE_ERRORS
+ * TLS_ERROR_BUFSIZ
+ * TLS_APP_ERRFLUSH -- void ...(int child_p, char *, size_t, void *apparg)
+ */
+
+#ifndef TLS_APP_PROCESS_INIT
+# define TLS_APP_PROCESS_INIT(fd, client_p, apparg) ((void) 0)
+#endif
+
+#ifndef TLS_ERROR_BUFSIZ
+# define TLS_ERROR_BUFSIZ (10*160)
+#endif
+#if TLS_ERROR_BUFSIZ < 2 /* {'\n',0} */
+# error "TLS_ERROR_BUFSIZE is too small."
+#endif
+
+#ifndef TLS_APP_ERRFLUSH
+# define TLS_APP_ERRFLUSH tls_app_errflush
+static void
+tls_app_errflush(int child_p, char *errbuf, size_t num, void *apparg)
+{
+ fputs(errbuf, stderr);
+}
+#endif
+
+/*****************************************************************************/
+
+#ifdef DEBUG_TLS
+# define DEBUG_MSG(x) fprintf(stderr," %s\n",x)
+# define DEBUG_MSG2(x,y) fprintf(stderr, " %s: %d\n",x,y)
+static int tls_loop_count = 0;
+static int tls_select_count = 0;
+#else
+# define DEBUG_MSG(x) (void)0
+# define DEBUG_MSG2(x,y) (void)0
+#endif
+
+static void tls_rand_seed_uniquely(void);
+static void tls_proxy(int clear_fd, int tls_fd, int info_fd, SSL_CTX *ctx, int client_p);
+static int tls_socket_nonblocking(int fd);
+
+static int tls_child_p = 0;
+static void *tls_child_apparg;
+
+
+struct tls_start_proxy_args
+tls_start_proxy_defaultargs(void)
+{
+ struct tls_start_proxy_args ret;
+
+ ret.fd = -1;
+ ret.client_p = -1;
+ ret.ctx = NULL;
+ ret.pid = NULL;
+ ret.infofd = NULL;
+
+ return ret;
+}
+
+/* Slice in TLS proxy process at fd.
+ * Return value:
+ * 0 ok (*pid is set to child's PID if pid != NULL),
+ * < 0 look at errno
+ * > 0 other error
+ * (return value encodes place of error)
+ *
+ */
+int
+tls_start_proxy(struct tls_start_proxy_args a, void *apparg)
+{
+ int fds[2] = {-1, -1};
+ int infofds[2] = {-1, -1};
+ int r, getfd, getfl;
+ int ret;
+
+ DEBUG_MSG2("tls_start_proxy fd", a.fd);
+ DEBUG_MSG2("tls_start_proxy client_p", a.client_p);
+
+ if (a.fd == -1 || a.client_p == -1 || a.ctx == NULL)
+ return 1;
+
+ if (a.pid != NULL) {
+ *a.pid = 0;
+ }
+ if (a.infofd != NULL) {
+ *a.infofd = -1;
+ }
+
+ r = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+ if (r == -1)
+ return -1;
+ if (a.fd >= FD_SETSIZE || fds[0] >= FD_SETSIZE) {
+ ret = 2;
+ goto err;
+ }
+ if (a.infofd != NULL) {
+ r = pipe(infofds);
+ if (r == -1) {
+ ret = -3;
+ goto err;
+ }
+ }
+
+ r = fork();
+ if (r == -1) {
+ ret = -4;
+ goto err;
+ }
+ if (r == 0) {
+ DEBUG_MSG("fork");
+ tls_child_p = 1;
+ tls_child_apparg = apparg;
+ close(fds[1]);
+ if (infofds[0] != -1)
+ close(infofds[0]);
+ TLS_APP_PROCESS_INIT(a.fd, a.client_p, apparg);
+ DEBUG_MSG("TLS_APP_PROCESS_INIT");
+ tls_proxy(fds[0], a.fd, infofds[1], a.ctx, a.client_p);
+ exit(0);
+ }
+ if (a.pid != NULL)
+ *a.pid = r;
+ if (infofds[1] != -1) {
+ close(infofds[1]);
+ infofds[1] = -1;
+ }
+ /* install fds[1] in place of fd: */
+ close(fds[0]);
+ fds[0] = -1;
+ getfd = fcntl(a.fd, F_GETFD);
+ getfl = fcntl(a.fd, F_GETFL);
+ r = dup2(fds[1], a.fd);
+ close(fds[1]);
+ fds[1] = -1;
+ if (r == -1) {
+ ret = -5;
+ goto err;
+ }
+ if (getfd != 1)
+ fcntl(a.fd, F_SETFD, getfd);
+ if (getfl & O_NONBLOCK)
+ (void)tls_socket_nonblocking(a.fd);
+ if (a.infofd != NULL)
+ *a.infofd = infofds[0];
+ return 0;
+
+ err:
+ if (fds[0] != -1)
+ close(fds[0]);
+ if (fds[1] != -1)
+ close(fds[1]);
+ if (infofds[0] != -1)
+ close(infofds[0]);
+ if (infofds[1] != -1)
+ close(infofds[1]);
+ return ret;
+}
+
+/*****************************************************************************/
+
+static char errbuf[TLS_ERROR_BUFSIZ];
+static size_t errbuf_i = 0;
+
+static void
+tls_errflush(void *apparg)
+{
+ if (errbuf_i == 0)
+ return;
+
+ assert(errbuf_i < sizeof errbuf);
+ assert(errbuf[errbuf_i] == 0);
+ if (errbuf_i == sizeof errbuf - 1) {
+ /* make sure we have a newline, even if string has been truncated */
+ errbuf[errbuf_i - 1] = '\n';
+ }
+
+ /* TLS_APP_ERRFLUSH may modify the string as needed,
+ * e.g. substitute other characters for \n for convenience */
+ TLS_APP_ERRFLUSH(tls_child_p, errbuf, errbuf_i, apparg);
+
+ errbuf_i = 0;
+}
+
+static void
+tls_errprintf(int flush, void *apparg, const char *fmt, ...)
+{
+ va_list args;
+ int r;
+
+ if (errbuf_i < sizeof errbuf - 1) {
+ size_t n;
+
+ va_start(args, fmt);
+ n = (sizeof errbuf) - errbuf_i;
+ r = vsnprintf(errbuf + errbuf_i, n, fmt, args);
+ if (r >= n)
+ r = n - 1;
+ if (r >= 0) {
+ errbuf_i += r;
+ } else {
+ errbuf_i = sizeof errbuf - 1;
+ errbuf[errbuf_i] = '\0';
+ }
+ assert(errbuf_i < sizeof errbuf);
+ assert(errbuf[errbuf_i] == 0);
+ }
+#ifndef TLS_CUMULATE_ERRORS
+ tls_errflush(apparg);
+#else
+ if (flush)
+ tls_errflush(apparg);
+#endif
+}
+
+/* app_prefix.. are for additional information provided by caller.
+ * If OpenSSL error queue is empty, print default_text ("???" if NULL).
+ */
+static char *
+tls_openssl_errors(const char *app_prefix_1, const char *app_prefix_2, const char *default_text, void *apparg)
+{
+ static char reasons[255];
+ size_t reasons_i;
+ unsigned long err;
+ const char *file;
+ int line;
+ const char *data;
+ int flags;
+ char *errstring;
+ int printed_something = 0;
+
+ reasons_i = 0;
+
+ assert(app_prefix_1 != NULL);
+ assert(app_prefix_2 != NULL);
+
+ if (default_text == NULL)
+ default_text = "?""?""?";
+
+ while ((err = ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) {
+ if (reasons_i < sizeof reasons) {
+ size_t n;
+ int r;
+
+ n = (sizeof reasons) - reasons_i;
+ r = snprintf(reasons + reasons_i, n, "%s%s", (reasons_i > 0 ? ", " : ""), ERR_reason_error_string(err));
+ if (r >= n)
+ r = n - 1;
+ if (r >= 0) {
+ reasons_i += r;
+ } else {
+ reasons_i = sizeof reasons;
+ }
+ assert(reasons_i <= sizeof reasons);
+ }
+
+ errstring = ERR_error_string(err, NULL);
+ assert(errstring != NULL);
+ tls_errprintf(0, apparg, "OpenSSL error%s%s: %s:%s:%d:%s\n", app_prefix_1, app_prefix_2, errstring, file, line, (flags & ERR_TXT_STRING) ? data : "");
+ printed_something = 1;
+ }
+
+ if (!printed_something) {
+ assert(reasons_i == 0);
+ snprintf(reasons, sizeof reasons, "%s", default_text);
+ tls_errprintf(0, apparg, "OpenSSL error%s%s: %s\n", app_prefix_1, app_prefix_2, default_text);
+ }
+
+#ifdef TLS_CUMULATE_ERRORS
+ tls_errflush(apparg);
+#endif
+ assert(errbuf_i == 0);
+
+ return reasons;
+}
+
+/*****************************************************************************/
+
+static int tls_init_done = 0;
+
+static int
+tls_init(void *apparg)
+{
+ if (tls_init_done)
+ return 0;
+
+ SSL_load_error_strings();
+ if (!SSL_library_init() /* aka SSLeay_add_ssl_algorithms() */ ) {
+ tls_errprintf(1, apparg, "SSL_library_init failed.\n");
+ return -1;
+ }
+ tls_init_done = 1;
+ tls_rand_seed();
+ return 0;
+}
+
+/*****************************************************************************/
+
+static void
+tls_rand_seed_uniquely(void)
+{
+ struct {
+ pid_t pid;
+ time_t time;
+ void *stack;
+ } data;
+
+ data.pid = getpid();
+ data.time = time(NULL);
+ data.stack = (void *)&data;
+
+ RAND_seed((const void *)&data, sizeof data);
+}
+
+void
+tls_rand_seed(void)
+{
+ struct {
+ struct utsname uname;
+ int uname_1;
+ int uname_2;
+ uid_t uid;
+ uid_t euid;
+ gid_t gid;
+ gid_t egid;
+ } data;
+
+ data.uname_1 = uname(&data.uname);
+ data.uname_2 = errno; /* Let's hope that uname fails randomly :-) */
+
+ data.uid = getuid();
+ data.euid = geteuid();
+ data.gid = getgid();
+ data.egid = getegid();
+
+ RAND_seed((const void *)&data, sizeof data);
+ tls_rand_seed_uniquely();
+}
+
+static int tls_rand_seeded_p = 0;
+
+#define my_MIN_SEED_BYTES 256 /* struct stat can be larger than 128 */
+int
+tls_rand_seed_from_file(const char *filename, size_t n, void *apparg)
+{
+ /* Seed OpenSSL's random number generator from file.
+ Try to read n bytes if n > 0, whole file if n == 0. */
+
+ int r;
+
+ if (tls_init(apparg) == -1)
+ return -1;
+ tls_rand_seed();
+
+ r = RAND_load_file(filename, (n > 0 && n < LONG_MAX) ? (long)n : LONG_MAX);
+ /* r is the number of bytes filled into the random number generator,
+ * which are taken from "stat(filename, ...)" in addition to the
+ * file contents.
+ */
+ assert(1 < my_MIN_SEED_BYTES);
+ /* We need to detect at least those cases when the file does not exist
+ * at all. With current versions of OpenSSL, this should do it: */
+ if (n == 0)
+ n = my_MIN_SEED_BYTES;
+ if (r < n) {
+ tls_errprintf(1, apparg, "rand_seed_from_file: could not read %d bytes from %s.\n", n, filename);
+ return -1;
+ } else {
+ tls_rand_seeded_p = 1;
+ return 0;
+ }
+}
+
+void
+tls_rand_seed_from_memory(const void *buf, size_t n)
+{
+ size_t i = 0;
+
+ while (i < n) {
+ size_t rest = n - i;
+ int chunk = rest < INT_MAX ? (int)rest : INT_MAX;
+ RAND_seed((const char *)buf + i, chunk);
+ i += chunk;
+ }
+ tls_rand_seeded_p = 1;
+}
+
+
+/*****************************************************************************/
+
+struct tls_x509_name_string {
+ char str[100];
+};
+
+static void
+tls_get_x509_subject_name_oneline(X509 *cert, struct tls_x509_name_string *namestring)
+{
+ X509_NAME *name;
+
+ if (cert == NULL) {
+ namestring->str[0] = '\0';
+ return;
+ }
+
+ name = X509_get_subject_name(cert); /* does not increment any reference counter */
+
+ assert(sizeof namestring->str >= 4); /* "?" or "...", plus 0 */
+
+ if (name == NULL) {
+ namestring->str[0] = '?';
+ namestring->str[1] = 0;
+ } else {
+ size_t len;
+
+ X509_NAME_oneline(name, namestring->str, sizeof namestring->str);
+ len = strlen(namestring->str);
+ assert(namestring->str[len] == 0);
+ assert(len < sizeof namestring->str);
+
+ if (len+1 == sizeof namestring->str) {
+ /* (Probably something was cut off.)
+ * Does not really work -- X509_NAME_oneline truncates after
+ * name components, we cannot tell from the result whether
+ * anything is missing. */
+
+ assert(namestring->str[len] == 0);
+ namestring->str[--len] = '.';
+ namestring->str[--len] = '.';
+ namestring->str[--len] = '.';
+ }
+ }
+}
+
+/*****************************************************************************/
+
+/* to hinder OpenSSL from asking for passphrases */
+static int
+no_passphrase_callback(char *buf, int num, int w, void *arg)
+{
+ return -1;
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+static int
+verify_dont_fail_cb(X509_STORE_CTX *c, void *unused_arg)
+#else
+static int
+verify_dont_fail_cb(X509_STORE_CTX *c)
+#endif
+{
+ int i;
+
+ i = X509_verify_cert(c); /* sets c->error */
+#if OPENSSL_VERSION_NUMBER >= 0x00905000L /* don't allow unverified
+ * certificates -- they could
+ * survive session reuse, but
+ * OpenSSL < 0.9.5-dev does not
+ * preserve their verify_result */
+ if (i == 0)
+ return 1;
+ else
+#endif
+ return i;
+}
+
+static DH *tls_dhe1024 = NULL; /* generating these takes a while, so do it just once */
+
+void
+tls_set_dhe1024(int i, void *apparg)
+{
+ DSA *dsaparams;
+ DH *dhparams;
+ const char *seed[] = { ";-) :-( :-) :-( ",
+ ";-) :-( :-) :-( ",
+ "Random String no. 12",
+ ";-) :-( :-) :-( ",
+ "hackers have even mo", /* from jargon file */
+ };
+ unsigned char seedbuf[20];
+
+ tls_init(apparg);
+ if (i >= 0) {
+ i %= sizeof seed / sizeof seed[0];
+ assert(strlen(seed[i]) == 20);
+ memcpy(seedbuf, seed[i], 20);
+ dsaparams = DSA_generate_parameters(1024, seedbuf, 20, NULL, NULL, 0, NULL);
+ } else {
+ /* random parameters (may take a while) */
+ dsaparams = DSA_generate_parameters(1024, NULL, 0, NULL, NULL, 0, NULL);
+ }
+
+ if (dsaparams == NULL) {
+ tls_openssl_errors("", "", NULL, apparg);
+ return;
+ }
+ dhparams = DSA_dup_DH(dsaparams);
+ DSA_free(dsaparams);
+ if (dhparams == NULL) {
+ tls_openssl_errors("", "", NULL, apparg);
+ return;
+ }
+ if (tls_dhe1024 != NULL)
+ DH_free(tls_dhe1024);
+ tls_dhe1024 = dhparams;
+}
+
+struct tls_create_ctx_args
+tls_create_ctx_defaultargs(void)
+{
+ struct tls_create_ctx_args ret;
+
+ ret.client_p = 0;
+ ret.certificate_file = NULL;
+ ret.key_file = NULL;
+ ret.ca_file = NULL;
+ ret.verify_depth = -1;
+ ret.fail_unless_verified = 0;
+ ret.export_p = 0;
+
+ return ret;
+}
+
+SSL_CTX *
+tls_create_ctx(struct tls_create_ctx_args a, void *apparg)
+{
+ int r;
+ static long context_num = 0;
+ SSL_CTX *ret;
+ const char *err_pref_1 = "", *err_pref_2 = "";
+
+ if (tls_init(apparg) == -1)
+ return NULL;
+
+ ret = SSL_CTX_new((a.client_p? SSLv23_client_method:SSLv23_server_method)());
+
+ if (ret == NULL)
+ goto err;
+
+ SSL_CTX_set_default_passwd_cb(ret, no_passphrase_callback);
+ SSL_CTX_set_mode(ret, SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+ if ((a.certificate_file != NULL) || (a.key_file != NULL)) {
+ if (a.key_file == NULL) {
+ tls_errprintf(1, apparg, "Need a key file.\n");
+ goto err_return;
+ }
+ if (a.certificate_file == NULL) {
+ tls_errprintf(1, apparg, "Need a certificate chain file.\n");
+ goto err_return;
+ }
+
+ if (!SSL_CTX_use_PrivateKey_file(ret, a.key_file, SSL_FILETYPE_PEM))
+ goto err;
+ if (!tls_rand_seeded_p) {
+ /* particularly paranoid people may not like this --
+ * so provide your own random seeding before calling this */
+ if (tls_rand_seed_from_file(a.key_file, 0, apparg) == -1)
+ goto err_return;
+ }
+ if (!SSL_CTX_use_certificate_chain_file(ret, a.certificate_file))
+ goto err;
+ if (!SSL_CTX_check_private_key(ret)) {
+ tls_errprintf(1, apparg, "Private key \"%s\" does not match certificate \"%s\".\n", a.key_file, a.certificate_file);
+ goto err_peek;
+ }
+ }
+
+ if ((a.ca_file != NULL) || (a.verify_depth > 0)) {
+ context_num++;
+ r = SSL_CTX_set_session_id_context(ret, (const void *)&context_num, (unsigned int)sizeof context_num);
+ if (!r)
+ goto err;
+
+ SSL_CTX_set_verify(ret, SSL_VERIFY_PEER | (a.fail_unless_verified ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), 0);
+ if (!a.fail_unless_verified)
+ SSL_CTX_set_cert_verify_callback(ret, verify_dont_fail_cb, NULL);
+
+ if (a.verify_depth > 0)
+ SSL_CTX_set_verify_depth(ret, a.verify_depth);
+
+ if (a.ca_file != NULL) {
+ r = SSL_CTX_load_verify_locations(ret, a.ca_file, NULL /* no CA-directory */); /* does not report failure if file does not exist ... */
+ if (!r) {
+ err_pref_1 = " while processing certificate file ";
+ err_pref_2 = a.ca_file;
+ goto err;
+ }
+
+ if (!a.client_p) {
+ /* SSL_load_client_CA_file is a misnomer, it just creates a list of CNs. */
+ SSL_CTX_set_client_CA_list(ret, SSL_load_client_CA_file(a.ca_file));
+ /* SSL_CTX_set_client_CA_list does not have a return value;
+ * it does not really need one, but make sure
+ * (we really test if SSL_load_client_CA_file worked) */
+ if (SSL_CTX_get_client_CA_list(ret) == NULL) {
+ tls_errprintf(1, apparg, "Could not set client CA list from \"%s\".\n", a.ca_file);
+ goto err_peek;
+ }
+ }
+ }
+ }
+
+ if (!a.client_p) {
+ if (tls_dhe1024 == NULL) {
+ int i;
+
+ RAND_bytes((unsigned char *) &i, sizeof i);
+ /* make sure that i is non-negative -- pick one of the provided
+ * seeds */
+ if (i < 0)
+ i = -i;
+ if (i < 0)
+ i = 0;
+ tls_set_dhe1024(i, apparg);
+ if (tls_dhe1024 == NULL)
+ goto err_return;
+ }
+
+ if (!SSL_CTX_set_tmp_dh(ret, tls_dhe1024))
+ goto err;
+
+ /* avoid small subgroup attacks: */
+ SSL_CTX_set_options(ret, SSL_OP_SINGLE_DH_USE);
+ }
+
+#ifndef NO_RSA
+ if (!a.client_p && a.export_p) {
+ RSA *tmpkey;
+
+ tmpkey = RSA_generate_key(512, RSA_F4, 0, NULL);
+ if (tmpkey == NULL)
+ goto err;
+ if (!SSL_CTX_set_tmp_rsa(ret, tmpkey)) {
+ RSA_free(tmpkey);
+ goto err;
+ }
+ RSA_free(tmpkey); /* SSL_CTX_set_tmp_rsa uses a duplicate. */
+ }
+#endif
+
+ return ret;
+
+ err_peek:
+ if (!ERR_peek_error())
+ goto err_return;
+ err:
+ tls_openssl_errors(err_pref_1, err_pref_2, NULL, apparg);
+ err_return:
+ if (ret != NULL)
+ SSL_CTX_free(ret);
+ return NULL;
+}
+
+
+/*****************************************************************************/
+
+static int
+tls_socket_nonblocking(int fd)
+{
+ int v, r;
+
+ v = fcntl(fd, F_GETFL, 0);
+ if (v == -1) {
+ if (errno == EINVAL)
+ return 0; /* already shut down -- ignore */
+ return -1;
+ }
+ r = fcntl(fd, F_SETFL, v | O_NONBLOCK);
+ if (r == -1) {
+ if (errno == EINVAL)
+ return 0; /* already shut down -- ignore */
+ return -1;
+ }
+ return 0;
+}
+
+static int
+max(int a, int b)
+{
+ return a > b ? a : b;
+}
+
+static void
+tls_sockets_select(int read_select_1, int read_select_2, int write_select_1, int write_select_2, int seconds /* timeout, -1 means no timeout */)
+{
+ int maxfd, n;
+ fd_set reads, writes;
+ struct timeval timeout;
+ struct timeval *timeout_p;
+
+ assert(read_select_1 >= -1 && read_select_2 >= -1 && write_select_1 >= -1 && write_select_2 >= -1);
+ assert(read_select_1 < FD_SETSIZE && read_select_2 < FD_SETSIZE -1 && write_select_1 < FD_SETSIZE -1 && write_select_2 < FD_SETSIZE -1);
+
+ maxfd = max(max(read_select_1, read_select_2), max(write_select_1, write_select_2));
+ assert(maxfd >= 0);
+
+ FD_ZERO(&reads);
+ FD_ZERO(&writes);
+
+ for(n = 0; n < 4; ++n) {
+ int i = n % 2;
+ int w = n >= 2;
+ /* loop over all (i, w) in {0,1}x{0,1} */
+ int fd;
+
+ if (i == 0 && w == 0)
+ fd = read_select_1;
+ else if (i == 1 && w == 0)
+ fd = read_select_2;
+ else if (i == 0 && w == 1)
+ fd = write_select_1;
+ else {
+ assert(i == 1 && w == 1);
+ fd = write_select_2;
+ }
+
+ if (fd >= 0) {
+ if (w == 0)
+ FD_SET(fd, &reads);
+ else /* w == 1 */
+ FD_SET(fd, &writes);
+ }
+ }
+
+ if (seconds >= 0) {
+ timeout.tv_sec = seconds;
+ timeout.tv_usec = 0;
+ timeout_p = &timeout;
+ } else
+ timeout_p = NULL;
+
+ DEBUG_MSG2("select no.", ++tls_select_count);
+ select(maxfd + 1, &reads, &writes, (fd_set *) NULL, timeout_p);
+ DEBUG_MSG("cont.");
+}
+
+/*****************************************************************************/
+
+#define TUNNELBUFSIZE (16*1024)
+struct tunnelbuf {
+ char buf[TUNNELBUFSIZE];
+ size_t len;
+ size_t offset;
+};
+
+static int tls_connect_attempt(SSL *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref);
+
+static int tls_accept_attempt(SSL *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref);
+
+static int tls_write_attempt(SSL *, struct tunnelbuf *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref);
+
+static int tls_read_attempt(SSL *, struct tunnelbuf *, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref);
+
+static int write_attempt(int fd, struct tunnelbuf *, int *select, int *closed, int *progress);
+
+static int read_attempt(int fd, struct tunnelbuf *, int *select, int *closed, int *progress);
+
+static void write_info(SSL *ssl, int *info_fd)
+{
+ if (*info_fd != -1) {
+ long v;
+ int v_ok;
+ struct tls_x509_name_string peer;
+ char infobuf[TLS_INFO_SIZE];
+ int r;
+
+ DEBUG_MSG("write_info");
+ v = SSL_get_verify_result(ssl);
+ v_ok = (v == X509_V_OK) ? 'A' : 'E'; /* Auth./Error */
+ {
+ X509 *peercert;
+
+ peercert = SSL_get_peer_certificate(ssl);
+ tls_get_x509_subject_name_oneline(peercert, &peer);
+ if (peercert != NULL)
+ X509_free(peercert);
+ }
+ if (peer.str[0] == '\0')
+ v_ok = '0'; /* no cert at all */
+ else
+ if (strchr(peer.str, '\n')) {
+ /* should not happen, but make sure */
+ *strchr(peer.str, '\n') = '\0';
+ }
+ r = snprintf(infobuf, sizeof infobuf, "%c:%s\n%s\n", v_ok, X509_verify_cert_error_string(v), peer.str);
+ DEBUG_MSG2("snprintf", r);
+ if (r == -1 || r >= sizeof infobuf)
+ r = sizeof infobuf - 1;
+ write(*info_fd, infobuf, r);
+ close (*info_fd);
+ *info_fd = -1;
+ }
+}
+
+
+/* tls_proxy expects that all fds are closed after return */
+static void
+tls_proxy(int clear_fd, int tls_fd, int info_fd, SSL_CTX *ctx, int client_p)
+{
+ struct tunnelbuf clear_to_tls, tls_to_clear;
+ SSL *ssl;
+ BIO *rbio, *wbio;
+ int closed, in_handshake;
+ const char *err_pref_1 = "", *err_pref_2 = "";
+ const char *err_def = NULL;
+
+ assert(clear_fd != -1);
+ assert(tls_fd != -1);
+ assert(clear_fd < FD_SETSIZE);
+ assert(tls_fd < FD_SETSIZE);
+ /* info_fd may be -1 */
+ assert(ctx != NULL);
+
+ tls_rand_seed_uniquely();
+
+ tls_socket_nonblocking(clear_fd);
+ DEBUG_MSG2("clear_fd", clear_fd);
+ tls_socket_nonblocking(tls_fd);
+ DEBUG_MSG2("tls_fd", tls_fd);
+
+ ssl = SSL_new(ctx);
+ if (ssl == NULL)
+ goto err;
+ DEBUG_MSG("SSL_new");
+ if (!SSL_set_fd(ssl, tls_fd))
+ goto err;
+ rbio = SSL_get_rbio(ssl);
+ wbio = SSL_get_wbio(ssl); /* should be the same, but who cares */
+ assert(rbio != NULL);
+ assert(wbio != NULL);
+ if (client_p)
+ SSL_set_connect_state(ssl);
+ else
+ SSL_set_accept_state(ssl);
+
+ closed = 0;
+ in_handshake = 1;
+ tls_to_clear.len = 0;
+ tls_to_clear.offset = 0;
+ clear_to_tls.len = 0;
+ clear_to_tls.offset = 0;
+
+ err_def = "I/O error";
+
+ /* loop finishes as soon as we detect that one side closed;
+ * when all (program and OS) buffers have enough space,
+ * the data from the last succesful read in each direction is transferred
+ * before close */
+ do {
+ int clear_read_select = 0, clear_write_select = 0,
+ tls_read_select = 0, tls_write_select = 0,
+ progress = 0;
+ int r;
+ unsigned long num_read = BIO_number_read(rbio),
+ num_written = BIO_number_written(wbio);
+
+ DEBUG_MSG2("loop iteration", ++tls_loop_count);
+
+ if (in_handshake) {
+ DEBUG_MSG("in_handshake");
+ if (client_p)
+ r = tls_connect_attempt(ssl, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1);
+ else
+ r = tls_accept_attempt(ssl, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1);
+ if (r != 0) {
+ write_info(ssl, &info_fd);
+ goto err;
+ }
+ if (closed)
+ goto err_return;
+ if (!SSL_in_init(ssl)) {
+ in_handshake = 0;
+ write_info(ssl, &info_fd);
+ }
+ }
+
+ if (clear_to_tls.len != 0 && !in_handshake) {
+ assert(!closed);
+
+ r = tls_write_attempt(ssl, &clear_to_tls, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1);
+ if (r != 0)
+ goto err;
+ if (closed) {
+ assert(progress);
+ tls_to_clear.offset = 0;
+ tls_to_clear.len = 0;
+ }
+ }
+
+ if (tls_to_clear.len != 0) {
+ assert(!closed);
+
+ r = write_attempt(clear_fd, &tls_to_clear, &clear_write_select, &closed, &progress);
+ if (r != 0)
+ goto err_return;
+ if (closed) {
+ assert(progress);
+ clear_to_tls.offset = 0;
+ clear_to_tls.len = 0;
+ }
+ }
+
+ if (!closed) {
+ if (clear_to_tls.offset + clear_to_tls.len < sizeof clear_to_tls.buf) {
+ r = read_attempt(clear_fd, &clear_to_tls, &clear_read_select, &closed, &progress);
+ if (r != 0)
+ goto err_return;
+ if (closed) {
+ r = SSL_shutdown(ssl);
+ DEBUG_MSG2("SSL_shutdown", r);
+ }
+ }
+ }
+
+ if (!closed && !in_handshake) {
+ if (tls_to_clear.offset + tls_to_clear.len < sizeof tls_to_clear.buf) {
+ r = tls_read_attempt(ssl, &tls_to_clear, &tls_write_select, &tls_read_select, &closed, &progress, &err_pref_1);
+ if (r != 0)
+ goto err;
+ if (closed) {
+ r = SSL_shutdown(ssl);
+ DEBUG_MSG2("SSL_shutdown", r);
+ }
+ }
+ }
+
+ if (!progress) {
+ DEBUG_MSG("!progress?");
+ if (num_read != BIO_number_read(rbio) || num_written != BIO_number_written(wbio))
+ progress = 1;
+
+ if (!progress) {
+ DEBUG_MSG("!progress");
+ assert(clear_read_select || tls_read_select || clear_write_select || tls_write_select);
+ tls_sockets_select(clear_read_select ? clear_fd : -1, tls_read_select ? tls_fd : -1, clear_write_select ? clear_fd : -1, tls_write_select ? tls_fd : -1, -1);
+ }
+ }
+ } while (!closed);
+ return;
+
+ err:
+ tls_openssl_errors(err_pref_1, err_pref_2, err_def, tls_child_apparg);
+ err_return:
+ return;
+}
+
+
+static int
+tls_get_error(SSL *ssl, int r, int *write_select, int *read_select, int *closed, int *progress)
+{
+ int err = SSL_get_error(ssl, r);
+
+ if (err == SSL_ERROR_NONE) {
+ assert(r > 0);
+ *progress = 1;
+ return 0;
+ }
+
+ assert(r <= 0);
+
+ switch (err) {
+ case SSL_ERROR_ZERO_RETURN:
+ assert(r == 0);
+ *closed = 1;
+ *progress = 1;
+ return 0;
+
+ case SSL_ERROR_WANT_WRITE:
+ *write_select = 1;
+ return 0;
+
+ case SSL_ERROR_WANT_READ:
+ *read_select = 1;
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+tls_connect_attempt(SSL *ssl, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref)
+{
+ int n, r;
+
+ DEBUG_MSG("tls_connect_attempt");
+ n = SSL_connect(ssl);
+ DEBUG_MSG2("SSL_connect",n);
+ r = tls_get_error(ssl, n, write_select, read_select, closed, progress);
+ if (r == -1)
+ *err_pref = " during SSL_connect";
+ return r;
+}
+
+static int
+tls_accept_attempt(SSL *ssl, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref)
+{
+ int n, r;
+
+ DEBUG_MSG("tls_accept_attempt");
+ n = SSL_accept(ssl);
+ DEBUG_MSG2("SSL_accept",n);
+ r = tls_get_error(ssl, n, write_select, read_select, closed, progress);
+ if (r == -1)
+ *err_pref = " during SSL_accept";
+ return r;
+}
+
+static int
+tls_write_attempt(SSL *ssl, struct tunnelbuf *buf, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref)
+{
+ int n, r;
+
+ DEBUG_MSG("tls_write_attempt");
+ n = SSL_write(ssl, buf->buf + buf->offset, buf->len);
+ DEBUG_MSG2("SSL_write",n);
+ r = tls_get_error(ssl, n, write_select, read_select, closed, progress);
+ if (n > 0) {
+ buf->len -= n;
+ assert(buf->len >= 0);
+ if (buf->len == 0)
+ buf->offset = 0;
+ else
+ buf->offset += n;
+ }
+ if (r == -1)
+ *err_pref = " during SSL_write";
+ return r;
+}
+
+static int
+tls_read_attempt(SSL *ssl, struct tunnelbuf *buf, int *write_select, int *read_select, int *closed, int *progress, const char **err_pref)
+{
+ int n, r;
+ size_t total;
+
+ DEBUG_MSG("tls_read_attempt");
+ total = buf->offset + buf->len;
+ assert(total < sizeof buf->buf);
+ n = SSL_read(ssl, buf->buf + total, (sizeof buf->buf) - total);
+ DEBUG_MSG2("SSL_read",n);
+ r = tls_get_error(ssl, n, write_select, read_select, closed, progress);
+ if (n > 0) {
+ buf->len += n;
+ assert(buf->offset + buf->len <= sizeof buf->buf);
+ }
+ if (r == -1)
+ *err_pref = " during SSL_read";
+ return r;
+}
+
+static int
+get_error(int r, int *select, int *closed, int *progress)
+{
+ if (r >= 0) {
+ *progress = 1;
+ if (r == 0)
+ *closed = 1;
+ return 0;
+ } else {
+ assert(r == -1);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ *select = 1;
+ return 0;
+ } else if (errno == EPIPE) {
+ *progress = 1;
+ *closed = 1;
+ return 0;
+ } else
+ return -1;
+ }
+}
+
+static int write_attempt(int fd, struct tunnelbuf *buf, int *select, int *closed, int *progress)
+{
+ int n, r;
+
+ DEBUG_MSG("write_attempt");
+ n = write(fd, buf->buf + buf->offset, buf->len);
+ DEBUG_MSG2("write",n);
+ r = get_error(n, select, closed, progress);
+ if (n > 0) {
+ buf->len -= n;
+ assert(buf->len >= 0);
+ if (buf->len == 0)
+ buf->offset = 0;
+ else
+ buf->offset += n;
+ }
+ if (r == -1)
+ tls_errprintf(1, tls_child_apparg, "write error: %s\n", strerror(errno));
+ return r;
+}
+
+static int
+read_attempt(int fd, struct tunnelbuf *buf, int *select, int *closed, int *progress)
+{
+ int n, r;
+ size_t total;
+
+ DEBUG_MSG("read_attempt");
+ total = buf->offset + buf->len;
+ assert(total < sizeof buf->buf);
+ n = read(fd, buf->buf + total, (sizeof buf->buf) - total);
+ DEBUG_MSG2("read",n);
+ r = get_error(n, select, closed, progress);
+ if (n > 0) {
+ buf->len += n;
+ assert(buf->offset + buf->len <= sizeof buf->buf);
+ }
+ if (r == -1)
+ tls_errprintf(1, tls_child_apparg, "read error: %s\n", strerror(errno));
+ return r;
+}
diff --git a/crypto/openssl/demos/easy_tls/easy-tls.h b/crypto/openssl/demos/easy_tls/easy-tls.h
new file mode 100644
index 0000000..52b298e
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/easy-tls.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; c-file-style: "bsd" -*- */
+/*
+ * easy-tls.h -- generic TLS proxy.
+ * $Id: easy-tls.h,v 1.1 2001/09/17 19:06:59 bodo Exp $
+ */
+/*
+ * (c) Copyright 1999 Bodo Moeller. All rights reserved.
+ */
+
+#ifndef HEADER_TLS_H
+#define HEADER_TLS_H
+
+#ifndef HEADER_SSL_H
+typedef struct ssl_ctx_st SSL_CTX;
+#endif
+
+#define TLS_INFO_SIZE 512 /* max. # of bytes written to infofd */
+
+void tls_set_dhe1024(int i, void* apparg);
+/* Generate DHE parameters:
+ * i >= 0 deterministic (i selects seed), i < 0 random (may take a while).
+ * tls_create_ctx calls this with random non-negative i if the application
+ * has never called it.*/
+
+void tls_rand_seed(void);
+int tls_rand_seed_from_file(const char *filename, size_t n, void *apparg);
+void tls_rand_seed_from_memory(const void *buf, size_t n);
+
+struct tls_create_ctx_args
+{
+ int client_p;
+ const char *certificate_file;
+ const char *key_file;
+ const char *ca_file;
+ int verify_depth;
+ int fail_unless_verified;
+ int export_p;
+};
+struct tls_create_ctx_args tls_create_ctx_defaultargs(void);
+/* struct tls_create_ctx_args is similar to a conventional argument list,
+ * but it can provide default values and allows for future extension. */
+SSL_CTX *tls_create_ctx(struct tls_create_ctx_args, void *apparg);
+
+struct tls_start_proxy_args
+{
+ int fd;
+ int client_p;
+ SSL_CTX *ctx;
+ pid_t *pid;
+ int *infofd;
+};
+struct tls_start_proxy_args tls_start_proxy_defaultargs(void);
+/* tls_start_proxy return value *MUST* be checked!
+ * 0 means ok, otherwise we've probably run out of some resources. */
+int tls_start_proxy(struct tls_start_proxy_args, void *apparg);
+
+#endif
diff --git a/crypto/openssl/demos/easy_tls/test.c b/crypto/openssl/demos/easy_tls/test.c
new file mode 100644
index 0000000..21f679a
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/test.c
@@ -0,0 +1,244 @@
+/* test.c */
+/* $Id: test.c,v 1.1 2001/09/17 19:06:59 bodo Exp $ */
+
+#define L_PORT 9999
+#define C_PORT 443
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "test.h"
+#include "easy-tls.h"
+
+void
+test_process_init(int fd, int client_p, void *apparg)
+{
+ fprintf(stderr, "test_process_init(fd = %d, client_p = %d, apparg = %p)\n", fd, client_p, apparg);
+}
+
+void
+test_errflush(int child_p, char *errbuf, size_t num, void *apparg)
+{
+ fputs(errbuf, stderr);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ int s, fd, r;
+ FILE *conn_in;
+ FILE *conn_out;
+ char buf[256];
+ SSL_CTX *ctx;
+ int client_p = 0;
+ int port;
+ int tls = 0;
+ char infobuf[TLS_INFO_SIZE + 1];
+
+ if (argc > 1 && argv[1][0] == '-') {
+ fputs("Usage: test [port] -- server\n"
+ " test num.num.num.num [port] -- client\n",
+ stderr);
+ exit(1);
+ }
+
+ if (argc > 1) {
+ if (strchr(argv[1], '.')) {
+ client_p = 1;
+ }
+ }
+
+ fputs(client_p ? "Client\n" : "Server\n", stderr);
+
+ {
+ struct tls_create_ctx_args a = tls_create_ctx_defaultargs();
+ a.client_p = client_p;
+ a.certificate_file = "cert.pem";
+ a.key_file = "cert.pem";
+ a.ca_file = "cacerts.pem";
+
+ ctx = tls_create_ctx(a, NULL);
+ if (ctx == NULL)
+ exit(1);
+ }
+
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (s == -1) {
+ perror("socket");
+ exit(1);
+ }
+
+ if (client_p) {
+ struct sockaddr_in addr;
+ size_t addr_len = sizeof addr;
+
+ addr.sin_family = AF_INET;
+ assert(argc > 1);
+ if (argc > 2)
+ sscanf(argv[2], "%d", &port);
+ else
+ port = C_PORT;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = inet_addr(argv[1]);
+
+ r = connect(s, &addr, addr_len);
+ if (r != 0) {
+ perror("connect");
+ exit(1);
+ }
+ fd = s;
+ fprintf(stderr, "Connect (fd = %d).\n", fd);
+ } else {
+ /* server */
+ {
+ int i = 1;
+
+ r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *) &i, sizeof i);
+ if (r == -1) {
+ perror("setsockopt");
+ exit(1);
+ }
+ }
+
+ {
+ struct sockaddr_in addr;
+ size_t addr_len = sizeof addr;
+
+ if (argc > 1)
+ sscanf(argv[1], "%d", &port);
+ else
+ port = L_PORT;
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ r = bind(s, &addr, addr_len);
+ if (r != 0) {
+ perror("bind");
+ exit(1);
+ }
+ }
+
+ r = listen(s, 1);
+ if (r == -1) {
+ perror("listen");
+ exit(1);
+ }
+
+ fprintf(stderr, "Listening at port %i.\n", port);
+
+ fd = accept(s, NULL, 0);
+ if (fd == -1) {
+ perror("accept");
+ exit(1);
+ }
+
+ fprintf(stderr, "Accept (fd = %d).\n", fd);
+ }
+
+ conn_in = fdopen(fd, "r");
+ if (conn_in == NULL) {
+ perror("fdopen");
+ exit(1);
+ }
+ conn_out = fdopen(fd, "w");
+ if (conn_out == NULL) {
+ perror("fdopen");
+ exit(1);
+ }
+
+ setvbuf(conn_in, NULL, _IOLBF, 256);
+ setvbuf(conn_out, NULL, _IOLBF, 256);
+
+ while (fgets(buf, sizeof buf, stdin) != NULL) {
+ if (buf[0] == 'W') {
+ fprintf(conn_out, "%.*s\r\n", (int)(strlen(buf + 1) - 1), buf + 1);
+ fprintf(stderr, ">>> %.*s\n", (int)(strlen(buf + 1) - 1), buf + 1);
+ } else if (buf[0] == 'C') {
+ fprintf(stderr, "Closing.\n");
+ fclose(conn_in);
+ fclose(conn_out);
+ exit(0);
+ } else if (buf[0] == 'R') {
+ int lines = 0;
+
+ sscanf(buf + 1, "%d", &lines);
+ do {
+ if (fgets(buf, sizeof buf, conn_in) == NULL) {
+ if (ferror(conn_in)) {
+ fprintf(stderr, "ERROR\n");
+ exit(1);
+ }
+ fprintf(stderr, "CLOSED\n");
+ return 0;
+ }
+ fprintf(stderr, "<<< %s", buf);
+ } while (--lines > 0);
+ } else if (buf[0] == 'T') {
+ int infofd;
+
+ tls++;
+ {
+ struct tls_start_proxy_args a = tls_start_proxy_defaultargs();
+ a.fd = fd;
+ a.client_p = client_p;
+ a.ctx = ctx;
+ a.infofd = &infofd;
+ r = tls_start_proxy(a, NULL);
+ }
+ assert(r != 1);
+ if (r != 0) {
+ fprintf(stderr, "tls_start_proxy failed: %d\n", r);
+ switch (r) {
+ case -1:
+ fputs("socketpair", stderr); break;
+ case 2:
+ fputs("FD_SETSIZE exceeded", stderr); break;
+ case -3:
+ fputs("pipe", stderr); break;
+ case -4:
+ fputs("fork", stderr); break;
+ case -5:
+ fputs("dup2", stderr); break;
+ default:
+ fputs("?", stderr);
+ }
+ if (r < 0)
+ perror("");
+ else
+ fputc('\n', stderr);
+ exit(1);
+ }
+
+ r = read(infofd, infobuf, sizeof infobuf - 1);
+ if (r > 0) {
+ const char *info = infobuf;
+ const char *eol;
+
+ infobuf[r] = '\0';
+ while ((eol = strchr(info, '\n')) != NULL) {
+ fprintf(stderr, "+++ `%.*s'\n", eol - info, info);
+ info = eol+1;
+ }
+ close (infofd);
+ }
+ } else {
+ fprintf(stderr, "W... write line to network\n"
+ "R[n] read line (n lines) from network\n"
+ "C close\n"
+ "T start %sTLS proxy\n", tls ? "another " : "");
+ }
+ }
+ return 0;
+}
diff --git a/crypto/openssl/demos/easy_tls/test.h b/crypto/openssl/demos/easy_tls/test.h
new file mode 100644
index 0000000..dda6678
--- /dev/null
+++ b/crypto/openssl/demos/easy_tls/test.h
@@ -0,0 +1,11 @@
+/* test.h */
+/* $Id: test.h,v 1.1 2001/09/17 19:07:00 bodo Exp $ */
+
+
+void test_process_init(int fd, int client_p, void *apparg);
+#define TLS_APP_PROCESS_INIT test_process_init
+
+#undef TLS_CUMULATE_ERRORS
+
+void test_errflush(int child_p, char *errbuf, size_t num, void *apparg);
+#define TLS_APP_ERRFLUSH test_errflush
diff --git a/crypto/openssl/demos/engines/cluster_labs/Makefile b/crypto/openssl/demos/engines/cluster_labs/Makefile
new file mode 100644
index 0000000..956193f
--- /dev/null
+++ b/crypto/openssl/demos/engines/cluster_labs/Makefile
@@ -0,0 +1,114 @@
+LIBNAME= libclabs
+SRC= hw_cluster_labs.c
+OBJ= hw_cluster_labs.o
+HEADER= hw_cluster_labs.h
+
+CC= gcc
+PIC= -fPIC
+CFLAGS= -g -I../../../include $(PIC) -DENGINE_DYNAMIC_SUPPORT -DFLAT_INC
+AR= ar r
+RANLIB= ranlib
+
+LIB= $(LIBNAME).a
+SHLIB= $(LIBNAME).so
+
+all:
+ @echo 'Please choose a system to build on:'
+ @echo ''
+ @echo 'tru64: Tru64 Unix, Digital Unix, Digital OSF/1'
+ @echo 'solaris: Solaris'
+ @echo 'irix: IRIX'
+ @echo 'hpux32: 32-bit HP/UX'
+ @echo 'hpux64: 64-bit HP/UX'
+ @echo 'aix: AIX'
+ @echo 'gnu: Generic GNU-based system (gcc and GNU ld)'
+ @echo ''
+
+FORCE.update:
+update: FORCE.update
+ perl ../../../util/mkerr.pl -conf hw_cluster_labs.ec \
+ -nostatic -staticloader -write hw_cluster_labs.c
+
+gnu: $(SHLIB).gnu
+tru64: $(SHLIB).tru64
+solaris: $(SHLIB).solaris
+irix: $(SHLIB).irix
+hpux32: $(SHLIB).hpux32
+hpux64: $(SHLIB).hpux64
+aix: $(SHLIB).aix
+
+$(LIB): $(OBJ)
+ $(AR) $(LIB) $(OBJ)
+ - $(RANLIB) $(LIB)
+
+LINK_SO= \
+ ld -r -o $(LIBNAME).o $$ALLSYMSFLAGS $(LIB) && \
+ (nm -Pg $(LIBNAME).o | grep ' [BDT] ' | cut -f1 -d' ' > $(LIBNAME).exp; \
+ $$SHAREDCMD $$SHAREDFLAGS -o $(SHLIB) $(LIBNAME).o -L ../../.. -lcrypto -lc)
+
+$(SHLIB).gnu: $(LIB)
+ ALLSYMSFLAGS='--whole-archive' \
+ SHAREDFLAGS='-shared -Wl,-soname=$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).gnu
+$(SHLIB).tru64: $(LIB)
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).tru64
+$(SHLIB).solaris: $(LIB)
+ ALLSYMSFLAGS='-z allextract' \
+ SHAREDFLAGS='-G -h $(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).solaris
+$(SHLIB).irix: $(LIB)
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared -Wl,-soname,$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).irix
+$(SHLIB).hpux32: $(LIB)
+ ALLSYMSFLAGS='-Fl' \
+ SHAREDFLAGS='+vnocompatwarnings -b -z +s +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux32
+$(SHLIB).hpux64: $(LIB)
+ ALLSYMSFLAGS='+forceload' \
+ SHAREDFLAGS='-b -z +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux64
+$(SHLIB).aix: $(LIB)
+ ALLSYMSFLAGS='-bnogc' \
+ SHAREDFLAGS='-G -bE:$(LIBNAME).exp -bM:SRE' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).aix
+
+depend:
+ sed -e '/^# DO NOT DELETE.*/,$$d' < Makefile > Makefile.tmp
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' >> Makefile.tmp
+ gcc -M $(CFLAGS) $(SRC) >> Makefile.tmp
+ perl ../../../util/clean-depend.pl < Makefile.tmp > Makefile.new
+ rm -f Makefile.tmp Makefile
+ mv Makefile.new Makefile
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+rsaref.o: ../../../include/openssl/asn1.h ../../../include/openssl/bio.h
+rsaref.o: ../../../include/openssl/bn.h ../../../include/openssl/crypto.h
+rsaref.o: ../../../include/openssl/dh.h ../../../include/openssl/dsa.h
+rsaref.o: ../../../include/openssl/e_os2.h ../../../include/openssl/engine.h
+rsaref.o: ../../../include/openssl/err.h ../../../include/openssl/lhash.h
+rsaref.o: ../../../include/openssl/opensslconf.h
+rsaref.o: ../../../include/openssl/opensslv.h
+rsaref.o: ../../../include/openssl/ossl_typ.h ../../../include/openssl/rand.h
+rsaref.o: ../../../include/openssl/rsa.h ../../../include/openssl/safestack.h
+rsaref.o: ../../../include/openssl/stack.h ../../../include/openssl/symhacks.h
+rsaref.o: ../../../include/openssl/ui.h rsaref.c rsaref_err.c rsaref_err.h
+rsaref.o: source/des.h source/global.h source/md2.h source/md5.h source/rsa.h
+rsaref.o: source/rsaref.h
diff --git a/crypto/openssl/demos/engines/cluster_labs/cluster_labs.h b/crypto/openssl/demos/engines/cluster_labs/cluster_labs.h
new file mode 100644
index 0000000..d092679
--- /dev/null
+++ b/crypto/openssl/demos/engines/cluster_labs/cluster_labs.h
@@ -0,0 +1,35 @@
+typedef int cl_engine_init(void);
+typedef int cl_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *cgx);
+typedef int cl_mod_exp_crt(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1,
+ const BIGNUM *iqmp, BN_CTX *ctx);
+typedef int cl_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+typedef int cl_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+typedef int cl_rsa_pub_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+typedef int cl_rsa_priv_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+typedef int cl_rsa_priv_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+typedef int cl_rand_bytes(unsigned char *buf, int num);
+typedef DSA_SIG *cl_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+typedef int cl_dsa_verify(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
+
+
+static const char *CLUSTER_LABS_LIB_NAME = "cluster_labs";
+static const char *CLUSTER_LABS_F1 = "hw_engine_init";
+static const char *CLUSTER_LABS_F2 = "hw_mod_exp";
+static const char *CLUSTER_LABS_F3 = "hw_mod_exp_crt";
+static const char *CLUSTER_LABS_F4 = "hw_rsa_mod_exp";
+static const char *CLUSTER_LABS_F5 = "hw_rsa_priv_enc";
+static const char *CLUSTER_LABS_F6 = "hw_rsa_priv_dec";
+static const char *CLUSTER_LABS_F7 = "hw_rsa_pub_enc";
+static const char *CLUSTER_LABS_F8 = "hw_rsa_pub_dec";
+static const char *CLUSTER_LABS_F20 = "hw_rand_bytes";
+static const char *CLUSTER_LABS_F30 = "hw_dsa_sign";
+static const char *CLUSTER_LABS_F31 = "hw_dsa_verify";
+
+
diff --git a/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.c b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.c
new file mode 100644
index 0000000..036f48b
--- /dev/null
+++ b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.c
@@ -0,0 +1,721 @@
+/* crypto/engine/hw_cluster_labs.c */
+/* Written by Jan Tschirschwitz (jan.tschirschwitz@cluster-labs.com
+ * for the OpenSSL project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#define MSC_VER /* only used cryptic.h */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include <openssl/dso.h>
+#include <openssl/des.h>
+#include <openssl/engine.h>
+
+#ifndef NO_HW
+#ifndef NO_HW_CLUSTER_LABS
+
+#ifdef FLAT_INC
+#include "cluster_labs.h"
+#else
+#include "vendor_defns/cluster_labs.h"
+#endif
+
+#define CL_LIB_NAME "cluster_labs engine"
+#include "hw_cluster_labs_err.c"
+
+
+static int cluster_labs_destroy(ENGINE *e);
+static int cluster_labs_init(ENGINE *e);
+static int cluster_labs_finish(ENGINE *e);
+static int cluster_labs_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+
+/* BIGNUM stuff */
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int cluster_labs_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+
+/* RSA stuff */
+#ifndef OPENSSL_NO_RSA
+static int cluster_labs_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int cluster_labs_rsa_pub_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int cluster_labs_rsa_priv_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int cluster_labs_rsa_priv_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int cluster_labs_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+#endif
+
+/* DSA stuff */
+#ifndef OPENSSL_NO_DSA
+static DSA_SIG *cluster_labs_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+static int cluster_labs_dsa_verify(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
+static int cluster_labs_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+ BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *in_mont);
+static int cluster_labs_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+#endif
+
+/* DH stuff */
+#ifndef OPENSSL_NO_DH
+/* This function is alised to mod_exp (with the DH and mont dropped). */
+static int cluster_labs_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+#endif
+
+/* RANDOM stuff */
+static int cluster_labs_rand_bytes(unsigned char *buf, int num);
+
+/* The definitions for control commands specific to this engine */
+#define CLUSTER_LABS_CMD_SO_PATH ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN cluster_labs_cmd_defns[] =
+ {
+ { CLUSTER_LABS_CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the 'cluster labs' shared library",
+ ENGINE_CMD_FLAG_STRING
+ },
+ {0, NULL, NULL, 0}
+ };
+
+/* Our internal RSA_METHOD that we provide pointers to */
+#ifndef OPENSSL_NO_RSA
+static RSA_METHOD cluster_labs_rsa =
+ {
+ "Cluster Labs RSA method",
+ cluster_labs_rsa_pub_enc, /* rsa_pub_enc */
+ cluster_labs_rsa_pub_dec, /* rsa_pub_dec */
+ cluster_labs_rsa_priv_enc, /* rsa_priv_enc */
+ cluster_labs_rsa_priv_dec, /* rsa_priv_dec */
+ cluster_labs_rsa_mod_exp, /* rsa_mod_exp */
+ cluster_labs_mod_exp_mont, /* bn_mod_exp */
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+ NULL, /* apps_data */
+ NULL, /* rsa_sign */
+ NULL /* rsa_verify */
+ };
+#endif
+
+/* Our internal DSA_METHOD that we provide pointers to */
+#ifndef OPENSSL_NO_DSA
+static DSA_METHOD cluster_labs_dsa =
+ {
+ "Cluster Labs DSA method",
+ cluster_labs_dsa_sign, /* dsa_do_sign */
+ NULL, /* dsa_sign_setup */
+ cluster_labs_dsa_verify, /* dsa_do_verify */
+ cluster_labs_dsa_mod_exp, /* dsa_mod_exp */
+ cluster_labs_mod_exp_dsa, /* bn_mod_exp */
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+ NULL /* app_data */
+ };
+#endif
+
+/* Our internal DH_METHOD that we provide pointers to */
+#ifndef OPENSSL_NO_DH
+static DH_METHOD cluster_labs_dh =
+ {
+ "Cluster Labs DH method",
+ NULL, /* generate key */
+ NULL, /* compute key */
+ cluster_labs_mod_exp_dh, /* bn_mod_exp */
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+ NULL /* app_data */
+ };
+#endif
+
+static RAND_METHOD cluster_labs_rand =
+ {
+ /* "Cluster Labs RAND method", */
+ NULL, /* seed */
+ cluster_labs_rand_bytes, /* bytes */
+ NULL, /* cleanup */
+ NULL, /* add */
+ cluster_labs_rand_bytes, /* pseudorand */
+ NULL, /* status */
+ };
+
+static const char *engine_cluster_labs_id = "cluster_labs";
+static const char *engine_cluster_labs_name = "Cluster Labs hardware engine support";
+
+/* engine implementation */
+/*-----------------------*/
+static int bind_helper(ENGINE *e)
+ {
+
+ if(!ENGINE_set_id(e, engine_cluster_labs_id) ||
+ !ENGINE_set_name(e, engine_cluster_labs_name) ||
+#ifndef OPENSSL_NO_RSA
+ !ENGINE_set_RSA(e, &cluster_labs_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+ !ENGINE_set_DSA(e, &cluster_labs_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+ !ENGINE_set_DH(e, &cluster_labs_dh) ||
+#endif
+ !ENGINE_set_RAND(e, &cluster_labs_rand) ||
+ !ENGINE_set_destroy_function(e, cluster_labs_destroy) ||
+ !ENGINE_set_init_function(e, cluster_labs_init) ||
+ !ENGINE_set_finish_function(e, cluster_labs_finish) ||
+ !ENGINE_set_ctrl_function(e, cluster_labs_ctrl) ||
+ !ENGINE_set_cmd_defns(e, cluster_labs_cmd_defns))
+ return 0;
+ /* Ensure the error handling is set up */
+ ERR_load_CL_strings();
+ return 1;
+ }
+
+#ifndef ENGINE_DYNAMIC_SUPPORT
+static ENGINE *engine_cluster_labs(void)
+ {
+ ENGINE *ret = ENGINE_new();
+
+ if(!ret)
+ return NULL;
+ if(!bind_helper(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static
+#endif
+void ENGINE_load_cluster_labs(void)
+ {
+
+ ENGINE *cluster_labs = engine_cluster_labs();
+
+ if(!cluster_labs) return;
+ ENGINE_add(cluster_labs);
+ ENGINE_free(cluster_labs);
+ ERR_clear_error();
+ }
+#endif /* !ENGINE_DYNAMIC_SUPPORT */
+
+static int cluster_labs_destroy(ENGINE *e)
+ {
+
+ ERR_unload_CL_strings();
+ return 1;
+ }
+
+
+
+/* This is a process-global DSO handle used for loading and unloading
+ * the Cluster Labs library. NB: This is only set (or unset) during an
+ * init() or finish() call (reference counts permitting) and they're
+ * operating with global locks, so this should be thread-safe
+ * implicitly. */
+static DSO *cluster_labs_dso = NULL;
+
+/* These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded. */
+static cl_engine_init *p_cl_engine_init = NULL;
+static cl_mod_exp *p_cl_mod_exp = NULL;
+static cl_mod_exp_crt *p_cl_mod_exp_crt = NULL;
+static cl_rsa_mod_exp *p_cl_rsa_mod_exp = NULL;
+static cl_rsa_priv_enc *p_cl_rsa_priv_enc = NULL;
+static cl_rsa_priv_dec *p_cl_rsa_priv_dec = NULL;
+static cl_rsa_pub_enc *p_cl_rsa_pub_enc = NULL;
+static cl_rsa_pub_dec *p_cl_rsa_pub_dec = NULL;
+static cl_rand_bytes *p_cl_rand_bytes = NULL;
+static cl_dsa_sign *p_cl_dsa_sign = NULL;
+static cl_dsa_verify *p_cl_dsa_verify = NULL;
+
+
+int cluster_labs_init(ENGINE *e)
+ {
+
+ cl_engine_init *p1;
+ cl_mod_exp *p2;
+ cl_mod_exp_crt *p3;
+ cl_rsa_mod_exp *p4;
+ cl_rsa_priv_enc *p5;
+ cl_rsa_priv_dec *p6;
+ cl_rsa_pub_enc *p7;
+ cl_rsa_pub_dec *p8;
+ cl_rand_bytes *p20;
+ cl_dsa_sign *p30;
+ cl_dsa_verify *p31;
+
+ /* engine already loaded */
+ if(cluster_labs_dso != NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_INIT,CL_R_ALREADY_LOADED);
+ goto err;
+ }
+ /* try to load engine */
+ cluster_labs_dso = DSO_load(NULL, CLUSTER_LABS_LIB_NAME, NULL,0);
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_INIT,CL_R_DSO_FAILURE);
+ goto err;
+ }
+ /* bind functions */
+ if( !(p1 = (cl_engine_init *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F1)) ||
+ !(p2 = (cl_mod_exp *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F2)) ||
+ !(p3 = (cl_mod_exp_crt *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F3)) ||
+ !(p4 = (cl_rsa_mod_exp *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F4)) ||
+ !(p5 = (cl_rsa_priv_enc *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F5)) ||
+ !(p6 = (cl_rsa_priv_dec *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F6)) ||
+ !(p7 = (cl_rsa_pub_enc *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F7)) ||
+ !(p8 = (cl_rsa_pub_dec *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F8)) ||
+ !(p20= (cl_rand_bytes *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F20)) ||
+ !(p30= (cl_dsa_sign *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F30)) ||
+ !(p31= (cl_dsa_verify *)DSO_bind_func(
+ cluster_labs_dso, CLUSTER_LABS_F31)))
+ {
+ CLerr(CL_F_CLUSTER_LABS_INIT,CL_R_DSO_FAILURE);
+ goto err;
+ }
+
+ /* copy function pointers */
+ p_cl_engine_init = p1;
+ p_cl_mod_exp = p2;
+ p_cl_mod_exp_crt = p3;
+ p_cl_rsa_mod_exp = p4;
+ p_cl_rsa_priv_enc = p5;
+ p_cl_rsa_priv_dec = p6;
+ p_cl_rsa_pub_enc = p7;
+ p_cl_rsa_pub_dec = p8;
+ p_cl_rand_bytes = p20;
+ p_cl_dsa_sign = p30;
+ p_cl_dsa_verify = p31;
+
+
+
+ /* cluster labs engine init */
+ if(p_cl_engine_init()== 0){
+ CLerr(CL_F_CLUSTER_LABS_INIT,CL_R_INIT_FAILED);
+ goto err;
+ }
+
+ return(1);
+
+err:
+ /* reset all pointers */
+ if(cluster_labs_dso)
+ DSO_free(cluster_labs_dso);
+
+ cluster_labs_dso = NULL;
+ p_cl_engine_init = NULL;
+ p_cl_mod_exp = NULL;
+ p_cl_mod_exp_crt = NULL;
+ p_cl_rsa_mod_exp = NULL;
+ p_cl_rsa_priv_enc = NULL;
+ p_cl_rsa_priv_dec = NULL;
+ p_cl_rsa_pub_enc = NULL;
+ p_cl_rsa_pub_dec = NULL;
+ p_cl_rand_bytes = NULL;
+ p_cl_dsa_sign = NULL;
+ p_cl_dsa_verify = NULL;
+
+ return(0);
+ }
+
+
+static int cluster_labs_finish(ENGINE *e)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_FINISH,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(!DSO_free(cluster_labs_dso))
+ {
+ CLerr(CL_F_CLUSTER_LABS_FINISH,CL_R_DSO_FAILURE);
+ return 0;
+ }
+
+ cluster_labs_dso = NULL;
+ p_cl_engine_init = NULL;
+ p_cl_mod_exp = NULL;
+ p_cl_rsa_mod_exp = NULL;
+ p_cl_mod_exp_crt = NULL;
+ p_cl_rsa_priv_enc = NULL;
+ p_cl_rsa_priv_dec = NULL;
+ p_cl_rsa_pub_enc = NULL;
+ p_cl_rsa_pub_dec = NULL;
+ p_cl_rand_bytes = NULL;
+ p_cl_dsa_sign = NULL;
+ p_cl_dsa_verify = NULL;
+
+ return(1);
+
+ }
+
+static int cluster_labs_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+ {
+ int initialised = ((cluster_labs_dso == NULL) ? 0 : 1);
+
+ switch(cmd)
+ {
+ case CLUSTER_LABS_CMD_SO_PATH:
+ if(p == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if(initialised)
+ {
+ CLerr(CL_F_CLUSTER_LABS_CTRL,CL_R_ALREADY_LOADED);
+ return 0;
+ }
+ CLUSTER_LABS_LIB_NAME = (const char *)p;
+ return 1;
+ default:
+ break;
+ }
+ CLerr(CL_F_CLUSTER_LABS_CTRL,CL_R_COMMAND_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+
+static int cluster_labs_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_MOD_EXP,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_mod_exp == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_MOD_EXP,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_mod_exp(r, a, p, m, ctx);
+
+ }
+
+static int cluster_labs_mod_exp_crt(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1,
+ const BIGNUM *iqmp, BN_CTX *ctx)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_MOD_EXP_CRT,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_mod_exp_crt == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_MOD_EXP_CRT,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_mod_exp_crt(r, a, p, q,dmp1, dmq1, iqmp, ctx);
+
+ }
+
+static int cluster_labs_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_MOD_EXP,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_rsa_mod_exp == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_MOD_EXP,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_rsa_mod_exp(r0, I, rsa);
+
+ }
+
+static DSA_SIG *cluster_labs_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_DSA_SIGN,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_dsa_sign == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_DSA_SIGN,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_dsa_sign(dgst, dlen, dsa);
+
+ }
+
+static int cluster_labs_dsa_verify(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_DSA_VERIFY,CL_R_NOT_LOADED);
+ return 0;
+ }
+
+ if(p_cl_dsa_verify == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_DSA_VERIFY,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_dsa_verify(dgst, dgst_len, sig, dsa);
+
+ }
+
+static int cluster_labs_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+ BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *in_mont)
+ {
+ BIGNUM t;
+ int status = 0;
+
+ BN_init(&t);
+ /* let rr = a1 ^ p1 mod m */
+ if (!cluster_labs_mod_exp(rr,a1,p1,m,ctx)) goto end;
+ /* let t = a2 ^ p2 mod m */
+ if (!cluster_labs_mod_exp(&t,a2,p2,m,ctx)) goto end;
+ /* let rr = rr * t mod m */
+ if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
+ status = 1;
+end:
+ BN_free(&t);
+
+ return(1);
+
+ }
+
+static int cluster_labs_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx)
+ {
+ return cluster_labs_mod_exp(r, a, p, m, ctx);
+ }
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int cluster_labs_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+ {
+ return cluster_labs_mod_exp(r, a, p, m, ctx);
+ }
+
+
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int cluster_labs_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+ {
+ return cluster_labs_mod_exp(r, a, p, m, ctx);
+ }
+
+
+static int cluster_labs_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PUB_ENC,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_rsa_priv_enc == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PUB_ENC,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_rsa_pub_enc(flen, from, to, rsa, padding);
+
+ }
+
+static int cluster_labs_rsa_pub_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PUB_DEC,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_rsa_priv_enc == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PUB_DEC,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_rsa_pub_dec(flen, from, to, rsa, padding);
+
+ }
+
+
+static int cluster_labs_rsa_priv_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PRIV_ENC,CL_R_NOT_LOADED);
+ return 0;
+ }
+
+ if(p_cl_rsa_priv_enc == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PRIV_ENC,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_rsa_priv_enc(flen, from, to, rsa, padding);
+
+ }
+
+static int cluster_labs_rsa_priv_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding)
+ {
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PRIV_DEC,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_rsa_priv_dec == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RSA_PRIV_DEC,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_rsa_priv_dec(flen, from, to, rsa, padding);
+
+ }
+
+/************************************************************************************
+* Symmetric algorithms
+************************************************************************************/
+/* this will be come soon! */
+
+/************************************************************************************
+* Random generator
+************************************************************************************/
+
+static int cluster_labs_rand_bytes(unsigned char *buf, int num){
+
+ if(cluster_labs_dso == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RAND_BYTES,CL_R_NOT_LOADED);
+ return 0;
+ }
+ if(p_cl_mod_exp_crt == NULL)
+ {
+ CLerr(CL_F_CLUSTER_LABS_RAND_BYTES,CL_R_FUNCTION_NOT_BINDED);
+ return 0;
+ }
+
+ return p_cl_rand_bytes(buf, num);
+
+}
+
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+ {
+ fprintf(stderr, "bind_fn CLUSTER_LABS\n");
+ if(id && (strcmp(id, engine_cluster_labs_id) != 0)) {
+ fprintf(stderr, "bind_fn return(0) first\n");
+ return 0;
+ }
+ if(!bind_helper(e)) {
+ fprintf(stderr, "bind_fn return(1) first\n");
+ return 0;
+ }
+ fprintf(stderr, "bind_fn return(1)\n");
+ return 1;
+ }
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !NO_HW_CLUSTER_LABS */
+#endif /* !NO_HW */
+
diff --git a/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.ec b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.ec
new file mode 100644
index 0000000..1f64786
--- /dev/null
+++ b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs.ec
@@ -0,0 +1,8 @@
+# configuration file for util/mkerr.pl
+#
+# use like this:
+#
+# perl ../../../util/mkerr.pl -conf hw_cluster_labs.ec \
+# -nostatic -staticloader -write *.c
+
+L CL hw_cluster_labs_err.h hw_cluster_labs_err.c
diff --git a/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.c b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.c
new file mode 100644
index 0000000..a7fa408
--- /dev/null
+++ b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.c
@@ -0,0 +1,151 @@
+/* hw_cluster_labs_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_cluster_labs_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA CL_str_functs[]=
+ {
+{ERR_PACK(0,CL_F_CLUSTER_LABS_CTRL,0), "CLUSTER_LABS_CTRL"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_DSA_SIGN,0), "CLUSTER_LABS_DSA_SIGN"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_DSA_VERIFY,0), "CLUSTER_LABS_DSA_VERIFY"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_FINISH,0), "CLUSTER_LABS_FINISH"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_INIT,0), "CLUSTER_LABS_INIT"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_MOD_EXP,0), "CLUSTER_LABS_MOD_EXP"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_MOD_EXP_CRT,0), "CLUSTER_LABS_MOD_EXP_CRT"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_RAND_BYTES,0), "CLUSTER_LABS_RAND_BYTES"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_RSA_MOD_EXP,0), "CLUSTER_LABS_RSA_MOD_EXP"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_RSA_PRIV_DEC,0), "CLUSTER_LABS_RSA_PRIV_DEC"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_RSA_PRIV_ENC,0), "CLUSTER_LABS_RSA_PRIV_ENC"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_RSA_PUB_DEC,0), "CLUSTER_LABS_RSA_PUB_DEC"},
+{ERR_PACK(0,CL_F_CLUSTER_LABS_RSA_PUB_ENC,0), "CLUSTER_LABS_RSA_PUB_ENC"},
+{0,NULL}
+ };
+
+static ERR_STRING_DATA CL_str_reasons[]=
+ {
+{CL_R_ALREADY_LOADED ,"already loaded"},
+{CL_R_COMMAND_NOT_IMPLEMENTED ,"command not implemented"},
+{CL_R_DSO_FAILURE ,"dso failure"},
+{CL_R_FUNCTION_NOT_BINDED ,"function not binded"},
+{CL_R_INIT_FAILED ,"init failed"},
+{CL_R_NOT_LOADED ,"not loaded"},
+{0,NULL}
+ };
+
+#endif
+
+#ifdef CL_LIB_NAME
+static ERR_STRING_DATA CL_lib_name[]=
+ {
+{0 ,CL_LIB_NAME},
+{0,NULL}
+ };
+#endif
+
+
+static int CL_lib_error_code=0;
+static int CL_error_init=1;
+
+static void ERR_load_CL_strings(void)
+ {
+ if (CL_lib_error_code == 0)
+ CL_lib_error_code=ERR_get_next_error_library();
+
+ if (CL_error_init)
+ {
+ CL_error_init=0;
+#ifndef OPENSSL_NO_ERR
+ ERR_load_strings(CL_lib_error_code,CL_str_functs);
+ ERR_load_strings(CL_lib_error_code,CL_str_reasons);
+#endif
+
+#ifdef CL_LIB_NAME
+ CL_lib_name->error = ERR_PACK(CL_lib_error_code,0,0);
+ ERR_load_strings(0,CL_lib_name);
+#endif
+ }
+ }
+
+static void ERR_unload_CL_strings(void)
+ {
+ if (CL_error_init == 0)
+ {
+#ifndef OPENSSL_NO_ERR
+ ERR_unload_strings(CL_lib_error_code,CL_str_functs);
+ ERR_unload_strings(CL_lib_error_code,CL_str_reasons);
+#endif
+
+#ifdef CL_LIB_NAME
+ ERR_unload_strings(0,CL_lib_name);
+#endif
+ CL_error_init=1;
+ }
+ }
+
+static void ERR_CL_error(int function, int reason, char *file, int line)
+ {
+ if (CL_lib_error_code == 0)
+ CL_lib_error_code=ERR_get_next_error_library();
+ ERR_PUT_error(CL_lib_error_code,function,reason,file,line);
+ }
diff --git a/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.h b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.h
new file mode 100644
index 0000000..afc175b
--- /dev/null
+++ b/crypto/openssl/demos/engines/cluster_labs/hw_cluster_labs_err.h
@@ -0,0 +1,95 @@
+/* ====================================================================
+ * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_CL_ERR_H
+#define HEADER_CL_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_CL_strings(void);
+static void ERR_unload_CL_strings(void);
+static void ERR_CL_error(int function, int reason, char *file, int line);
+#define CLerr(f,r) ERR_CL_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the CL functions. */
+
+/* Function codes. */
+#define CL_F_CLUSTER_LABS_CTRL 100
+#define CL_F_CLUSTER_LABS_DSA_SIGN 101
+#define CL_F_CLUSTER_LABS_DSA_VERIFY 102
+#define CL_F_CLUSTER_LABS_FINISH 103
+#define CL_F_CLUSTER_LABS_INIT 104
+#define CL_F_CLUSTER_LABS_MOD_EXP 105
+#define CL_F_CLUSTER_LABS_MOD_EXP_CRT 106
+#define CL_F_CLUSTER_LABS_RAND_BYTES 107
+#define CL_F_CLUSTER_LABS_RSA_MOD_EXP 108
+#define CL_F_CLUSTER_LABS_RSA_PRIV_DEC 109
+#define CL_F_CLUSTER_LABS_RSA_PRIV_ENC 110
+#define CL_F_CLUSTER_LABS_RSA_PUB_DEC 111
+#define CL_F_CLUSTER_LABS_RSA_PUB_ENC 112
+
+/* Reason codes. */
+#define CL_R_ALREADY_LOADED 100
+#define CL_R_COMMAND_NOT_IMPLEMENTED 101
+#define CL_R_DSO_FAILURE 102
+#define CL_R_FUNCTION_NOT_BINDED 103
+#define CL_R_INIT_FAILED 104
+#define CL_R_NOT_LOADED 105
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/openssl/demos/engines/ibmca/Makefile b/crypto/openssl/demos/engines/ibmca/Makefile
new file mode 100644
index 0000000..72f3546
--- /dev/null
+++ b/crypto/openssl/demos/engines/ibmca/Makefile
@@ -0,0 +1,114 @@
+LIBNAME= libibmca
+SRC= hw_ibmca.c
+OBJ= hw_ibmca.o
+HEADER= hw_ibmca.h
+
+CC= gcc
+PIC= -fPIC
+CFLAGS= -g -I../../../include $(PIC) -DENGINE_DYNAMIC_SUPPORT -DFLAT_INC
+AR= ar r
+RANLIB= ranlib
+
+LIB= $(LIBNAME).a
+SHLIB= $(LIBNAME).so
+
+all:
+ @echo 'Please choose a system to build on:'
+ @echo ''
+ @echo 'tru64: Tru64 Unix, Digital Unix, Digital OSF/1'
+ @echo 'solaris: Solaris'
+ @echo 'irix: IRIX'
+ @echo 'hpux32: 32-bit HP/UX'
+ @echo 'hpux64: 64-bit HP/UX'
+ @echo 'aix: AIX'
+ @echo 'gnu: Generic GNU-based system (gcc and GNU ld)'
+ @echo ''
+
+FORCE.update:
+update: FORCE.update
+ perl ../../../util/mkerr.pl -conf hw_ibmca.ec \
+ -nostatic -staticloader -write hw_ibmca.c
+
+gnu: $(SHLIB).gnu
+tru64: $(SHLIB).tru64
+solaris: $(SHLIB).solaris
+irix: $(SHLIB).irix
+hpux32: $(SHLIB).hpux32
+hpux64: $(SHLIB).hpux64
+aix: $(SHLIB).aix
+
+$(LIB): $(OBJ)
+ $(AR) $(LIB) $(OBJ)
+ - $(RANLIB) $(LIB)
+
+LINK_SO= \
+ ld -r -o $(LIBNAME).o $$ALLSYMSFLAGS $(LIB) && \
+ (nm -Pg $(LIBNAME).o | grep ' [BDT] ' | cut -f1 -d' ' > $(LIBNAME).exp; \
+ $$SHAREDCMD $$SHAREDFLAGS -o $(SHLIB) $(LIBNAME).o -L ../../.. -lcrypto -lc)
+
+$(SHLIB).gnu: $(LIB)
+ ALLSYMSFLAGS='--whole-archive' \
+ SHAREDFLAGS='-shared -Wl,-soname=$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).gnu
+$(SHLIB).tru64: $(LIB)
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).tru64
+$(SHLIB).solaris: $(LIB)
+ ALLSYMSFLAGS='-z allextract' \
+ SHAREDFLAGS='-G -h $(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).solaris
+$(SHLIB).irix: $(LIB)
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared -Wl,-soname,$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).irix
+$(SHLIB).hpux32: $(LIB)
+ ALLSYMSFLAGS='-Fl' \
+ SHAREDFLAGS='+vnocompatwarnings -b -z +s +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux32
+$(SHLIB).hpux64: $(LIB)
+ ALLSYMSFLAGS='+forceload' \
+ SHAREDFLAGS='-b -z +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux64
+$(SHLIB).aix: $(LIB)
+ ALLSYMSFLAGS='-bnogc' \
+ SHAREDFLAGS='-G -bE:$(LIBNAME).exp -bM:SRE' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).aix
+
+depend:
+ sed -e '/^# DO NOT DELETE.*/,$$d' < Makefile > Makefile.tmp
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' >> Makefile.tmp
+ gcc -M $(CFLAGS) $(SRC) >> Makefile.tmp
+ perl ../../../util/clean-depend.pl < Makefile.tmp > Makefile.new
+ rm -f Makefile.tmp Makefile
+ mv Makefile.new Makefile
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+rsaref.o: ../../../include/openssl/asn1.h ../../../include/openssl/bio.h
+rsaref.o: ../../../include/openssl/bn.h ../../../include/openssl/crypto.h
+rsaref.o: ../../../include/openssl/dh.h ../../../include/openssl/dsa.h
+rsaref.o: ../../../include/openssl/e_os2.h ../../../include/openssl/engine.h
+rsaref.o: ../../../include/openssl/err.h ../../../include/openssl/lhash.h
+rsaref.o: ../../../include/openssl/opensslconf.h
+rsaref.o: ../../../include/openssl/opensslv.h
+rsaref.o: ../../../include/openssl/ossl_typ.h ../../../include/openssl/rand.h
+rsaref.o: ../../../include/openssl/rsa.h ../../../include/openssl/safestack.h
+rsaref.o: ../../../include/openssl/stack.h ../../../include/openssl/symhacks.h
+rsaref.o: ../../../include/openssl/ui.h rsaref.c rsaref_err.c rsaref_err.h
+rsaref.o: source/des.h source/global.h source/md2.h source/md5.h source/rsa.h
+rsaref.o: source/rsaref.h
diff --git a/crypto/openssl/demos/engines/ibmca/hw_ibmca.c b/crypto/openssl/demos/engines/ibmca/hw_ibmca.c
new file mode 100644
index 0000000..0c2c39b
--- /dev/null
+++ b/crypto/openssl/demos/engines/ibmca/hw_ibmca.c
@@ -0,0 +1,920 @@
+/* crypto/engine/hw_ibmca.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* (C) COPYRIGHT International Business Machines Corp. 2001 */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_IBMCA
+
+#ifdef FLAT_INC
+#include "ica_openssl_api.h"
+#else
+#include "vendor_defns/ica_openssl_api.h"
+#endif
+
+#define IBMCA_LIB_NAME "ibmca engine"
+#include "hw_ibmca_err.c"
+
+static int ibmca_destroy(ENGINE *e);
+static int ibmca_init(ENGINE *e);
+static int ibmca_finish(ENGINE *e);
+static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+static const char *IBMCA_F1 = "icaOpenAdapter";
+static const char *IBMCA_F2 = "icaCloseAdapter";
+static const char *IBMCA_F3 = "icaRsaModExpo";
+static const char *IBMCA_F4 = "icaRandomNumberGenerate";
+static const char *IBMCA_F5 = "icaRsaCrt";
+
+ICA_ADAPTER_HANDLE handle=0;
+
+/* BIGNUM stuff */
+static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx);
+
+static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1,
+ const BIGNUM *iqmp, BN_CTX *ctx);
+
+#ifndef OPENSSL_NO_RSA
+/* RSA stuff */
+static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+
+#ifndef OPENSSL_NO_DSA
+/* DSA stuff */
+static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+ BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *in_mont);
+static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* DH stuff */
+/* This function is alised to mod_exp (with the DH and mont dropped). */
+static int ibmca_mod_exp_dh(const DH *dh, BIGNUM *r,
+ const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+#endif
+
+/* RAND stuff */
+static int ibmca_rand_bytes(unsigned char *buf, int num);
+static int ibmca_rand_status(void);
+
+
+/* WJH - check for more commands, like in nuron */
+
+/* The definitions for control commands specific to this engine */
+#define IBMCA_CMD_SO_PATH ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN ibmca_cmd_defns[] = {
+ {IBMCA_CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the 'atasi' shared library",
+ ENGINE_CMD_FLAG_STRING},
+ {0, NULL, NULL, 0}
+ };
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD ibmca_rsa =
+ {
+ "Ibmca RSA method",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ibmca_rsa_mod_exp,
+ ibmca_mod_exp_mont,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL
+ };
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* Our internal DSA_METHOD that we provide pointers to */
+static DSA_METHOD ibmca_dsa =
+ {
+ "Ibmca DSA method",
+ NULL, /* dsa_do_sign */
+ NULL, /* dsa_sign_setup */
+ NULL, /* dsa_do_verify */
+ ibmca_dsa_mod_exp, /* dsa_mod_exp */
+ ibmca_mod_exp_dsa, /* bn_mod_exp */
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+ NULL /* app_data */
+ };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+static DH_METHOD ibmca_dh =
+ {
+ "Ibmca DH method",
+ NULL,
+ NULL,
+ ibmca_mod_exp_dh,
+ NULL,
+ NULL,
+ 0,
+ NULL
+ };
+#endif
+
+static RAND_METHOD ibmca_rand =
+ {
+ /* "IBMCA RAND method", */
+ NULL,
+ ibmca_rand_bytes,
+ NULL,
+ NULL,
+ ibmca_rand_bytes,
+ ibmca_rand_status,
+ };
+
+/* Constants used when creating the ENGINE */
+static const char *engine_ibmca_id = "ibmca";
+static const char *engine_ibmca_name = "Ibmca hardware engine support";
+
+/* This internal function is used by ENGINE_ibmca() and possibly by the
+ * "dynamic" ENGINE support too */
+static int bind_helper(ENGINE *e)
+ {
+#ifndef OPENSSL_NO_RSA
+ const RSA_METHOD *meth1;
+#endif
+#ifndef OPENSSL_NO_DSA
+ const DSA_METHOD *meth2;
+#endif
+#ifndef OPENSSL_NO_DH
+ const DH_METHOD *meth3;
+#endif
+ if(!ENGINE_set_id(e, engine_ibmca_id) ||
+ !ENGINE_set_name(e, engine_ibmca_name) ||
+#ifndef OPENSSL_NO_RSA
+ !ENGINE_set_RSA(e, &ibmca_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+ !ENGINE_set_DSA(e, &ibmca_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+ !ENGINE_set_DH(e, &ibmca_dh) ||
+#endif
+ !ENGINE_set_RAND(e, &ibmca_rand) ||
+ !ENGINE_set_destroy_function(e, ibmca_destroy) ||
+ !ENGINE_set_init_function(e, ibmca_init) ||
+ !ENGINE_set_finish_function(e, ibmca_finish) ||
+ !ENGINE_set_ctrl_function(e, ibmca_ctrl) ||
+ !ENGINE_set_cmd_defns(e, ibmca_cmd_defns))
+ return 0;
+
+#ifndef OPENSSL_NO_RSA
+ /* We know that the "PKCS1_SSLeay()" functions hook properly
+ * to the ibmca-specific mod_exp and mod_exp_crt so we use
+ * those functions. NB: We don't use ENGINE_openssl() or
+ * anything "more generic" because something like the RSAref
+ * code may not hook properly, and if you own one of these
+ * cards then you have the right to do RSA operations on it
+ * anyway! */
+ meth1 = RSA_PKCS1_SSLeay();
+ ibmca_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+ ibmca_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+ ibmca_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+ ibmca_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+#endif
+
+#ifndef OPENSSL_NO_DSA
+ /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
+ * bits. */
+ meth2 = DSA_OpenSSL();
+ ibmca_dsa.dsa_do_sign = meth2->dsa_do_sign;
+ ibmca_dsa.dsa_sign_setup = meth2->dsa_sign_setup;
+ ibmca_dsa.dsa_do_verify = meth2->dsa_do_verify;
+#endif
+
+#ifndef OPENSSL_NO_DH
+ /* Much the same for Diffie-Hellman */
+ meth3 = DH_OpenSSL();
+ ibmca_dh.generate_key = meth3->generate_key;
+ ibmca_dh.compute_key = meth3->compute_key;
+#endif
+
+ /* Ensure the ibmca error handling is set up */
+ ERR_load_IBMCA_strings();
+ return 1;
+ }
+
+static ENGINE *engine_ibmca(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!bind_helper(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static
+#endif
+void ENGINE_load_ibmca(void)
+ {
+ /* Copied from eng_[openssl|dyn].c */
+ ENGINE *toadd = engine_ibmca();
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ ENGINE_free(toadd);
+ ERR_clear_error();
+ }
+
+/* Destructor (complements the "ENGINE_ibmca()" constructor) */
+static int ibmca_destroy(ENGINE *e)
+ {
+ /* Unload the ibmca error strings so any error state including our
+ * functs or reasons won't lead to a segfault (they simply get displayed
+ * without corresponding string data because none will be found). */
+ ERR_unload_IBMCA_strings();
+ return 1;
+ }
+
+
+/* This is a process-global DSO handle used for loading and unloading
+ * the Ibmca library. NB: This is only set (or unset) during an
+ * init() or finish() call (reference counts permitting) and they're
+ * operating with global locks, so this should be thread-safe
+ * implicitly. */
+
+static DSO *ibmca_dso = NULL;
+
+/* These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded. */
+
+static unsigned int (ICA_CALL *p_icaOpenAdapter)();
+static unsigned int (ICA_CALL *p_icaCloseAdapter)();
+static unsigned int (ICA_CALL *p_icaRsaModExpo)();
+static unsigned int (ICA_CALL *p_icaRandomNumberGenerate)();
+static unsigned int (ICA_CALL *p_icaRsaCrt)();
+
+/* utility function to obtain a context */
+static int get_context(ICA_ADAPTER_HANDLE *p_handle)
+ {
+ unsigned int status=0;
+
+ status = p_icaOpenAdapter(0, p_handle);
+ if(status != 0)
+ return 0;
+ return 1;
+ }
+
+/* similarly to release one. */
+static void release_context(ICA_ADAPTER_HANDLE handle)
+ {
+ p_icaCloseAdapter(handle);
+ }
+
+/* (de)initialisation functions. */
+static int ibmca_init(ENGINE *e)
+ {
+
+ void (*p1)();
+ void (*p2)();
+ void (*p3)();
+ void (*p4)();
+ void (*p5)();
+
+ if(ibmca_dso != NULL)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_ALREADY_LOADED);
+ goto err;
+ }
+ /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be
+ * changed unfortunately because the Ibmca drivers don't have
+ * standard library names that can be platform-translated well. */
+ /* TODO: Work out how to actually map to the names the Ibmca
+ * drivers really use - for now a symbollic link needs to be
+ * created on the host system from libatasi.so to atasi.so on
+ * unix variants. */
+
+ /* WJH XXX check name translation */
+
+ ibmca_dso = DSO_load(NULL, IBMCA_LIBNAME, NULL,
+ /* DSO_FLAG_NAME_TRANSLATION */ 0);
+ if(ibmca_dso == NULL)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE);
+ goto err;
+ }
+
+ if(!(p1 = DSO_bind_func(
+ ibmca_dso, IBMCA_F1)) ||
+ !(p2 = DSO_bind_func(
+ ibmca_dso, IBMCA_F2)) ||
+ !(p3 = DSO_bind_func(
+ ibmca_dso, IBMCA_F3)) ||
+ !(p4 = DSO_bind_func(
+ ibmca_dso, IBMCA_F4)) ||
+ !(p5 = DSO_bind_func(
+ ibmca_dso, IBMCA_F5)))
+ {
+ IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE);
+ goto err;
+ }
+
+ /* Copy the pointers */
+
+ p_icaOpenAdapter = (unsigned int (ICA_CALL *)())p1;
+ p_icaCloseAdapter = (unsigned int (ICA_CALL *)())p2;
+ p_icaRsaModExpo = (unsigned int (ICA_CALL *)())p3;
+ p_icaRandomNumberGenerate = (unsigned int (ICA_CALL *)())p4;
+ p_icaRsaCrt = (unsigned int (ICA_CALL *)())p5;
+
+ if(!get_context(&handle))
+ {
+ IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_UNIT_FAILURE);
+ goto err;
+ }
+
+ return 1;
+ err:
+ if(ibmca_dso)
+ DSO_free(ibmca_dso);
+
+ p_icaOpenAdapter = NULL;
+ p_icaCloseAdapter = NULL;
+ p_icaRsaModExpo = NULL;
+ p_icaRandomNumberGenerate = NULL;
+
+ return 0;
+ }
+
+static int ibmca_finish(ENGINE *e)
+ {
+ if(ibmca_dso == NULL)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_NOT_LOADED);
+ return 0;
+ }
+ release_context(handle);
+ if(!DSO_free(ibmca_dso))
+ {
+ IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_DSO_FAILURE);
+ return 0;
+ }
+ ibmca_dso = NULL;
+
+ return 1;
+ }
+
+static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+ {
+ int initialised = ((ibmca_dso == NULL) ? 0 : 1);
+ switch(cmd)
+ {
+ case IBMCA_CMD_SO_PATH:
+ if(p == NULL)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if(initialised)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_ALREADY_LOADED);
+ return 0;
+ }
+ IBMCA_LIBNAME = (const char *)p;
+ return 1;
+ default:
+ break;
+ }
+ IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+
+static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx)
+ {
+ /* I need somewhere to store temporary serialised values for
+ * use with the Ibmca API calls. A neat cheat - I'll use
+ * BIGNUMs from the BN_CTX but access their arrays directly as
+ * byte arrays <grin>. This way I don't have to clean anything
+ * up. */
+
+ BIGNUM *argument=NULL;
+ BIGNUM *result=NULL;
+ BIGNUM *key=NULL;
+ int to_return;
+ int inLen, outLen, tmpLen;
+
+
+ ICA_KEY_RSA_MODEXPO *publKey=NULL;
+ unsigned int rc;
+
+ to_return = 0; /* expect failure */
+
+ if(!ibmca_dso)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_NOT_LOADED);
+ goto err;
+ }
+ /* Prepare the params */
+ BN_CTX_start(ctx);
+ argument = BN_CTX_get(ctx);
+ result = BN_CTX_get(ctx);
+ key = BN_CTX_get(ctx);
+
+ if( !argument || !result || !key)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_CTX_FULL);
+ goto err;
+ }
+
+
+ if(!bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top) ||
+ !bn_wexpand(key, sizeof(*publKey)/BN_BYTES))
+
+ {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_EXPAND_FAIL);
+ goto err;
+ }
+
+ publKey = (ICA_KEY_RSA_MODEXPO *)key->d;
+
+ if (publKey == NULL)
+ {
+ goto err;
+ }
+ memset(publKey, 0, sizeof(ICA_KEY_RSA_MODEXPO));
+
+ publKey->keyType = CORRECT_ENDIANNESS(ME_KEY_TYPE);
+ publKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_MODEXPO));
+ publKey->expOffset = (char *) publKey->keyRecord - (char *) publKey;
+
+ /* A quirk of the card: the exponent length has to be the same
+ as the modulus (key) length */
+
+ outLen = BN_num_bytes(m);
+
+/* check for modulus length SAB*/
+ if (outLen > 256 ) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_MEXP_LENGTH_TO_LARGE);
+ goto err;
+ }
+/* check for modulus length SAB*/
+
+
+ publKey->expLength = publKey->nLength = outLen;
+/* SAB Check for underflow condition
+ the size of the exponent is less than the size of the parameter
+ then we have a big problem and will underflow the keyRecord
+ buffer. Bad stuff could happen then
+*/
+if (outLen < BN_num_bytes(p)){
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_UNDERFLOW_KEYRECORD);
+ goto err;
+}
+/* SAB End check for underflow */
+
+
+ BN_bn2bin(p, &publKey->keyRecord[publKey->expLength -
+ BN_num_bytes(p)]);
+ BN_bn2bin(m, &publKey->keyRecord[publKey->expLength]);
+
+
+
+ publKey->modulusBitLength = CORRECT_ENDIANNESS(publKey->nLength * 8);
+ publKey->nOffset = CORRECT_ENDIANNESS(publKey->expOffset +
+ publKey->expLength);
+
+ publKey->expOffset = CORRECT_ENDIANNESS((char *) publKey->keyRecord -
+ (char *) publKey);
+
+ tmpLen = outLen;
+ publKey->expLength = publKey->nLength = CORRECT_ENDIANNESS(tmpLen);
+
+ /* Prepare the argument */
+
+ memset(argument->d, 0, outLen);
+ BN_bn2bin(a, (unsigned char *)argument->d + outLen -
+ BN_num_bytes(a));
+
+ inLen = outLen;
+
+ /* Perform the operation */
+
+ if( (rc = p_icaRsaModExpo(handle, inLen,(unsigned char *)argument->d,
+ publKey, &outLen, (unsigned char *)result->d))
+ !=0 )
+
+ {
+ printf("rc = %d\n", rc);
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_REQUEST_FAILED);
+ goto err;
+ }
+
+
+ /* Convert the response */
+ BN_bin2bn((unsigned char *)result->d, outLen, r);
+ to_return = 1;
+ err:
+ BN_CTX_end(ctx);
+ return to_return;
+ }
+
+#ifndef OPENSSL_NO_RSA
+static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+ {
+ BN_CTX *ctx;
+ int to_return = 0;
+
+ if((ctx = BN_CTX_new()) == NULL)
+ goto err;
+ if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
+ {
+ if(!rsa->d || !rsa->n)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP,
+ IBMCA_R_MISSING_KEY_COMPONENTS);
+ goto err;
+ }
+ to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx);
+ }
+ else
+ {
+ to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
+ rsa->dmq1, rsa->iqmp, ctx);
+ }
+ err:
+ if(ctx)
+ BN_CTX_free(ctx);
+ return to_return;
+ }
+#endif
+
+/* Ein kleines chinesisches "Restessen" */
+static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *q, const BIGNUM *dmp1,
+ const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx)
+ {
+
+ BIGNUM *argument = NULL;
+ BIGNUM *result = NULL;
+ BIGNUM *key = NULL;
+
+ int to_return = 0; /* expect failure */
+
+ char *pkey=NULL;
+ ICA_KEY_RSA_CRT *privKey=NULL;
+ int inLen, outLen;
+
+ int rc;
+ unsigned int offset, pSize, qSize;
+/* SAB New variables */
+ unsigned int keyRecordSize;
+ unsigned int pbytes = BN_num_bytes(p);
+ unsigned int qbytes = BN_num_bytes(q);
+ unsigned int dmp1bytes = BN_num_bytes(dmp1);
+ unsigned int dmq1bytes = BN_num_bytes(dmq1);
+ unsigned int iqmpbytes = BN_num_bytes(iqmp);
+
+ /* Prepare the params */
+
+ BN_CTX_start(ctx);
+ argument = BN_CTX_get(ctx);
+ result = BN_CTX_get(ctx);
+ key = BN_CTX_get(ctx);
+
+ if(!argument || !result || !key)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_CTX_FULL);
+ goto err;
+ }
+
+ if(!bn_wexpand(argument, p->top + q->top) ||
+ !bn_wexpand(result, p->top + q->top) ||
+ !bn_wexpand(key, sizeof(*privKey)/BN_BYTES ))
+ {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_EXPAND_FAIL);
+ goto err;
+ }
+
+
+ privKey = (ICA_KEY_RSA_CRT *)key->d;
+/* SAB Add check for total size in bytes of the parms does not exceed
+ the buffer space we have
+ do this first
+*/
+ keyRecordSize = pbytes+qbytes+dmp1bytes+dmq1bytes+iqmpbytes;
+ if ( keyRecordSize > sizeof(privKey->keyRecord )) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
+ goto err;
+ }
+
+ if ( (qbytes + dmq1bytes) > 256 ){
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
+ goto err;
+ }
+
+ if ( pbytes + dmp1bytes > 256 ) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
+ goto err;
+ }
+
+/* end SAB additions */
+
+ memset(privKey, 0, sizeof(ICA_KEY_RSA_CRT));
+ privKey->keyType = CORRECT_ENDIANNESS(CRT_KEY_TYPE);
+ privKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_CRT));
+ privKey->modulusBitLength =
+ CORRECT_ENDIANNESS(BN_num_bytes(q) * 2 * 8);
+
+ /*
+ * p,dp & qInv are 1 QWORD Larger
+ */
+ privKey->pLength = CORRECT_ENDIANNESS(BN_num_bytes(p)+8);
+ privKey->qLength = CORRECT_ENDIANNESS(BN_num_bytes(q));
+ privKey->dpLength = CORRECT_ENDIANNESS(BN_num_bytes(dmp1)+8);
+ privKey->dqLength = CORRECT_ENDIANNESS(BN_num_bytes(dmq1));
+ privKey->qInvLength = CORRECT_ENDIANNESS(BN_num_bytes(iqmp)+8);
+
+ offset = (char *) privKey->keyRecord
+ - (char *) privKey;
+
+ qSize = BN_num_bytes(q);
+ pSize = qSize + 8; /* 1 QWORD larger */
+
+
+/* SAB probably aittle redundant, but we'll verify that each of the
+ components which make up a key record sent ot the card does not exceed
+ the space that is allocated for it. this handles the case where even if
+ the total length does not exceed keyrecord zied, if the operands are funny sized
+they could cause potential side affects on either the card or the result */
+
+ if ( (pbytes > pSize) || (dmp1bytes > pSize) ||
+ (iqmpbytes > pSize) || ( qbytes >qSize) ||
+ (dmq1bytes > qSize) ) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_OPERANDS_TO_LARGE);
+ goto err;
+
+ }
+
+
+ privKey->dpOffset = CORRECT_ENDIANNESS(offset);
+
+ offset += pSize;
+ privKey->dqOffset = CORRECT_ENDIANNESS(offset);
+
+ offset += qSize;
+ privKey->pOffset = CORRECT_ENDIANNESS(offset);
+
+ offset += pSize;
+ privKey->qOffset = CORRECT_ENDIANNESS(offset);
+
+ offset += qSize;
+ privKey->qInvOffset = CORRECT_ENDIANNESS(offset);
+
+ pkey = (char *) privKey->keyRecord;
+
+
+/* SAB first check that we don;t under flow the buffer */
+ if ( pSize < pbytes ) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_UNDERFLOW_CONDITION);
+ goto err;
+ }
+
+ /* pkey += pSize - BN_num_bytes(p); WROING this should be dmp1) */
+ pkey += pSize - BN_num_bytes(dmp1);
+ BN_bn2bin(dmp1, pkey);
+ pkey += BN_num_bytes(dmp1); /* move the pointer */
+
+ BN_bn2bin(dmq1, pkey); /* Copy over dmq1 */
+
+ pkey += qSize; /* move pointer */
+ pkey += pSize - BN_num_bytes(p); /* set up for zero padding of next field */
+
+ BN_bn2bin(p, pkey);
+ pkey += BN_num_bytes(p); /* increment pointer by number of bytes moved */
+
+ BN_bn2bin(q, pkey);
+ pkey += qSize ; /* move the pointer */
+ pkey += pSize - BN_num_bytes(iqmp); /* Adjust for padding */
+ BN_bn2bin(iqmp, pkey);
+
+ /* Prepare the argument and response */
+
+ outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2; /* Correct endianess is used
+ because the fields were converted above */
+
+ if (outLen > 256) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OUTLEN_TO_LARGE);
+ goto err;
+ }
+
+ /* SAB check for underflow here on the argeument */
+ if ( outLen < BN_num_bytes(a)) {
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_UNDERFLOW_CONDITION);
+ goto err;
+ }
+
+ BN_bn2bin(a, (unsigned char *)argument->d + outLen -
+ BN_num_bytes(a));
+ inLen = outLen;
+
+ memset(result->d, 0, outLen);
+
+ /* Perform the operation */
+
+ if ( (rc = p_icaRsaCrt(handle, inLen, (unsigned char *)argument->d,
+ privKey, &outLen, (unsigned char *)result->d)) != 0)
+ {
+ printf("rc = %d\n", rc);
+ IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_REQUEST_FAILED);
+ goto err;
+ }
+
+ /* Convert the response */
+
+ BN_bin2bn((unsigned char *)result->d, outLen, r);
+ to_return = 1;
+
+ err:
+ BN_CTX_end(ctx);
+ return to_return;
+
+ }
+
+#ifndef OPENSSL_NO_DSA
+/* This code was liberated and adapted from the commented-out code in
+ * dsa_ossl.c. Because of the unoptimised form of the Ibmca acceleration
+ * (it doesn't have a CRT form for RSA), this function means that an
+ * Ibmca system running with a DSA server certificate can handshake
+ * around 5 or 6 times faster/more than an equivalent system running with
+ * RSA. Just check out the "signs" statistics from the RSA and DSA parts
+ * of "openssl speed -engine ibmca dsa1024 rsa1024". */
+static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+ BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *in_mont)
+ {
+ BIGNUM t;
+ int to_return = 0;
+
+ BN_init(&t);
+ /* let rr = a1 ^ p1 mod m */
+ if (!ibmca_mod_exp(rr,a1,p1,m,ctx)) goto end;
+ /* let t = a2 ^ p2 mod m */
+ if (!ibmca_mod_exp(&t,a2,p2,m,ctx)) goto end;
+ /* let rr = rr * t mod m */
+ if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
+ to_return = 1;
+ end:
+ BN_free(&t);
+ return to_return;
+ }
+
+
+static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx)
+ {
+ return ibmca_mod_exp(r, a, p, m, ctx);
+ }
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+ {
+ return ibmca_mod_exp(r, a, p, m, ctx);
+ }
+
+#ifndef OPENSSL_NO_DH
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int ibmca_mod_exp_dh(DH const *dh, BIGNUM *r,
+ const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+ {
+ return ibmca_mod_exp(r, a, p, m, ctx);
+ }
+#endif
+
+/* Random bytes are good */
+static int ibmca_rand_bytes(unsigned char *buf, int num)
+ {
+ int to_return = 0; /* assume failure */
+ unsigned int ret;
+
+
+ if(handle == 0)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_NOT_INITIALISED);
+ goto err;
+ }
+
+ ret = p_icaRandomNumberGenerate(handle, num, buf);
+ if (ret < 0)
+ {
+ IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_REQUEST_FAILED);
+ goto err;
+ }
+ to_return = 1;
+ err:
+ return to_return;
+ }
+
+static int ibmca_rand_status(void)
+ {
+ return 1;
+ }
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+ {
+ if(id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */
+ return 0;
+ if(!bind_helper(e))
+ return 0;
+ return 1;
+ }
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+
+#endif /* !OPENSSL_NO_HW_IBMCA */
+#endif /* !OPENSSL_NO_HW */
diff --git a/crypto/openssl/demos/engines/ibmca/hw_ibmca.ec b/crypto/openssl/demos/engines/ibmca/hw_ibmca.ec
new file mode 100644
index 0000000..f68646d
--- /dev/null
+++ b/crypto/openssl/demos/engines/ibmca/hw_ibmca.ec
@@ -0,0 +1,8 @@
+# configuration file for util/mkerr.pl
+#
+# use like this:
+#
+# perl ../../../util/mkerr.pl -conf hw_ibmca.ec \
+# -nostatic -staticloader -write *.c
+
+L IBMCA hw_ibmca_err.h hw_ibmca_err.c
diff --git a/crypto/openssl/demos/engines/ibmca/hw_ibmca_err.c b/crypto/openssl/demos/engines/ibmca/hw_ibmca_err.c
new file mode 100644
index 0000000..c4053f6
--- /dev/null
+++ b/crypto/openssl/demos/engines/ibmca/hw_ibmca_err.c
@@ -0,0 +1,154 @@
+/* hw_ibmca_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_ibmca_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA IBMCA_str_functs[]=
+ {
+{ERR_PACK(0,IBMCA_F_IBMCA_CTRL,0), "IBMCA_CTRL"},
+{ERR_PACK(0,IBMCA_F_IBMCA_FINISH,0), "IBMCA_FINISH"},
+{ERR_PACK(0,IBMCA_F_IBMCA_INIT,0), "IBMCA_INIT"},
+{ERR_PACK(0,IBMCA_F_IBMCA_MOD_EXP,0), "IBMCA_MOD_EXP"},
+{ERR_PACK(0,IBMCA_F_IBMCA_MOD_EXP_CRT,0), "IBMCA_MOD_EXP_CRT"},
+{ERR_PACK(0,IBMCA_F_IBMCA_RAND_BYTES,0), "IBMCA_RAND_BYTES"},
+{ERR_PACK(0,IBMCA_F_IBMCA_RSA_MOD_EXP,0), "IBMCA_RSA_MOD_EXP"},
+{0,NULL}
+ };
+
+static ERR_STRING_DATA IBMCA_str_reasons[]=
+ {
+{IBMCA_R_ALREADY_LOADED ,"already loaded"},
+{IBMCA_R_BN_CTX_FULL ,"bn ctx full"},
+{IBMCA_R_BN_EXPAND_FAIL ,"bn expand fail"},
+{IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"},
+{IBMCA_R_DSO_FAILURE ,"dso failure"},
+{IBMCA_R_MEXP_LENGTH_TO_LARGE ,"mexp length to large"},
+{IBMCA_R_MISSING_KEY_COMPONENTS ,"missing key components"},
+{IBMCA_R_NOT_INITIALISED ,"not initialised"},
+{IBMCA_R_NOT_LOADED ,"not loaded"},
+{IBMCA_R_OPERANDS_TO_LARGE ,"operands to large"},
+{IBMCA_R_OUTLEN_TO_LARGE ,"outlen to large"},
+{IBMCA_R_REQUEST_FAILED ,"request failed"},
+{IBMCA_R_UNDERFLOW_CONDITION ,"underflow condition"},
+{IBMCA_R_UNDERFLOW_KEYRECORD ,"underflow keyrecord"},
+{IBMCA_R_UNIT_FAILURE ,"unit failure"},
+{0,NULL}
+ };
+
+#endif
+
+#ifdef IBMCA_LIB_NAME
+static ERR_STRING_DATA IBMCA_lib_name[]=
+ {
+{0 ,IBMCA_LIB_NAME},
+{0,NULL}
+ };
+#endif
+
+
+static int IBMCA_lib_error_code=0;
+static int IBMCA_error_init=1;
+
+static void ERR_load_IBMCA_strings(void)
+ {
+ if (IBMCA_lib_error_code == 0)
+ IBMCA_lib_error_code=ERR_get_next_error_library();
+
+ if (IBMCA_error_init)
+ {
+ IBMCA_error_init=0;
+#ifndef OPENSSL_NO_ERR
+ ERR_load_strings(IBMCA_lib_error_code,IBMCA_str_functs);
+ ERR_load_strings(IBMCA_lib_error_code,IBMCA_str_reasons);
+#endif
+
+#ifdef IBMCA_LIB_NAME
+ IBMCA_lib_name->error = ERR_PACK(IBMCA_lib_error_code,0,0);
+ ERR_load_strings(0,IBMCA_lib_name);
+#endif
+ }
+ }
+
+static void ERR_unload_IBMCA_strings(void)
+ {
+ if (IBMCA_error_init == 0)
+ {
+#ifndef OPENSSL_NO_ERR
+ ERR_unload_strings(IBMCA_lib_error_code,IBMCA_str_functs);
+ ERR_unload_strings(IBMCA_lib_error_code,IBMCA_str_reasons);
+#endif
+
+#ifdef IBMCA_LIB_NAME
+ ERR_unload_strings(0,IBMCA_lib_name);
+#endif
+ IBMCA_error_init=1;
+ }
+ }
+
+static void ERR_IBMCA_error(int function, int reason, char *file, int line)
+ {
+ if (IBMCA_lib_error_code == 0)
+ IBMCA_lib_error_code=ERR_get_next_error_library();
+ ERR_PUT_error(IBMCA_lib_error_code,function,reason,file,line);
+ }
diff --git a/crypto/openssl/demos/engines/ibmca/hw_ibmca_err.h b/crypto/openssl/demos/engines/ibmca/hw_ibmca_err.h
new file mode 100644
index 0000000..da64bde
--- /dev/null
+++ b/crypto/openssl/demos/engines/ibmca/hw_ibmca_err.h
@@ -0,0 +1,98 @@
+/* ====================================================================
+ * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_IBMCA_ERR_H
+#define HEADER_IBMCA_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_IBMCA_strings(void);
+static void ERR_unload_IBMCA_strings(void);
+static void ERR_IBMCA_error(int function, int reason, char *file, int line);
+#define IBMCAerr(f,r) ERR_IBMCA_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the IBMCA functions. */
+
+/* Function codes. */
+#define IBMCA_F_IBMCA_CTRL 100
+#define IBMCA_F_IBMCA_FINISH 101
+#define IBMCA_F_IBMCA_INIT 102
+#define IBMCA_F_IBMCA_MOD_EXP 103
+#define IBMCA_F_IBMCA_MOD_EXP_CRT 104
+#define IBMCA_F_IBMCA_RAND_BYTES 105
+#define IBMCA_F_IBMCA_RSA_MOD_EXP 106
+
+/* Reason codes. */
+#define IBMCA_R_ALREADY_LOADED 100
+#define IBMCA_R_BN_CTX_FULL 101
+#define IBMCA_R_BN_EXPAND_FAIL 102
+#define IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED 103
+#define IBMCA_R_DSO_FAILURE 104
+#define IBMCA_R_MEXP_LENGTH_TO_LARGE 105
+#define IBMCA_R_MISSING_KEY_COMPONENTS 106
+#define IBMCA_R_NOT_INITIALISED 107
+#define IBMCA_R_NOT_LOADED 108
+#define IBMCA_R_OPERANDS_TO_LARGE 109
+#define IBMCA_R_OUTLEN_TO_LARGE 110
+#define IBMCA_R_REQUEST_FAILED 111
+#define IBMCA_R_UNDERFLOW_CONDITION 112
+#define IBMCA_R_UNDERFLOW_KEYRECORD 113
+#define IBMCA_R_UNIT_FAILURE 114
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/openssl/demos/engines/ibmca/ica_openssl_api.h b/crypto/openssl/demos/engines/ibmca/ica_openssl_api.h
new file mode 100644
index 0000000..c77e0fd
--- /dev/null
+++ b/crypto/openssl/demos/engines/ibmca/ica_openssl_api.h
@@ -0,0 +1,189 @@
+
+#ifndef __ICA_OPENSSL_API_H__
+#define __ICA_OPENSSL_API_H__
+
+/**
+ ** abstract data types for API
+ **/
+
+#define ICA_ADAPTER_HANDLE int
+
+#if defined(linux) || defined (_AIX)
+#define ICA_CALL
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+#define ICA_CALL __stdcall
+#endif
+
+/*------------------------------------------------*
+ | RSA defines and typedefs |
+ *------------------------------------------------*/
+ /*
+ * All data elements of the RSA key are in big-endian format
+ * Modulus-Exponent form of key
+ *
+ */
+ #define MAX_EXP_SIZE 256
+ #define MAX_MODULUS_SIZE 256
+ #define MAX_MODEXP_SIZE (MAX_EXP_SIZE + MAX_MODULUS_SIZE)
+
+ #define MAX_OPERAND_SIZE MAX_EXP_SIZE
+
+ typedef unsigned char ICA_KEY_RSA_MODEXPO_REC[MAX_MODEXP_SIZE];
+ /*
+ * All data elements of the RSA key are in big-endian format
+ * Chinese Remainder Thereom(CRT) form of key
+ * Used only for Decrypt, the encrypt form is typically Modulus-Exponent
+ *
+ */
+ #define MAX_BP_SIZE 136
+ #define MAX_BQ_SIZE 128
+ #define MAX_NP_SIZE 136
+ #define MAX_NQ_SIZE 128
+ #define MAX_QINV_SIZE 136
+ #define MAX_RSACRT_SIZE (MAX_BP_SIZE+MAX_BQ_SIZE+MAX_NP_SIZE+MAX_NQ_SIZE+MAX_QINV_SIZE)
+
+#define RSA_GEN_OPERAND_MAX 256 /* bytes */
+
+typedef unsigned char ICA_KEY_RSA_CRT_REC[MAX_RSACRT_SIZE];
+/*------------------------------------------------*
+ | RSA key token types |
+ *------------------------------------------------*/
+
+#define RSA_PUBLIC_MODULUS_EXPONENT 3
+#define RSA_PKCS_PRIVATE_CHINESE_REMAINDER 6
+
+#define KEYTYPE_MODEXPO 1
+#define KEYTYPE_PKCSCRT 2
+
+
+/*------------------------------------------------*
+ | RSA Key Token format |
+ *------------------------------------------------*/
+
+/*
+ * NOTE: All the fields in the ICA_KEY_RSA_MODEXPO structure
+ * (lengths, offsets, exponents, modulus, etc.) are
+ * stored in big-endian format
+ */
+
+typedef struct _ICA_KEY_RSA_MODEXPO
+{ unsigned int keyType; /* RSA key type. */
+ unsigned int keyLength; /* Total length of the token. */
+ unsigned int modulusBitLength; /* Modulus n bit length. */
+ /* -- Start of the data length.*/
+ unsigned int nLength; /* Modulus n = p * q */
+ unsigned int expLength; /* exponent (public or private)*/
+ /* e = 1/d * mod(p-1)(q-1) */
+ /* -- Start of the data offsets*/
+ unsigned int nOffset; /* Modulus n . */
+ unsigned int expOffset; /* exponent (public or private)*/
+ unsigned char reserved[112]; /* reserved area */
+ /* -- Start of the variable -- */
+ /* -- length token data. -- */
+ ICA_KEY_RSA_MODEXPO_REC keyRecord;
+} ICA_KEY_RSA_MODEXPO;
+#define SZ_HEADER_MODEXPO (sizeof(ICA_KEY_RSA_MODEXPO) - sizeof(ICA_KEY_RSA_MODEXPO_REC))
+
+/*
+ * NOTE: All the fields in the ICA_KEY_RSA_CRT structure
+ * (lengths, offsets, exponents, modulus, etc.) are
+ * stored in big-endian format
+ */
+
+typedef struct _ICA_KEY_RSA_CRT
+{ unsigned int keyType; /* RSA key type. */
+ unsigned int keyLength; /* Total length of the token. */
+ unsigned int modulusBitLength; /* Modulus n bit length. */
+ /* -- Start of the data length.*/
+#if _AIX
+ unsigned int nLength; /* Modulus n = p * q */
+#endif
+ unsigned int pLength; /* Prime number p . */
+ unsigned int qLength; /* Prime number q . */
+ unsigned int dpLength; /* dp = d * mod(p-1) . */
+ unsigned int dqLength; /* dq = d * mod(q-1) . */
+ unsigned int qInvLength; /* PKCS: qInv = Ap/q */
+ /* -- Start of the data offsets*/
+#if _AIX
+ unsigned int nOffset; /* Modulus n . */
+#endif
+ unsigned int pOffset; /* Prime number p . */
+ unsigned int qOffset; /* Prime number q . */
+ unsigned int dpOffset; /* dp . */
+ unsigned int dqOffset; /* dq . */
+ unsigned int qInvOffset; /* qInv for PKCS */
+#if _AIX
+ unsigned char reserved[80]; /* reserved area */
+#else
+ unsigned char reserved[88]; /* reserved area */
+#endif
+ /* -- Start of the variable -- */
+ /* -- length token data. -- */
+ ICA_KEY_RSA_CRT_REC keyRecord;
+} ICA_KEY_RSA_CRT;
+#define SZ_HEADER_CRT (sizeof(ICA_KEY_RSA_CRT) - sizeof(ICA_KEY_RSA_CRT_REC))
+
+unsigned int
+icaOpenAdapter( unsigned int adapterId,
+ ICA_ADAPTER_HANDLE *pAdapterHandle );
+
+unsigned int
+icaCloseAdapter( ICA_ADAPTER_HANDLE adapterHandle );
+
+unsigned int
+icaRsaModExpo( ICA_ADAPTER_HANDLE hAdapterHandle,
+ unsigned int inputDataLength,
+ unsigned char *pInputData,
+ ICA_KEY_RSA_MODEXPO *pKeyModExpo,
+ unsigned int *pOutputDataLength,
+ unsigned char *pOutputData );
+
+unsigned int
+icaRsaCrt( ICA_ADAPTER_HANDLE hAdapterHandle,
+ unsigned int inputDataLength,
+ unsigned char *pInputData,
+ ICA_KEY_RSA_CRT *pKeyCrt,
+ unsigned int *pOutputDataLength,
+ unsigned char *pOutputData );
+
+unsigned int
+icaRandomNumberGenerate( ICA_ADAPTER_HANDLE hAdapterHandle,
+ unsigned int outputDataLength,
+ unsigned char *pOutputData );
+
+/* Specific macros and definitions to not have IFDEF;s all over the
+ main code */
+
+#if (_AIX)
+static const char *IBMCA_LIBNAME = "/lib/libica.a(shr.o)";
+#elif (WIN32)
+static const char *IBMCA_LIBNAME = "cryptica";
+#else
+static const char *IBMCA_LIBNAME = "ica";
+#endif
+
+#if (WIN32)
+/*
+ The ICA_KEY_RSA_MODEXPO & ICA_KEY_RSA_CRT lengths and
+ offsets must be in big-endian format.
+
+*/
+#define CORRECT_ENDIANNESS(b) ( \
+ (((unsigned long) (b) & 0x000000ff) << 24) | \
+ (((unsigned long) (b) & 0x0000ff00) << 8) | \
+ (((unsigned long) (b) & 0x00ff0000) >> 8) | \
+ (((unsigned long) (b) & 0xff000000) >> 24) \
+ )
+#define CRT_KEY_TYPE RSA_PKCS_PRIVATE_CHINESE_REMAINDER
+#define ME_KEY_TYPE RSA_PUBLIC_MODULUS_EXPONENT
+#else
+#define CORRECT_ENDIANNESS(b) (b)
+#define CRT_KEY_TYPE KEYTYPE_PKCSCRT
+#define ME_KEY_TYPE KEYTYPE_MODEXPO
+#endif
+
+
+
+#endif /* __ICA_OPENSSL_API_H__ */
diff --git a/crypto/openssl/demos/engines/rsaref/Makefile b/crypto/openssl/demos/engines/rsaref/Makefile
new file mode 100644
index 0000000..63b8c79
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/Makefile
@@ -0,0 +1,135 @@
+LIBNAME= librsaref
+SRC= rsaref.c
+OBJ= rsaref.o
+HEADER= rsaref.h
+
+CC= gcc
+PIC= -fPIC
+CFLAGS= -g -I../../../include $(PIC) -DENGINE_DYNAMIC_SUPPORT
+AR= ar r
+RANLIB= ranlib
+
+LIB= $(LIBNAME).a
+SHLIB= $(LIBNAME).so
+
+all:
+ @echo 'Please choose a system to build on:'
+ @echo ''
+ @echo 'tru64: Tru64 Unix, Digital Unix, Digital OSF/1'
+ @echo 'solaris: Solaris'
+ @echo 'irix: IRIX'
+ @echo 'hpux32: 32-bit HP/UX'
+ @echo 'hpux64: 64-bit HP/UX'
+ @echo 'aix: AIX'
+ @echo 'gnu: Generic GNU-based system (gcc and GNU ld)'
+ @echo ''
+
+FORCE.install:
+install: FORCE.install
+ cd install; \
+ make -f unix/makefile CFLAGS='-I. -DPROTOTYPES=1 -O -c' RSAREFLIB=librsaref.a librsaref.a
+
+FORCE.update:
+update: FORCE.update
+ perl ../../../util/mkerr.pl -conf rsaref.ec \
+ -nostatic -staticloader -write rsaref.c
+
+darwin: install $(SHLIB).darwin
+cygwin: install $(SHLIB).cygwin
+gnu: install $(SHLIB).gnu
+alpha-osf1: install $(SHLIB).alpha-osf1
+tru64: install $(SHLIB).tru64
+solaris: install $(SHLIB).solaris
+irix: install $(SHLIB).irix
+hpux32: install $(SHLIB).hpux32
+hpux64: install $(SHLIB).hpux64
+aix: install $(SHLIB).aix
+reliantunix: install $(SHLIB).reliantunix
+
+$(LIB): $(OBJ)
+ $(AR) $(LIB) $(OBJ)
+ - $(RANLIB) $(LIB)
+
+LINK_SO= \
+ ld -r -o $(LIBNAME).o $$ALLSYMSFLAGS $(LIB) install/librsaref.a && \
+ (nm -Pg $(LIBNAME).o | grep ' [BDT] ' | cut -f1 -d' ' > $(LIBNAME).exp; \
+ $$SHAREDCMD $$SHAREDFLAGS -o $(SHLIB) $(LIBNAME).o -L ../../.. -lcrypto -lc)
+
+$(SHLIB).darwin: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='-all_load' \
+ SHAREDFLAGS='-dynamiclib -install_name $(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).darwin
+$(SHLIB).cygwin: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='--whole-archive' \
+ SHAREDFLAGS='-shared -Wl,-Bsymbolic -Wl,--out-implib,$(LIBNAME).dll.a' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).cygwin
+$(SHLIB).gnu: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='--whole-archive' \
+ SHAREDFLAGS='-shared -Wl,-soname=$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).gnu
+$(SHLIB).tru64: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).tru64
+$(SHLIB).solaris: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='-z allextract' \
+ SHAREDFLAGS='-G -h $(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).solaris
+$(SHLIB).irix: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared -Wl,-soname,$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).irix
+$(SHLIB).hpux32: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='-Fl' \
+ SHAREDFLAGS='+vnocompatwarnings -b -z +s +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux32
+$(SHLIB).hpux64: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='+forceload' \
+ SHAREDFLAGS='-b -z +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux64
+$(SHLIB).aix: $(LIB) install/librsaref.a
+ ALLSYMSFLAGS='-bnogc' \
+ SHAREDFLAGS='-G -bE:$(LIBNAME).exp -bM:SRE' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).aix
+
+depend:
+ sed -e '/^# DO NOT DELETE.*/,$$d' < Makefile > Makefile.tmp
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' >> Makefile.tmp
+ gcc -M $(CFLAGS) $(SRC) >> Makefile.tmp
+ perl ../../../util/clean-depend.pl < Makefile.tmp > Makefile.new
+ rm -f Makefile.tmp Makefile
+ mv Makefile.new Makefile
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+rsaref.o: ../../../include/openssl/asn1.h ../../../include/openssl/bio.h
+rsaref.o: ../../../include/openssl/bn.h ../../../include/openssl/crypto.h
+rsaref.o: ../../../include/openssl/dh.h ../../../include/openssl/dsa.h
+rsaref.o: ../../../include/openssl/e_os2.h ../../../include/openssl/engine.h
+rsaref.o: ../../../include/openssl/err.h ../../../include/openssl/lhash.h
+rsaref.o: ../../../include/openssl/opensslconf.h
+rsaref.o: ../../../include/openssl/opensslv.h
+rsaref.o: ../../../include/openssl/ossl_typ.h ../../../include/openssl/rand.h
+rsaref.o: ../../../include/openssl/rsa.h ../../../include/openssl/safestack.h
+rsaref.o: ../../../include/openssl/stack.h ../../../include/openssl/symhacks.h
+rsaref.o: ../../../include/openssl/ui.h rsaref.c rsaref_err.c rsaref_err.h
+rsaref.o: source/des.h source/global.h source/md2.h source/md5.h source/rsa.h
+rsaref.o: source/rsaref.h
diff --git a/crypto/openssl/demos/engines/rsaref/README b/crypto/openssl/demos/engines/rsaref/README
new file mode 100644
index 0000000..00b1f74
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/README
@@ -0,0 +1,22 @@
+librsaref.so is a demonstration dynamic engine that does RSA
+operations using the old RSAref 2.0 implementation.
+
+To make proper use of this engine, you must download RSAref 2.0
+(search the web for rsaref.tar.Z for example) and unpack it in this
+directory, so you'll end up having the subdirectories "install" and
+"source" among others.
+
+To build, do the following:
+
+ make
+
+This will list a number of available targets to choose from. Most of
+them are architecture-specific. The exception is "gnu" which is to be
+used on systems where GNU ld and gcc have been installed in such a way
+that gcc uses GNU ld to link together programs and shared libraries.
+
+The make file assumes you use gcc. To change that, just reassign CC:
+
+ make CC=cc
+
+The result is librsaref.so, which you can copy to any place you wish.
diff --git a/crypto/openssl/demos/engines/rsaref/build.com b/crypto/openssl/demos/engines/rsaref/build.com
new file mode 100644
index 0000000..b956912
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/build.com
@@ -0,0 +1,85 @@
+$! BUILD.COM -- Building procedure for the RSAref engine
+$
+$ if f$search("source.dir") .eqs. "" -
+ .or. f$search("install.dir") .eqs. ""
+$ then
+$ write sys$error "RSAref 2.0 hasn't been properly extracted."
+$ exit
+$ endif
+$
+$ _save_default = f$environment("default")
+$ set default [.install]
+$ files := desc,digit,md2c,md5c,nn,prime,-
+ rsa,r_encode,r_dh,r_enhanc,r_keygen,r_random,-
+ r_stdlib
+$ delete rsaref.olb;*
+$ library/create/object rsaref.olb
+$ files_i = 0
+$ rsaref_loop:
+$ files_e = f$edit(f$element(files_i,",",files),"trim")
+$ files_i = files_i + 1
+$ if files_e .eqs. "," then goto rsaref_loop_end
+$ cc/include=([-.source],[])/define=PROTOTYPES=1/object=[]'files_e'.obj -
+ [-.source]'files_e'.c
+$ library/replace/object rsaref.olb 'files_e'.obj
+$ goto rsaref_loop
+$ rsaref_loop_end:
+$
+$ set default [-]
+$ define/user openssl [---.include.openssl]
+$ cc/define=ENGINE_DYNAMIC_SUPPORT rsaref.c
+$
+$ if f$getsyi("CPU") .ge. 128
+$ then
+$ link/share=librsaref.exe sys$input:/option
+[]rsaref.obj
+[.install]rsaref.olb/lib
+[---.axp.exe.crypto]libcrypto.olb/lib
+symbol_vector=(bind_engine=procedure,v_check=procedure)
+$ else
+$ macro/object=rsaref_vec.obj sys$input:
+;
+; Transfer vector for VAX shareable image
+;
+ .TITLE librsaref
+;
+; Define macro to assist in building transfer vector entries. Each entry
+; should take no more than 8 bytes.
+;
+ .MACRO FTRANSFER_ENTRY routine
+ .ALIGN QUAD
+ .TRANSFER routine
+ .MASK routine
+ JMP routine+2
+ .ENDM FTRANSFER_ENTRY
+;
+; Place entries in own program section.
+;
+ .PSECT $$LIBRSAREF,QUAD,PIC,USR,CON,REL,LCL,SHR,EXE,RD,NOWRT
+
+LIBRSAREF_xfer:
+ FTRANSFER_ENTRY bind_engine
+ FTRANSFER_ENTRY v_check
+
+;
+; Allocate extra storage at end of vector to allow for expansion.
+;
+ .BLKB 512-<.-LIBRSAREF_xfer> ; 1 page.
+ .END
+$ link/share=librsaref.exe sys$input:/option
+!
+! Ensure transfer vector is at beginning of image
+!
+CLUSTER=FIRST
+COLLECT=FIRST,$$LIBRSAREF
+!
+! make psects nonshareable so image can be installed.
+!
+PSECT_ATTR=$CHAR_STRING_CONSTANTS,NOWRT
+[]rsaref_vec.obj
+[]rsaref.obj
+[.install]rsaref.olb/lib
+[---.vax.exe.crypto]libcrypto.olb/lib
+$ endif
+$
+$ set default '_save_default'
diff --git a/crypto/openssl/demos/engines/rsaref/rsaref.c b/crypto/openssl/demos/engines/rsaref/rsaref.c
new file mode 100644
index 0000000..872811b
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/rsaref.c
@@ -0,0 +1,685 @@
+/* Demo of how to construct your own engine and using it. The basis of this
+ engine is RSAref, an old reference of the RSA algorithm which can still
+ be found a little here and there. */
+
+#include <stdio.h>
+#include <string.h>
+#include "./source/global.h"
+#include "./source/rsaref.h"
+#include "./source/rsa.h"
+#include "./source/des.h"
+#include <openssl/err.h>
+#define OPENSSL_NO_MD2
+#define OPENSSL_NO_MD5
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/engine.h>
+
+#define RSAREF_LIB_NAME "rsaref engine"
+#include "rsaref_err.c"
+
+/*****************************************************************************
+ *** Function declarations and global variable definitions ***
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Constants used when creating the ENGINE
+ **/
+static const char *engine_rsaref_id = "rsaref";
+static const char *engine_rsaref_name = "RSAref engine support";
+
+/*****************************************************************************
+ * Functions to handle the engine
+ **/
+static int rsaref_destroy(ENGINE *e);
+static int rsaref_init(ENGINE *e);
+static int rsaref_finish(ENGINE *e);
+#if 0
+static int rsaref_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+#endif
+
+/*****************************************************************************
+ * Engine commands
+ **/
+static const ENGINE_CMD_DEFN rsaref_cmd_defns[] = {
+ {0, NULL, NULL, 0}
+ };
+
+/*****************************************************************************
+ * RSA functions
+ **/
+static int rsaref_private_decrypt(int len, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int rsaref_private_encrypt(int len, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int rsaref_public_encrypt(int len, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int rsaref_public_decrypt(int len, const unsigned char *from,
+ unsigned char *to, RSA *rsa, int padding);
+static int bnref_mod_exp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,const BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+static int rsaref_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+
+/*****************************************************************************
+ * Our RSA method
+ **/
+static RSA_METHOD rsaref_rsa =
+{
+ "RSAref PKCS#1 RSA",
+ rsaref_public_encrypt,
+ rsaref_public_decrypt,
+ rsaref_private_encrypt,
+ rsaref_private_decrypt,
+ rsaref_mod_exp,
+ bnref_mod_exp,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*****************************************************************************
+ * Symetric cipher and digest function registrars
+ **/
+static int rsaref_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid);
+static int rsaref_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid);
+
+static int rsaref_cipher_nids[] =
+ { NID_des_cbc, NID_des_ede3_cbc, NID_desx_cbc, 0 };
+static int rsaref_digest_nids[] =
+ { NID_md2, NID_md5, 0 };
+
+/*****************************************************************************
+ * DES functions
+ **/
+static int cipher_des_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int cipher_des_cbc_code(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl);
+static int cipher_des_cbc_clean(EVP_CIPHER_CTX *);
+static int cipher_des_ede3_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int cipher_des_ede3_cbc_code(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl);
+static int cipher_des_ede3_cbc_clean(EVP_CIPHER_CTX *);
+static int cipher_desx_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int cipher_desx_cbc_code(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl);
+static int cipher_desx_cbc_clean(EVP_CIPHER_CTX *);
+
+/*****************************************************************************
+ * Our DES ciphers
+ **/
+static const EVP_CIPHER cipher_des_cbc =
+ {
+ NID_des_cbc,
+ 8, 8, 8,
+ 0 | EVP_CIPH_CBC_MODE,
+ cipher_des_cbc_init,
+ cipher_des_cbc_code,
+ cipher_des_cbc_clean,
+ sizeof(DES_CBC_CTX),
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+static const EVP_CIPHER cipher_des_ede3_cbc =
+ {
+ NID_des_ede3_cbc,
+ 8, 24, 8,
+ 0 | EVP_CIPH_CBC_MODE,
+ cipher_des_ede3_cbc_init,
+ cipher_des_ede3_cbc_code,
+ cipher_des_ede3_cbc_clean,
+ sizeof(DES3_CBC_CTX),
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+static const EVP_CIPHER cipher_desx_cbc =
+ {
+ NID_desx_cbc,
+ 8, 24, 8,
+ 0 | EVP_CIPH_CBC_MODE,
+ cipher_desx_cbc_init,
+ cipher_desx_cbc_code,
+ cipher_desx_cbc_clean,
+ sizeof(DESX_CBC_CTX),
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+/*****************************************************************************
+ * MD functions
+ **/
+static int digest_md2_init(EVP_MD_CTX *ctx);
+static int digest_md2_update(EVP_MD_CTX *ctx,const void *data,
+ unsigned long count);
+static int digest_md2_final(EVP_MD_CTX *ctx,unsigned char *md);
+static int digest_md5_init(EVP_MD_CTX *ctx);
+static int digest_md5_update(EVP_MD_CTX *ctx,const void *data,
+ unsigned long count);
+static int digest_md5_final(EVP_MD_CTX *ctx,unsigned char *md);
+
+/*****************************************************************************
+ * Our MD digests
+ **/
+static const EVP_MD digest_md2 =
+ {
+ NID_md2,
+ NID_md2WithRSAEncryption,
+ 16,
+ 0,
+ digest_md2_init,
+ digest_md2_update,
+ digest_md2_final,
+ NULL,
+ NULL,
+ EVP_PKEY_RSA_method,
+ 16,
+ sizeof(MD2_CTX)
+ };
+
+static const EVP_MD digest_md5 =
+ {
+ NID_md5,
+ NID_md5WithRSAEncryption,
+ 16,
+ 0,
+ digest_md5_init,
+ digest_md5_update,
+ digest_md5_final,
+ NULL,
+ NULL,
+ EVP_PKEY_RSA_method,
+ 64,
+ sizeof(MD5_CTX)
+ };
+
+/*****************************************************************************
+ *** Function definitions ***
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Functions to handle the engine
+ **/
+
+static int bind_rsaref(ENGINE *e)
+ {
+ const RSA_METHOD *meth1;
+ if(!ENGINE_set_id(e, engine_rsaref_id)
+ || !ENGINE_set_name(e, engine_rsaref_name)
+ || !ENGINE_set_RSA(e, &rsaref_rsa)
+ || !ENGINE_set_ciphers(e, rsaref_ciphers)
+ || !ENGINE_set_digests(e, rsaref_digests)
+ || !ENGINE_set_destroy_function(e, rsaref_destroy)
+ || !ENGINE_set_init_function(e, rsaref_init)
+ || !ENGINE_set_finish_function(e, rsaref_finish)
+ /* || !ENGINE_set_ctrl_function(e, rsaref_ctrl) */
+ /* || !ENGINE_set_cmd_defns(e, rsaref_cmd_defns) */)
+ return 0;
+
+ /* Ensure the rsaref error handling is set up */
+ ERR_load_RSAREF_strings();
+ return 1;
+ }
+
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_helper(ENGINE *e, const char *id)
+ {
+ if(id && (strcmp(id, engine_rsaref_id) != 0))
+ return 0;
+ if(!bind_rsaref(e))
+ return 0;
+ return 1;
+ }
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+#else
+static ENGINE *engine_rsaref(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!bind_rsaref(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void ENGINE_load_rsaref(void)
+ {
+ /* Copied from eng_[openssl|dyn].c */
+ ENGINE *toadd = engine_rsaref();
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ ENGINE_free(toadd);
+ ERR_clear_error();
+ }
+#endif
+
+/* Initiator which is only present to make sure this engine looks available */
+static int rsaref_init(ENGINE *e)
+ {
+ return 1;
+ }
+
+/* Finisher which is only present to make sure this engine looks available */
+static int rsaref_finish(ENGINE *e)
+ {
+ return 1;
+ }
+
+/* Destructor (complements the "ENGINE_ncipher()" constructor) */
+static int rsaref_destroy(ENGINE *e)
+ {
+ ERR_unload_RSAREF_strings();
+ return 1;
+ }
+
+/*****************************************************************************
+ * RSA functions
+ **/
+
+static int rsaref_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_MOD_EXP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return(0);
+ }
+
+static int bnref_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+ {
+ RSAREFerr(RSAREF_F_BNREF_MOD_EXP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return(0);
+ }
+
+/* unsigned char *to: [max] */
+static int RSAref_bn2bin(BIGNUM *from, unsigned char *to, int max)
+ {
+ int i;
+
+ i=BN_num_bytes(from);
+ if (i > max)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_BN2BIN,RSAREF_R_LEN);
+ return(0);
+ }
+
+ memset(to,0,(unsigned int)max);
+ if (!BN_bn2bin(from,&(to[max-i])))
+ return(0);
+ return(1);
+ }
+
+#ifdef undef
+/* unsigned char *from: [max] */
+static BIGNUM *RSAref_bin2bn(unsigned char *from, BIGNUM *to, int max)
+ {
+ int i;
+ BIGNUM *ret;
+
+ for (i=0; i<max; i++)
+ if (from[i]) break;
+
+ ret=BN_bin2bn(&(from[i]),max-i,to);
+ return(ret);
+ }
+
+static int RSAref_Public_ref2eay(RSArefPublicKey *from, RSA *to)
+ {
+ to->n=RSAref_bin2bn(from->m,NULL,RSAref_MAX_LEN);
+ to->e=RSAref_bin2bn(from->e,NULL,RSAref_MAX_LEN);
+ if ((to->n == NULL) || (to->e == NULL)) return(0);
+ return(1);
+ }
+#endif
+
+static int RSAref_Public_eay2ref(RSA *from, R_RSA_PUBLIC_KEY *to)
+ {
+ to->bits=BN_num_bits(from->n);
+ if (!RSAref_bn2bin(from->n,to->modulus,MAX_RSA_MODULUS_LEN)) return(0);
+ if (!RSAref_bn2bin(from->e,to->exponent,MAX_RSA_MODULUS_LEN)) return(0);
+ return(1);
+ }
+
+#ifdef undef
+static int RSAref_Private_ref2eay(RSArefPrivateKey *from, RSA *to)
+ {
+ if ((to->n=RSAref_bin2bn(from->m,NULL,RSAref_MAX_LEN)) == NULL)
+ return(0);
+ if ((to->e=RSAref_bin2bn(from->e,NULL,RSAref_MAX_LEN)) == NULL)
+ return(0);
+ if ((to->d=RSAref_bin2bn(from->d,NULL,RSAref_MAX_LEN)) == NULL)
+ return(0);
+ if ((to->p=RSAref_bin2bn(from->prime[0],NULL,RSAref_MAX_PLEN)) == NULL)
+ return(0);
+ if ((to->q=RSAref_bin2bn(from->prime[1],NULL,RSAref_MAX_PLEN)) == NULL)
+ return(0);
+ if ((to->dmp1=RSAref_bin2bn(from->pexp[0],NULL,RSAref_MAX_PLEN))
+ == NULL)
+ return(0);
+ if ((to->dmq1=RSAref_bin2bn(from->pexp[1],NULL,RSAref_MAX_PLEN))
+ == NULL)
+ return(0);
+ if ((to->iqmp=RSAref_bin2bn(from->coef,NULL,RSAref_MAX_PLEN)) == NULL)
+ return(0);
+ return(1);
+ }
+#endif
+
+static int RSAref_Private_eay2ref(RSA *from, R_RSA_PRIVATE_KEY *to)
+ {
+ to->bits=BN_num_bits(from->n);
+ if (!RSAref_bn2bin(from->n,to->modulus,MAX_RSA_MODULUS_LEN)) return(0);
+ if (!RSAref_bn2bin(from->e,to->publicExponent,MAX_RSA_MODULUS_LEN)) return(0);
+ if (!RSAref_bn2bin(from->d,to->exponent,MAX_RSA_MODULUS_LEN)) return(0);
+ if (!RSAref_bn2bin(from->p,to->prime[0],MAX_RSA_PRIME_LEN)) return(0);
+ if (!RSAref_bn2bin(from->q,to->prime[1],MAX_RSA_PRIME_LEN)) return(0);
+ if (!RSAref_bn2bin(from->dmp1,to->primeExponent[0],MAX_RSA_PRIME_LEN)) return(0);
+ if (!RSAref_bn2bin(from->dmq1,to->primeExponent[1],MAX_RSA_PRIME_LEN)) return(0);
+ if (!RSAref_bn2bin(from->iqmp,to->coefficient,MAX_RSA_PRIME_LEN)) return(0);
+ return(1);
+ }
+
+static int rsaref_private_decrypt(int len, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+ int i,outlen= -1;
+ R_RSA_PRIVATE_KEY RSAkey;
+
+ if (!RSAref_Private_eay2ref(rsa,&RSAkey))
+ goto err;
+ if ((i=RSAPrivateDecrypt(to,(unsigned int *)&outlen,(unsigned char *)from,len,&RSAkey)) != 0)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_PRIVATE_DECRYPT,i);
+ outlen= -1;
+ }
+err:
+ memset(&RSAkey,0,sizeof(RSAkey));
+ return(outlen);
+ }
+
+static int rsaref_private_encrypt(int len, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+ int i,outlen= -1;
+ R_RSA_PRIVATE_KEY RSAkey;
+
+ if (padding != RSA_PKCS1_PADDING)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
+ goto err;
+ }
+ if (!RSAref_Private_eay2ref(rsa,&RSAkey))
+ goto err;
+ if ((i=RSAPrivateEncrypt(to,(unsigned int)&outlen,(unsigned char *)from,len,&RSAkey)) != 0)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_PRIVATE_ENCRYPT,i);
+ outlen= -1;
+ }
+err:
+ memset(&RSAkey,0,sizeof(RSAkey));
+ return(outlen);
+ }
+
+static int rsaref_public_decrypt(int len, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+ int i,outlen= -1;
+ R_RSA_PUBLIC_KEY RSAkey;
+
+ if (!RSAref_Public_eay2ref(rsa,&RSAkey))
+ goto err;
+ if ((i=RSAPublicDecrypt(to,(unsigned int)&outlen,(unsigned char *)from,len,&RSAkey)) != 0)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_PUBLIC_DECRYPT,i);
+ outlen= -1;
+ }
+err:
+ memset(&RSAkey,0,sizeof(RSAkey));
+ return(outlen);
+ }
+
+static int rsaref_public_encrypt(int len, const unsigned char *from, unsigned char *to,
+ RSA *rsa, int padding)
+ {
+ int outlen= -1;
+ int i;
+ R_RSA_PUBLIC_KEY RSAkey;
+ R_RANDOM_STRUCT rnd;
+ unsigned char buf[16];
+
+ if (padding != RSA_PKCS1_PADDING && padding != RSA_SSLV23_PADDING)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
+ goto err;
+ }
+
+ R_RandomInit(&rnd);
+ R_GetRandomBytesNeeded((unsigned int *)&i,&rnd);
+ while (i > 0)
+ {
+ if (RAND_bytes(buf,16) <= 0)
+ goto err;
+ R_RandomUpdate(&rnd,buf,(unsigned int)((i>16)?16:i));
+ i-=16;
+ }
+
+ if (!RSAref_Public_eay2ref(rsa,&RSAkey))
+ goto err;
+ if ((i=RSAPublicEncrypt(to,(unsigned int)&outlen,(unsigned char *)from,len,&RSAkey,&rnd)) != 0)
+ {
+ RSAREFerr(RSAREF_F_RSAREF_PUBLIC_ENCRYPT,i);
+ outlen= -1;
+ goto err;
+ }
+err:
+ memset(&RSAkey,0,sizeof(RSAkey));
+ R_RandomFinal(&rnd);
+ memset(&rnd,0,sizeof(rnd));
+ return(outlen);
+ }
+
+/*****************************************************************************
+ * Symetric cipher and digest function registrars
+ **/
+static int rsaref_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid)
+ {
+ int ok = 1;
+ if(!cipher)
+ {
+ /* We are returning a list of supported nids */
+ *nids = rsaref_cipher_nids;
+ return (sizeof(rsaref_cipher_nids)-1)/sizeof(rsaref_cipher_nids[0]);
+ }
+ /* We are being asked for a specific cipher */
+ switch (nid)
+ {
+ case NID_des_cbc:
+ *cipher = &cipher_des_cbc; break;
+ case NID_des_ede3_cbc:
+ *cipher = &cipher_des_ede3_cbc; break;
+ case NID_desx_cbc:
+ *cipher = &cipher_desx_cbc; break;
+ default:
+ ok = 0;
+ *cipher = NULL;
+ break;
+ }
+ return ok;
+ }
+static int rsaref_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid)
+ {
+ int ok = 1;
+ if(!digest)
+ {
+ /* We are returning a list of supported nids */
+ *nids = rsaref_digest_nids;
+ return (sizeof(rsaref_digest_nids)-1)/sizeof(rsaref_digest_nids[0]);
+ }
+ /* We are being asked for a specific digest */
+ switch (nid)
+ {
+ case NID_md2:
+ *digest = &digest_md2; break;
+ case NID_md5:
+ *digest = &digest_md5; break;
+ default:
+ ok = 0;
+ *digest = NULL;
+ break;
+ }
+ return ok;
+ }
+
+/*****************************************************************************
+ * DES functions
+ **/
+#undef data
+#define data(ctx) ((DES_CBC_CTX *)(ctx)->cipher_data)
+static int cipher_des_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+ DES_CBCInit(data(ctx), (unsigned char *)key, (unsigned char *)iv, enc);
+ return 1;
+ }
+static int cipher_des_cbc_code(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl)
+ {
+ int ret = DES_CBCUpdate(data(ctx), out, (unsigned char *)in, inl);
+ switch (ret)
+ {
+ case RE_LEN:
+ RSAREFerr(RSAREF_F_CIPHER_DES_CBC_CODE,RSAREF_R_LENGTH_NOT_BLOCK_ALIGNED);
+ break;
+ case 0:
+ break;
+ default:
+ RSAREFerr(RSAREF_F_CIPHER_DES_CBC_CODE,RSAREF_R_UNKNOWN_FAULT);
+ }
+ return !ret;
+ }
+static int cipher_des_cbc_clean(EVP_CIPHER_CTX *ctx)
+ {
+ memset(data(ctx), 0, ctx->cipher->ctx_size);
+ return 1;
+ }
+
+#undef data
+#define data(ctx) ((DES3_CBC_CTX *)(ctx)->cipher_data)
+static int cipher_des_ede3_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+ DES3_CBCInit(data(ctx), (unsigned char *)key, (unsigned char *)iv,
+ enc);
+ return 1;
+ }
+static int cipher_des_ede3_cbc_code(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl)
+ {
+ int ret = DES3_CBCUpdate(data(ctx), out, (unsigned char *)in, inl);
+ switch (ret)
+ {
+ case RE_LEN:
+ RSAREFerr(RSAREF_F_CIPHER_DES_CBC_CODE,RSAREF_R_LENGTH_NOT_BLOCK_ALIGNED);
+ break;
+ case 0:
+ break;
+ default:
+ RSAREFerr(RSAREF_F_CIPHER_DES_CBC_CODE,RSAREF_R_UNKNOWN_FAULT);
+ }
+ return !ret;
+ }
+static int cipher_des_ede3_cbc_clean(EVP_CIPHER_CTX *ctx)
+ {
+ memset(data(ctx), 0, ctx->cipher->ctx_size);
+ return 1;
+ }
+
+#undef data
+#define data(ctx) ((DESX_CBC_CTX *)(ctx)->cipher_data)
+static int cipher_desx_cbc_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+ DESX_CBCInit(data(ctx), (unsigned char *)key, (unsigned char *)iv,
+ enc);
+ return 1;
+ }
+static int cipher_desx_cbc_code(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, unsigned int inl)
+ {
+ int ret = DESX_CBCUpdate(data(ctx), out, (unsigned char *)in, inl);
+ switch (ret)
+ {
+ case RE_LEN:
+ RSAREFerr(RSAREF_F_CIPHER_DES_CBC_CODE,RSAREF_R_LENGTH_NOT_BLOCK_ALIGNED);
+ break;
+ case 0:
+ break;
+ default:
+ RSAREFerr(RSAREF_F_CIPHER_DES_CBC_CODE,RSAREF_R_UNKNOWN_FAULT);
+ }
+ return !ret;
+ }
+static int cipher_desx_cbc_clean(EVP_CIPHER_CTX *ctx)
+ {
+ memset(data(ctx), 0, ctx->cipher->ctx_size);
+ return 1;
+ }
+
+/*****************************************************************************
+ * MD functions
+ **/
+#undef data
+#define data(ctx) ((MD2_CTX *)(ctx)->md_data)
+static int digest_md2_init(EVP_MD_CTX *ctx)
+ {
+ MD2Init(data(ctx));
+ return 1;
+ }
+static int digest_md2_update(EVP_MD_CTX *ctx,const void *data,
+ unsigned long count)
+ {
+ MD2Update(data(ctx), (unsigned char *)data, (unsigned int)count);
+ return 1;
+ }
+static int digest_md2_final(EVP_MD_CTX *ctx,unsigned char *md)
+ {
+ MD2Final(md, data(ctx));
+ return 1;
+ }
+
+#undef data
+#define data(ctx) ((MD5_CTX *)(ctx)->md_data)
+static int digest_md5_init(EVP_MD_CTX *ctx)
+ {
+ MD5Init(data(ctx));
+ return 1;
+ }
+static int digest_md5_update(EVP_MD_CTX *ctx,const void *data,
+ unsigned long count)
+ {
+ MD5Update(data(ctx), (unsigned char *)data, (unsigned int)count);
+ return 1;
+ }
+static int digest_md5_final(EVP_MD_CTX *ctx,unsigned char *md)
+ {
+ MD5Final(md, data(ctx));
+ return 1;
+ }
diff --git a/crypto/openssl/demos/engines/rsaref/rsaref.ec b/crypto/openssl/demos/engines/rsaref/rsaref.ec
new file mode 100644
index 0000000..c690ae3
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/rsaref.ec
@@ -0,0 +1,8 @@
+# configuration file for util/mkerr.pl
+#
+# use like this:
+#
+# perl ../../../util/mkerr.pl -conf rsaref.ec \
+# -nostatic -staticloader -write *.c
+
+L RSAREF rsaref_err.h rsaref_err.c
diff --git a/crypto/openssl/demos/engines/rsaref/rsaref_err.c b/crypto/openssl/demos/engines/rsaref/rsaref_err.c
new file mode 100644
index 0000000..ceaf057
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/rsaref_err.c
@@ -0,0 +1,161 @@
+/* rsaref_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "rsaref_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA RSAREF_str_functs[]=
+ {
+{ERR_PACK(0,RSAREF_F_BNREF_MOD_EXP,0), "BNREF_MOD_EXP"},
+{ERR_PACK(0,RSAREF_F_CIPHER_DES_CBC_CODE,0), "CIPHER_DES_CBC_CODE"},
+{ERR_PACK(0,RSAREF_F_RSAREF_BN2BIN,0), "RSAREF_BN2BIN"},
+{ERR_PACK(0,RSAREF_F_RSAREF_MOD_EXP,0), "RSAREF_MOD_EXP"},
+{ERR_PACK(0,RSAREF_F_RSAREF_PRIVATE_DECRYPT,0), "RSAREF_PRIVATE_DECRYPT"},
+{ERR_PACK(0,RSAREF_F_RSAREF_PRIVATE_ENCRYPT,0), "RSAREF_PRIVATE_ENCRYPT"},
+{ERR_PACK(0,RSAREF_F_RSAREF_PUBLIC_DECRYPT,0), "RSAREF_PUBLIC_DECRYPT"},
+{ERR_PACK(0,RSAREF_F_RSAREF_PUBLIC_ENCRYPT,0), "RSAREF_PUBLIC_ENCRYPT"},
+{ERR_PACK(0,RSAREF_F_RSA_BN2BIN,0), "RSA_BN2BIN"},
+{ERR_PACK(0,RSAREF_F_RSA_PRIVATE_DECRYPT,0), "RSA_PRIVATE_DECRYPT"},
+{ERR_PACK(0,RSAREF_F_RSA_PRIVATE_ENCRYPT,0), "RSA_PRIVATE_ENCRYPT"},
+{ERR_PACK(0,RSAREF_F_RSA_PUBLIC_DECRYPT,0), "RSA_PUBLIC_DECRYPT"},
+{ERR_PACK(0,RSAREF_F_RSA_PUBLIC_ENCRYPT,0), "RSA_PUBLIC_ENCRYPT"},
+{0,NULL}
+ };
+
+static ERR_STRING_DATA RSAREF_str_reasons[]=
+ {
+{RSAREF_R_CONTENT_ENCODING ,"content encoding"},
+{RSAREF_R_DATA ,"data"},
+{RSAREF_R_DIGEST_ALGORITHM ,"digest algorithm"},
+{RSAREF_R_ENCODING ,"encoding"},
+{RSAREF_R_ENCRYPTION_ALGORITHM ,"encryption algorithm"},
+{RSAREF_R_KEY ,"key"},
+{RSAREF_R_KEY_ENCODING ,"key encoding"},
+{RSAREF_R_LEN ,"len"},
+{RSAREF_R_LENGTH_NOT_BLOCK_ALIGNED ,"length not block aligned"},
+{RSAREF_R_MODULUS_LEN ,"modulus len"},
+{RSAREF_R_NEED_RANDOM ,"need random"},
+{RSAREF_R_PRIVATE_KEY ,"private key"},
+{RSAREF_R_PUBLIC_KEY ,"public key"},
+{RSAREF_R_SIGNATURE ,"signature"},
+{RSAREF_R_SIGNATURE_ENCODING ,"signature encoding"},
+{RSAREF_R_UNKNOWN_FAULT ,"unknown fault"},
+{0,NULL}
+ };
+
+#endif
+
+#ifdef RSAREF_LIB_NAME
+static ERR_STRING_DATA RSAREF_lib_name[]=
+ {
+{0 ,RSAREF_LIB_NAME},
+{0,NULL}
+ };
+#endif
+
+
+static int RSAREF_lib_error_code=0;
+static int RSAREF_error_init=1;
+
+static void ERR_load_RSAREF_strings(void)
+ {
+ if (RSAREF_lib_error_code == 0)
+ RSAREF_lib_error_code=ERR_get_next_error_library();
+
+ if (RSAREF_error_init)
+ {
+ RSAREF_error_init=0;
+#ifndef OPENSSL_NO_ERR
+ ERR_load_strings(RSAREF_lib_error_code,RSAREF_str_functs);
+ ERR_load_strings(RSAREF_lib_error_code,RSAREF_str_reasons);
+#endif
+
+#ifdef RSAREF_LIB_NAME
+ RSAREF_lib_name->error = ERR_PACK(RSAREF_lib_error_code,0,0);
+ ERR_load_strings(0,RSAREF_lib_name);
+#endif
+ }
+ }
+
+static void ERR_unload_RSAREF_strings(void)
+ {
+ if (RSAREF_error_init == 0)
+ {
+#ifndef OPENSSL_NO_ERR
+ ERR_unload_strings(RSAREF_lib_error_code,RSAREF_str_functs);
+ ERR_unload_strings(RSAREF_lib_error_code,RSAREF_str_reasons);
+#endif
+
+#ifdef RSAREF_LIB_NAME
+ ERR_unload_strings(0,RSAREF_lib_name);
+#endif
+ RSAREF_error_init=1;
+ }
+ }
+
+static void ERR_RSAREF_error(int function, int reason, char *file, int line)
+ {
+ if (RSAREF_lib_error_code == 0)
+ RSAREF_lib_error_code=ERR_get_next_error_library();
+ ERR_PUT_error(RSAREF_lib_error_code,function,reason,file,line);
+ }
diff --git a/crypto/openssl/demos/engines/rsaref/rsaref_err.h b/crypto/openssl/demos/engines/rsaref/rsaref_err.h
new file mode 100644
index 0000000..1975970
--- /dev/null
+++ b/crypto/openssl/demos/engines/rsaref/rsaref_err.h
@@ -0,0 +1,109 @@
+/* rsaref_err.h */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_RSAREF_ERR_H
+#define HEADER_RSAREF_ERR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_RSAREF_strings(void);
+static void ERR_unload_RSAREF_strings(void);
+static void ERR_RSAREF_error(int function, int reason, char *file, int line);
+#define RSAREFerr(f,r) ERR_RSAREF_error((f),(r),__FILE__,__LINE__)
+/* Error codes for the RSAREF functions. */
+
+/* Function codes. */
+#define RSAREF_F_BNREF_MOD_EXP 100
+#define RSAREF_F_CIPHER_DES_CBC_CODE 112
+#define RSAREF_F_RSAREF_BN2BIN 101
+#define RSAREF_F_RSAREF_MOD_EXP 102
+#define RSAREF_F_RSAREF_PRIVATE_DECRYPT 103
+#define RSAREF_F_RSAREF_PRIVATE_ENCRYPT 104
+#define RSAREF_F_RSAREF_PUBLIC_DECRYPT 105
+#define RSAREF_F_RSAREF_PUBLIC_ENCRYPT 106
+#define RSAREF_F_RSA_BN2BIN 107
+#define RSAREF_F_RSA_PRIVATE_DECRYPT 108
+#define RSAREF_F_RSA_PRIVATE_ENCRYPT 109
+#define RSAREF_F_RSA_PUBLIC_DECRYPT 110
+#define RSAREF_F_RSA_PUBLIC_ENCRYPT 111
+
+/* Reason codes. */
+#define RSAREF_R_CONTENT_ENCODING 100
+#define RSAREF_R_DATA 101
+#define RSAREF_R_DIGEST_ALGORITHM 102
+#define RSAREF_R_ENCODING 103
+#define RSAREF_R_ENCRYPTION_ALGORITHM 104
+#define RSAREF_R_KEY 105
+#define RSAREF_R_KEY_ENCODING 106
+#define RSAREF_R_LEN 107
+#define RSAREF_R_LENGTH_NOT_BLOCK_ALIGNED 114
+#define RSAREF_R_MODULUS_LEN 108
+#define RSAREF_R_NEED_RANDOM 109
+#define RSAREF_R_PRIVATE_KEY 110
+#define RSAREF_R_PUBLIC_KEY 111
+#define RSAREF_R_SIGNATURE 112
+#define RSAREF_R_SIGNATURE_ENCODING 113
+#define RSAREF_R_UNKNOWN_FAULT 115
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/openssl/demos/engines/zencod/Makefile b/crypto/openssl/demos/engines/zencod/Makefile
new file mode 100644
index 0000000..5b6a339
--- /dev/null
+++ b/crypto/openssl/demos/engines/zencod/Makefile
@@ -0,0 +1,114 @@
+LIBNAME= libzencod
+SRC= hw_zencod.c
+OBJ= hw_zencod.o
+HEADER= hw_zencod.h
+
+CC= gcc
+PIC= -fPIC
+CFLAGS= -g -I../../../include $(PIC) -DENGINE_DYNAMIC_SUPPORT -DFLAT_INC
+AR= ar r
+RANLIB= ranlib
+
+LIB= $(LIBNAME).a
+SHLIB= $(LIBNAME).so
+
+all:
+ @echo 'Please choose a system to build on:'
+ @echo ''
+ @echo 'tru64: Tru64 Unix, Digital Unix, Digital OSF/1'
+ @echo 'solaris: Solaris'
+ @echo 'irix: IRIX'
+ @echo 'hpux32: 32-bit HP/UX'
+ @echo 'hpux64: 64-bit HP/UX'
+ @echo 'aix: AIX'
+ @echo 'gnu: Generic GNU-based system (gcc and GNU ld)'
+ @echo ''
+
+FORCE.update:
+update: FORCE.update
+ perl ../../../util/mkerr.pl -conf hw_zencod.ec \
+ -nostatic -staticloader -write hw_zencod.c
+
+gnu: $(SHLIB).gnu
+tru64: $(SHLIB).tru64
+solaris: $(SHLIB).solaris
+irix: $(SHLIB).irix
+hpux32: $(SHLIB).hpux32
+hpux64: $(SHLIB).hpux64
+aix: $(SHLIB).aix
+
+$(LIB): $(OBJ)
+ $(AR) $(LIB) $(OBJ)
+ - $(RANLIB) $(LIB)
+
+LINK_SO= \
+ ld -r -o $(LIBNAME).o $$ALLSYMSFLAGS $(LIB) && \
+ (nm -Pg $(LIBNAME).o | grep ' [BDT] ' | cut -f1 -d' ' > $(LIBNAME).exp; \
+ $$SHAREDCMD $$SHAREDFLAGS -o $(SHLIB) $(LIBNAME).o -L ../../.. -lcrypto -lc)
+
+$(SHLIB).gnu: $(LIB)
+ ALLSYMSFLAGS='--whole-archive' \
+ SHAREDFLAGS='-shared -Wl,-soname=$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).gnu
+$(SHLIB).tru64: $(LIB)
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).tru64
+$(SHLIB).solaris: $(LIB)
+ ALLSYMSFLAGS='-z allextract' \
+ SHAREDFLAGS='-G -h $(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).solaris
+$(SHLIB).irix: $(LIB)
+ ALLSYMSFLAGS='-all' \
+ SHAREDFLAGS='-shared -Wl,-soname,$(SHLIB)' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).irix
+$(SHLIB).hpux32: $(LIB)
+ ALLSYMSFLAGS='-Fl' \
+ SHAREDFLAGS='+vnocompatwarnings -b -z +s +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux32
+$(SHLIB).hpux64: $(LIB)
+ ALLSYMSFLAGS='+forceload' \
+ SHAREDFLAGS='-b -z +h $(SHLIB)' \
+ SHAREDCMD='/usr/ccs/bin/ld'; \
+ $(LINK_SO)
+ touch $(SHLIB).hpux64
+$(SHLIB).aix: $(LIB)
+ ALLSYMSFLAGS='-bnogc' \
+ SHAREDFLAGS='-G -bE:$(LIBNAME).exp -bM:SRE' \
+ SHAREDCMD='$(CC)'; \
+ $(LINK_SO)
+ touch $(SHLIB).aix
+
+depend:
+ sed -e '/^# DO NOT DELETE.*/,$$d' < Makefile > Makefile.tmp
+ echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' >> Makefile.tmp
+ gcc -M $(CFLAGS) $(SRC) >> Makefile.tmp
+ perl ../../../util/clean-depend.pl < Makefile.tmp > Makefile.new
+ rm -f Makefile.tmp Makefile
+ mv Makefile.new Makefile
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+rsaref.o: ../../../include/openssl/asn1.h ../../../include/openssl/bio.h
+rsaref.o: ../../../include/openssl/bn.h ../../../include/openssl/crypto.h
+rsaref.o: ../../../include/openssl/dh.h ../../../include/openssl/dsa.h
+rsaref.o: ../../../include/openssl/e_os2.h ../../../include/openssl/engine.h
+rsaref.o: ../../../include/openssl/err.h ../../../include/openssl/lhash.h
+rsaref.o: ../../../include/openssl/opensslconf.h
+rsaref.o: ../../../include/openssl/opensslv.h
+rsaref.o: ../../../include/openssl/ossl_typ.h ../../../include/openssl/rand.h
+rsaref.o: ../../../include/openssl/rsa.h ../../../include/openssl/safestack.h
+rsaref.o: ../../../include/openssl/stack.h ../../../include/openssl/symhacks.h
+rsaref.o: ../../../include/openssl/ui.h rsaref.c rsaref_err.c rsaref_err.h
+rsaref.o: source/des.h source/global.h source/md2.h source/md5.h source/rsa.h
+rsaref.o: source/rsaref.h
diff --git a/crypto/openssl/demos/engines/zencod/hw_zencod.c b/crypto/openssl/demos/engines/zencod/hw_zencod.c
new file mode 100644
index 0000000..29206b4
--- /dev/null
+++ b/crypto/openssl/demos/engines/zencod/hw_zencod.c
@@ -0,0 +1,1739 @@
+/* crypto/engine/hw_zencod.c */
+ /* Written by Fred Donnat (frederic.donnat@zencod.com) for "zencod"
+ * engine integration in order to redirect crypto computing on a crypto
+ * hardware accelerator zenssl32 ;-)
+ *
+ * Date : 25 jun 2002
+ * Revision : 17 Ju7 2002
+ * Version : zencod_engine-0.9.7
+ */
+
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+/* ENGINE general include */
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_ZENCOD
+
+#ifdef FLAT_INC
+# include "hw_zencod.h"
+#else
+# include "vendor_defns/hw_zencod.h"
+#endif
+
+#define ZENCOD_LIB_NAME "zencod engine"
+#include "hw_zencod_err.c"
+
+#define FAIL_TO_SOFTWARE -15
+
+#define ZEN_LIBRARY "zenbridge"
+
+#if 0
+# define PERROR(s) perror(s)
+# define CHEESE() fputs("## [ZenEngine] ## " __FUNCTION__ "\n", stderr)
+#else
+# define PERROR(s)
+# define CHEESE()
+#endif
+
+
+/* Sorry ;) */
+#ifndef WIN32
+static inline void esrever ( unsigned char *d, int l )
+{
+ for(;--l>0;--l,d++){*d^=*(d+l);*(d+l)^=*d;*d^=*(d+l);}
+}
+
+static inline void ypcmem ( unsigned char *d, const unsigned char *s, int l )
+{
+ for(d+=l;l--;)*--d=*s++;
+}
+#else
+static __inline void esrever ( unsigned char *d, int l )
+{
+ for(;--l>0;--l,d++){*d^=*(d+l);*(d+l)^=*d;*d^=*(d+l);}
+}
+
+static __inline void ypcmem ( unsigned char *d, const unsigned char *s, int l )
+{
+ for(d+=l;l--;)*--d=*s++;
+}
+#endif
+
+
+#define BIGNUM2ZEN(n, bn) (ptr_zencod_init_number((n), \
+ (unsigned long) ((bn)->top * BN_BITS2), \
+ (unsigned char *) ((bn)->d)))
+
+#define ZEN_BITS(n, bytes) (ptr_zencod_bytes2bits((unsigned char *) (n), (unsigned long) (bytes)))
+#define ZEN_BYTES(bits) (ptr_zencod_bits2bytes((unsigned long) (bits)))
+
+
+/* Function for ENGINE detection and control */
+static int zencod_destroy ( ENGINE *e ) ;
+static int zencod_init ( ENGINE *e ) ;
+static int zencod_finish ( ENGINE *e ) ;
+static int zencod_ctrl ( ENGINE *e, int cmd, long i, void *p, void (*f) () ) ;
+
+/* BIGNUM stuff */
+static int zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx ) ;
+
+/* RSA stuff */
+#ifndef OPENSSL_NO_RSA
+static int RSA_zencod_rsa_mod_exp ( BIGNUM *r0, const BIGNUM *I, RSA *rsa ) ;
+static int RSA_zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx ) ;
+#endif
+
+/* DSA stuff */
+#ifndef OPENSSL_NO_DSA
+static int DSA_zencod_bn_mod_exp ( DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx ) ;
+
+static DSA_SIG *DSA_zencod_do_sign ( const unsigned char *dgst, int dlen, DSA *dsa ) ;
+static int DSA_zencod_do_verify ( const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
+ DSA *dsa ) ;
+#endif
+
+/* DH stuff */
+#ifndef OPENSSL_NO_DH
+static int DH_zencod_bn_mod_exp ( const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx ) ;
+static int DH_zencod_generate_key ( DH *dh ) ;
+static int DH_zencod_compute_key ( unsigned char *key, const BIGNUM *pub_key, DH *dh ) ;
+#endif
+
+/* Rand stuff */
+static void RAND_zencod_seed ( const void *buf, int num ) ;
+static int RAND_zencod_rand_bytes ( unsigned char *buf, int num ) ;
+static int RAND_zencod_rand_status ( void ) ;
+
+/* Digest Stuff */
+static int engine_digests ( ENGINE *e, const EVP_MD **digest, const int **nids, int nid ) ;
+
+/* Cipher Stuff */
+static int engine_ciphers ( ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid ) ;
+
+
+#define ZENCOD_CMD_SO_PATH ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN zencod_cmd_defns [ ] =
+{
+ { ZENCOD_CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the 'zenbridge' shared library",
+ ENGINE_CMD_FLAG_STRING},
+ { 0, NULL, NULL, 0 }
+} ;
+
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD specific to zencod ENGINE providing pointers to our function */
+static RSA_METHOD zencod_rsa =
+{
+ "ZENCOD RSA method",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ RSA_zencod_rsa_mod_exp,
+ RSA_zencod_bn_mod_exp,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL
+} ;
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* Our internal DSA_METHOD specific to zencod ENGINE providing pointers to our function */
+static DSA_METHOD zencod_dsa =
+{
+ "ZENCOD DSA method",
+ DSA_zencod_do_sign,
+ NULL,
+ DSA_zencod_do_verify,
+ NULL,
+ DSA_zencod_bn_mod_exp,
+ NULL,
+ NULL,
+ 0,
+ NULL
+} ;
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD specific to zencod ENGINE providing pointers to our function */
+static DH_METHOD zencod_dh =
+{
+ "ZENCOD DH method",
+ DH_zencod_generate_key,
+ DH_zencod_compute_key,
+ DH_zencod_bn_mod_exp,
+ NULL,
+ NULL,
+ 0,
+ NULL
+} ;
+#endif
+
+/* Our internal RAND_meth specific to zencod ZNGINE providing pointers to our function */
+static RAND_METHOD zencod_rand =
+{
+ RAND_zencod_seed,
+ RAND_zencod_rand_bytes,
+ NULL,
+ NULL,
+ RAND_zencod_rand_bytes,
+ RAND_zencod_rand_status
+} ;
+
+
+/* Constants used when creating the ENGINE */
+static const char *engine_zencod_id = "zencod";
+static const char *engine_zencod_name = "ZENCOD hardware engine support";
+
+
+/* This internal function is used by ENGINE_zencod () and possibly by the
+ * "dynamic" ENGINE support too ;-)
+ */
+static int bind_helper ( ENGINE *e )
+{
+
+#ifndef OPENSSL_NO_RSA
+ const RSA_METHOD *meth_rsa ;
+#endif
+#ifndef OPENSSL_NO_DSA
+ const DSA_METHOD *meth_dsa ;
+#endif
+#ifndef OPENSSL_NO_DH
+ const DH_METHOD *meth_dh ;
+#endif
+
+ const RAND_METHOD *meth_rand ;
+
+
+ if ( !ENGINE_set_id ( e, engine_zencod_id ) ||
+ !ENGINE_set_name ( e, engine_zencod_name ) ||
+#ifndef OPENSSL_NO_RSA
+ !ENGINE_set_RSA ( e, &zencod_rsa ) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+ !ENGINE_set_DSA ( e, &zencod_dsa ) ||
+#endif
+#ifndef OPENSSL_NO_DH
+ !ENGINE_set_DH ( e, &zencod_dh ) ||
+#endif
+ !ENGINE_set_RAND ( e, &zencod_rand ) ||
+
+ !ENGINE_set_destroy_function ( e, zencod_destroy ) ||
+ !ENGINE_set_init_function ( e, zencod_init ) ||
+ !ENGINE_set_finish_function ( e, zencod_finish ) ||
+ !ENGINE_set_ctrl_function ( e, zencod_ctrl ) ||
+ !ENGINE_set_cmd_defns ( e, zencod_cmd_defns ) ||
+ !ENGINE_set_digests ( e, engine_digests ) ||
+ !ENGINE_set_ciphers ( e, engine_ciphers ) ) {
+ return 0 ;
+ }
+
+#ifndef OPENSSL_NO_RSA
+ /* We know that the "PKCS1_SSLeay()" functions hook properly
+ * to the Zencod-specific mod_exp and mod_exp_crt so we use
+ * those functions. NB: We don't use ENGINE_openssl() or
+ * anything "more generic" because something like the RSAref
+ * code may not hook properly, and if you own one of these
+ * cards then you have the right to do RSA operations on it
+ * anyway!
+ */
+ meth_rsa = RSA_PKCS1_SSLeay () ;
+
+ zencod_rsa.rsa_pub_enc = meth_rsa->rsa_pub_enc ;
+ zencod_rsa.rsa_pub_dec = meth_rsa->rsa_pub_dec ;
+ zencod_rsa.rsa_priv_enc = meth_rsa->rsa_priv_enc ;
+ zencod_rsa.rsa_priv_dec = meth_rsa->rsa_priv_dec ;
+ /* meth_rsa->rsa_mod_exp */
+ /* meth_rsa->bn_mod_exp */
+ zencod_rsa.init = meth_rsa->init ;
+ zencod_rsa.finish = meth_rsa->finish ;
+#endif
+
+#ifndef OPENSSL_NO_DSA
+ /* We use OpenSSL meth to supply what we don't provide ;-*)
+ */
+ meth_dsa = DSA_OpenSSL () ;
+
+ /* meth_dsa->dsa_do_sign */
+ zencod_dsa.dsa_sign_setup = meth_dsa->dsa_sign_setup ;
+ /* meth_dsa->dsa_do_verify */
+ zencod_dsa.dsa_mod_exp = meth_dsa->dsa_mod_exp ;
+ /* zencod_dsa.bn_mod_exp = meth_dsa->bn_mod_exp ; */
+ zencod_dsa.init = meth_dsa->init ;
+ zencod_dsa.finish = meth_dsa->finish ;
+#endif
+
+#ifndef OPENSSL_NO_DH
+ /* We use OpenSSL meth to supply what we don't provide ;-*)
+ */
+ meth_dh = DH_OpenSSL () ;
+
+ /* zencod_dh.generate_key = meth_dh->generate_key ; */
+ /* zencod_dh.compute_key = meth_dh->compute_key ; */
+ /* zencod_dh.bn_mod_exp = meth_dh->bn_mod_exp ; */
+ zencod_dh.init = meth_dh->init ;
+ zencod_dh.finish = meth_dh->finish ;
+
+#endif
+
+ /* We use OpenSSL (SSLeay) meth to supply what we don't provide ;-*)
+ */
+ meth_rand = RAND_SSLeay () ;
+
+ /* meth_rand->seed ; */
+ /* zencod_rand.seed = meth_rand->seed ; */
+ /* meth_rand->bytes ; */
+ /* zencod_rand.bytes = meth_rand->bytes ; */
+ zencod_rand.cleanup = meth_rand->cleanup ;
+ zencod_rand.add = meth_rand->add ;
+ /* meth_rand->pseudorand ; */
+ /* zencod_rand.pseudorand = meth_rand->pseudorand ; */
+ /* zencod_rand.status = meth_rand->status ; */
+ /* meth_rand->status ; */
+
+ /* Ensure the zencod error handling is set up */
+ ERR_load_ZENCOD_strings () ;
+ return 1 ;
+}
+
+
+/* As this is only ever called once, there's no need for locking
+ * (indeed - the lock will already be held by our caller!!!)
+ */
+static ENGINE *ENGINE_zencod ( void )
+{
+
+ ENGINE *eng = ENGINE_new () ;
+
+ if ( !eng ) {
+ return NULL ;
+ }
+ if ( !bind_helper ( eng ) ) {
+ ENGINE_free ( eng ) ;
+ return NULL ;
+ }
+
+ return eng ;
+}
+
+
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static
+#endif
+void ENGINE_load_zencod ( void )
+{
+ /* Copied from eng_[openssl|dyn].c */
+ ENGINE *toadd = ENGINE_zencod ( ) ;
+ if ( !toadd ) return ;
+ ENGINE_add ( toadd ) ;
+ ENGINE_free ( toadd ) ;
+ ERR_clear_error ( ) ;
+}
+
+
+/* This is a process-global DSO handle used for loading and unloading
+ * the ZENBRIDGE library.
+ * NB: This is only set (or unset) during an * init () or finish () call
+ * (reference counts permitting) and they're * operating with global locks,
+ * so this should be thread-safe * implicitly.
+ */
+static DSO *zencod_dso = NULL ;
+
+static t_zencod_test *ptr_zencod_test = NULL ;
+static t_zencod_bytes2bits *ptr_zencod_bytes2bits = NULL ;
+static t_zencod_bits2bytes *ptr_zencod_bits2bytes = NULL ;
+static t_zencod_new_number *ptr_zencod_new_number = NULL ;
+static t_zencod_init_number *ptr_zencod_init_number = NULL ;
+
+static t_zencod_rsa_mod_exp *ptr_zencod_rsa_mod_exp = NULL ;
+static t_zencod_rsa_mod_exp_crt *ptr_zencod_rsa_mod_exp_crt = NULL ;
+static t_zencod_dsa_do_sign *ptr_zencod_dsa_do_sign = NULL ;
+static t_zencod_dsa_do_verify *ptr_zencod_dsa_do_verify = NULL ;
+static t_zencod_dh_generate_key *ptr_zencod_dh_generate_key = NULL ;
+static t_zencod_dh_compute_key *ptr_zencod_dh_compute_key = NULL ;
+static t_zencod_rand_bytes *ptr_zencod_rand_bytes = NULL ;
+static t_zencod_math_mod_exp *ptr_zencod_math_mod_exp = NULL ;
+
+static t_zencod_md5_init *ptr_zencod_md5_init = NULL ;
+static t_zencod_md5_update *ptr_zencod_md5_update = NULL ;
+static t_zencod_md5_do_final *ptr_zencod_md5_do_final = NULL ;
+static t_zencod_sha1_init *ptr_zencod_sha1_init = NULL ;
+static t_zencod_sha1_update *ptr_zencod_sha1_update = NULL ;
+static t_zencod_sha1_do_final *ptr_zencod_sha1_do_final = NULL ;
+
+static t_zencod_xdes_cipher *ptr_zencod_xdes_cipher = NULL ;
+static t_zencod_rc4_cipher *ptr_zencod_rc4_cipher = NULL ;
+
+/* These are the static string constants for the DSO file name and the function
+ * symbol names to bind to.
+ */
+static const char *ZENCOD_LIBNAME = ZEN_LIBRARY ;
+
+static const char *ZENCOD_Fct_0 = "test_device" ;
+static const char *ZENCOD_Fct_1 = "zenbridge_bytes2bits" ;
+static const char *ZENCOD_Fct_2 = "zenbridge_bits2bytes" ;
+static const char *ZENCOD_Fct_3 = "zenbridge_new_number" ;
+static const char *ZENCOD_Fct_4 = "zenbridge_init_number" ;
+
+static const char *ZENCOD_Fct_exp_1 = "zenbridge_rsa_mod_exp" ;
+static const char *ZENCOD_Fct_exp_2 = "zenbridge_rsa_mod_exp_crt" ;
+static const char *ZENCOD_Fct_dsa_1 = "zenbridge_dsa_do_sign" ;
+static const char *ZENCOD_Fct_dsa_2 = "zenbridge_dsa_do_verify" ;
+static const char *ZENCOD_Fct_dh_1 = "zenbridge_dh_generate_key" ;
+static const char *ZENCOD_Fct_dh_2 = "zenbridge_dh_compute_key" ;
+static const char *ZENCOD_Fct_rand_1 = "zenbridge_rand_bytes" ;
+static const char *ZENCOD_Fct_math_1 = "zenbridge_math_mod_exp" ;
+
+static const char *ZENCOD_Fct_md5_1 = "zenbridge_md5_init" ;
+static const char *ZENCOD_Fct_md5_2 = "zenbridge_md5_update" ;
+static const char *ZENCOD_Fct_md5_3 = "zenbridge_md5_do_final" ;
+static const char *ZENCOD_Fct_sha1_1 = "zenbridge_sha1_init" ;
+static const char *ZENCOD_Fct_sha1_2 = "zenbridge_sha1_update" ;
+static const char *ZENCOD_Fct_sha1_3 = "zenbridge_sha1_do_final" ;
+
+static const char *ZENCOD_Fct_xdes_1 = "zenbridge_xdes_cipher" ;
+static const char *ZENCOD_Fct_rc4_1 = "zenbridge_rc4_cipher" ;
+
+/* Destructor (complements the "ENGINE_zencod ()" constructor)
+ */
+static int zencod_destroy (ENGINE *e )
+{
+
+ ERR_unload_ZENCOD_strings () ;
+
+ return 1 ;
+}
+
+
+/* (de)initialisation functions. Control Function
+ */
+static int zencod_init ( ENGINE *e )
+{
+
+ t_zencod_test *ptr_0 ;
+ t_zencod_bytes2bits *ptr_1 ;
+ t_zencod_bits2bytes *ptr_2 ;
+ t_zencod_new_number *ptr_3 ;
+ t_zencod_init_number *ptr_4 ;
+ t_zencod_rsa_mod_exp *ptr_exp_1 ;
+ t_zencod_rsa_mod_exp_crt *ptr_exp_2 ;
+ t_zencod_dsa_do_sign *ptr_dsa_1 ;
+ t_zencod_dsa_do_verify *ptr_dsa_2 ;
+ t_zencod_dh_generate_key *ptr_dh_1 ;
+ t_zencod_dh_compute_key *ptr_dh_2 ;
+ t_zencod_rand_bytes *ptr_rand_1 ;
+ t_zencod_math_mod_exp *ptr_math_1 ;
+ t_zencod_md5_init *ptr_md5_1 ;
+ t_zencod_md5_update *ptr_md5_2 ;
+ t_zencod_md5_do_final *ptr_md5_3 ;
+ t_zencod_sha1_init *ptr_sha1_1 ;
+ t_zencod_sha1_update *ptr_sha1_2 ;
+ t_zencod_sha1_do_final *ptr_sha1_3 ;
+ t_zencod_xdes_cipher *ptr_xdes_1 ;
+ t_zencod_rc4_cipher *ptr_rc4_1 ;
+
+ CHEESE () ;
+
+ /*
+ * We Should add some tests for non NULL parameters or bad value !!
+ * Stuff to be done ...
+ */
+
+ if ( zencod_dso != NULL ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_ALREADY_LOADED ) ;
+ goto err ;
+ }
+ /* Trying to load the Library "cryptozen"
+ */
+ zencod_dso = DSO_load ( NULL, ZENCOD_LIBNAME, NULL, 0 ) ;
+ if ( zencod_dso == NULL ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_DSO_FAILURE ) ;
+ goto err ;
+ }
+
+ /* Trying to load Function from the Library
+ */
+ if ( ! ( ptr_1 = (t_zencod_bytes2bits*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_1 ) ) ||
+ ! ( ptr_2 = (t_zencod_bits2bytes*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_2 ) ) ||
+ ! ( ptr_3 = (t_zencod_new_number*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_3 ) ) ||
+ ! ( ptr_4 = (t_zencod_init_number*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_4 ) ) ||
+ ! ( ptr_exp_1 = (t_zencod_rsa_mod_exp*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_exp_1 ) ) ||
+ ! ( ptr_exp_2 = (t_zencod_rsa_mod_exp_crt*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_exp_2 ) ) ||
+ ! ( ptr_dsa_1 = (t_zencod_dsa_do_sign*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dsa_1 ) ) ||
+ ! ( ptr_dsa_2 = (t_zencod_dsa_do_verify*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dsa_2 ) ) ||
+ ! ( ptr_dh_1 = (t_zencod_dh_generate_key*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dh_1 ) ) ||
+ ! ( ptr_dh_2 = (t_zencod_dh_compute_key*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dh_2 ) ) ||
+ ! ( ptr_rand_1 = (t_zencod_rand_bytes*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_rand_1 ) ) ||
+ ! ( ptr_math_1 = (t_zencod_math_mod_exp*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_math_1 ) ) ||
+ ! ( ptr_0 = (t_zencod_test *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_0 ) ) ||
+ ! ( ptr_md5_1 = (t_zencod_md5_init *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_md5_1 ) ) ||
+ ! ( ptr_md5_2 = (t_zencod_md5_update *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_md5_2 ) ) ||
+ ! ( ptr_md5_3 = (t_zencod_md5_do_final *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_md5_3 ) ) ||
+ ! ( ptr_sha1_1 = (t_zencod_sha1_init *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_sha1_1 ) ) ||
+ ! ( ptr_sha1_2 = (t_zencod_sha1_update *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_sha1_2 ) ) ||
+ ! ( ptr_sha1_3 = (t_zencod_sha1_do_final *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_sha1_3 ) ) ||
+ ! ( ptr_xdes_1 = (t_zencod_xdes_cipher *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_xdes_1 ) ) ||
+ ! ( ptr_rc4_1 = (t_zencod_rc4_cipher *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_rc4_1 ) ) ) {
+
+ ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_DSO_FAILURE ) ;
+ goto err ;
+ }
+
+ /* The function from "cryptozen" Library have been correctly loaded so copy them
+ */
+ ptr_zencod_test = ptr_0 ;
+ ptr_zencod_bytes2bits = ptr_1 ;
+ ptr_zencod_bits2bytes = ptr_2 ;
+ ptr_zencod_new_number = ptr_3 ;
+ ptr_zencod_init_number = ptr_4 ;
+ ptr_zencod_rsa_mod_exp = ptr_exp_1 ;
+ ptr_zencod_rsa_mod_exp_crt = ptr_exp_2 ;
+ ptr_zencod_dsa_do_sign = ptr_dsa_1 ;
+ ptr_zencod_dsa_do_verify = ptr_dsa_2 ;
+ ptr_zencod_dh_generate_key = ptr_dh_1 ;
+ ptr_zencod_dh_compute_key = ptr_dh_2 ;
+ ptr_zencod_rand_bytes = ptr_rand_1 ;
+ ptr_zencod_math_mod_exp = ptr_math_1 ;
+ ptr_zencod_test = ptr_0 ;
+ ptr_zencod_md5_init = ptr_md5_1 ;
+ ptr_zencod_md5_update = ptr_md5_2 ;
+ ptr_zencod_md5_do_final = ptr_md5_3 ;
+ ptr_zencod_sha1_init = ptr_sha1_1 ;
+ ptr_zencod_sha1_update = ptr_sha1_2 ;
+ ptr_zencod_sha1_do_final = ptr_sha1_3 ;
+ ptr_zencod_xdes_cipher = ptr_xdes_1 ;
+ ptr_zencod_rc4_cipher = ptr_rc4_1 ;
+
+ /* We should peform a test to see if there is actually any unit runnig on the system ...
+ * Even if the cryptozen library is loaded the module coul not be loaded on the system ...
+ * For now we may just open and close the device !!
+ */
+
+ if ( ptr_zencod_test () != 0 ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_UNIT_FAILURE ) ;
+ goto err ;
+ }
+
+ return 1 ;
+err :
+ if ( zencod_dso ) {
+ DSO_free ( zencod_dso ) ;
+ }
+ zencod_dso = NULL ;
+ ptr_zencod_bytes2bits = NULL ;
+ ptr_zencod_bits2bytes = NULL ;
+ ptr_zencod_new_number = NULL ;
+ ptr_zencod_init_number = NULL ;
+ ptr_zencod_rsa_mod_exp = NULL ;
+ ptr_zencod_rsa_mod_exp_crt = NULL ;
+ ptr_zencod_dsa_do_sign = NULL ;
+ ptr_zencod_dsa_do_verify = NULL ;
+ ptr_zencod_dh_generate_key = NULL ;
+ ptr_zencod_dh_compute_key = NULL ;
+ ptr_zencod_rand_bytes = NULL ;
+ ptr_zencod_math_mod_exp = NULL ;
+ ptr_zencod_test = NULL ;
+ ptr_zencod_md5_init = NULL ;
+ ptr_zencod_md5_update = NULL ;
+ ptr_zencod_md5_do_final = NULL ;
+ ptr_zencod_sha1_init = NULL ;
+ ptr_zencod_sha1_update = NULL ;
+ ptr_zencod_sha1_do_final = NULL ;
+ ptr_zencod_xdes_cipher = NULL ;
+ ptr_zencod_rc4_cipher = NULL ;
+
+ return 0 ;
+}
+
+
+static int zencod_finish ( ENGINE *e )
+{
+
+ CHEESE () ;
+
+ /*
+ * We Should add some tests for non NULL parameters or bad value !!
+ * Stuff to be done ...
+ */
+ if ( zencod_dso == NULL ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_FINISH, ZENCOD_R_NOT_LOADED ) ;
+ return 0 ;
+ }
+ if ( !DSO_free ( zencod_dso ) ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_FINISH, ZENCOD_R_DSO_FAILURE ) ;
+ return 0 ;
+ }
+
+ zencod_dso = NULL ;
+
+ ptr_zencod_bytes2bits = NULL ;
+ ptr_zencod_bits2bytes = NULL ;
+ ptr_zencod_new_number = NULL ;
+ ptr_zencod_init_number = NULL ;
+ ptr_zencod_rsa_mod_exp = NULL ;
+ ptr_zencod_rsa_mod_exp_crt = NULL ;
+ ptr_zencod_dsa_do_sign = NULL ;
+ ptr_zencod_dsa_do_verify = NULL ;
+ ptr_zencod_dh_generate_key = NULL ;
+ ptr_zencod_dh_compute_key = NULL ;
+ ptr_zencod_rand_bytes = NULL ;
+ ptr_zencod_math_mod_exp = NULL ;
+ ptr_zencod_test = NULL ;
+ ptr_zencod_md5_init = NULL ;
+ ptr_zencod_md5_update = NULL ;
+ ptr_zencod_md5_do_final = NULL ;
+ ptr_zencod_sha1_init = NULL ;
+ ptr_zencod_sha1_update = NULL ;
+ ptr_zencod_sha1_do_final = NULL ;
+ ptr_zencod_xdes_cipher = NULL ;
+ ptr_zencod_rc4_cipher = NULL ;
+
+ return 1 ;
+}
+
+
+static int zencod_ctrl ( ENGINE *e, int cmd, long i, void *p, void (*f) () )
+{
+
+ int initialised = ( ( zencod_dso == NULL ) ? 0 : 1 ) ;
+
+ CHEESE () ;
+
+ /*
+ * We Should add some tests for non NULL parameters or bad value !!
+ * Stuff to be done ...
+ */
+ switch ( cmd ) {
+ case ZENCOD_CMD_SO_PATH :
+ if ( p == NULL ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_CTRL, ERR_R_PASSED_NULL_PARAMETER ) ;
+ return 0 ;
+ }
+ if ( initialised ) {
+ ZENCODerr ( ZENCOD_F_ZENCOD_CTRL, ZENCOD_R_ALREADY_LOADED ) ;
+ return 0 ;
+ }
+ ZENCOD_LIBNAME = (const char *) p ;
+ return 1 ;
+ default :
+ break ;
+ }
+
+ ZENCODerr ( ZENCOD_F_ZENCOD_CTRL, ZENCOD_R_CTRL_COMMAND_NOT_IMPLEMENTED ) ;
+
+ return 0 ;
+}
+
+
+/* BIGNUM stuff Functions
+ */
+static int zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx )
+{
+ zen_nb_t y, x, e, n;
+ int ret;
+
+ CHEESE () ;
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_BN_MOD_EXP, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ if ( !bn_wexpand(r, m->top + 1) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_BN_MOD_EXP, ZENCOD_R_BN_EXPAND_FAIL);
+ return 0;
+ }
+
+ memset(r->d, 0, BN_num_bytes(m));
+
+ ptr_zencod_init_number ( &y, (r->dmax - 1) * sizeof (BN_ULONG) * 8, (unsigned char *) r->d ) ;
+ BIGNUM2ZEN ( &x, a ) ;
+ BIGNUM2ZEN ( &e, p ) ;
+ BIGNUM2ZEN ( &n, m ) ;
+
+ /* Must invert x and e parameter due to BN mod exp prototype ... */
+ ret = ptr_zencod_math_mod_exp ( &y, &e, &x, &n ) ;
+
+ if ( ret ) {
+ PERROR("zenbridge_math_mod_exp");
+ ENGINEerr(ZENCOD_F_ZENCOD_BN_MOD_EXP, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ r->top = (BN_num_bits(m) + BN_BITS2 - 1) / BN_BITS2;
+
+ return 1;
+}
+
+
+/* RSA stuff Functions
+ */
+#ifndef OPENSSL_NO_RSA
+static int RSA_zencod_rsa_mod_exp ( BIGNUM *r0, const BIGNUM *i, RSA *rsa )
+{
+
+ CHEESE () ;
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ if ( !rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_BAD_KEY_COMPONENTS);
+ return 0;
+ }
+
+ /* Do in software if argument is too large for hardware */
+ if ( RSA_size(rsa) * 8 > ZENBRIDGE_MAX_KEYSIZE_RSA_CRT ) {
+ const RSA_METHOD *meth;
+
+ meth = RSA_PKCS1_SSLeay();
+ return meth->rsa_mod_exp(r0, i, rsa);
+ } else {
+ zen_nb_t y, x, p, q, dmp1, dmq1, iqmp;
+
+ if ( !bn_expand(r0, RSA_size(rsa) * 8) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_BN_EXPAND_FAIL);
+ return 0;
+ }
+ r0->top = (RSA_size(rsa) * 8 + BN_BITS2 - 1) / BN_BITS2;
+
+ BIGNUM2ZEN ( &x, i ) ;
+ BIGNUM2ZEN ( &y, r0 ) ;
+ BIGNUM2ZEN ( &p, rsa->p ) ;
+ BIGNUM2ZEN ( &q, rsa->q ) ;
+ BIGNUM2ZEN ( &dmp1, rsa->dmp1 ) ;
+ BIGNUM2ZEN ( &dmq1, rsa->dmq1 ) ;
+ BIGNUM2ZEN ( &iqmp, rsa->iqmp ) ;
+
+ if ( ptr_zencod_rsa_mod_exp_crt ( &y, &x, &p, &q, &dmp1, &dmq1, &iqmp ) < 0 ) {
+ PERROR("zenbridge_rsa_mod_exp_crt");
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ return 1;
+ }
+}
+
+
+/* This function is aliased to RSA_mod_exp (with the mont stuff dropped).
+ */
+static int RSA_zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx )
+{
+
+ CHEESE () ;
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ /* Do in software if argument is too large for hardware */
+ if ( BN_num_bits(m) > ZENBRIDGE_MAX_KEYSIZE_RSA ) {
+ const RSA_METHOD *meth;
+
+ meth = RSA_PKCS1_SSLeay();
+ return meth->bn_mod_exp(r, a, p, m, ctx, m_ctx);
+ } else {
+ zen_nb_t y, x, e, n;
+
+ if ( !bn_expand(r, BN_num_bits(m)) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP, ZENCOD_R_BN_EXPAND_FAIL);
+ return 0;
+ }
+ r->top = (BN_num_bits(m) + BN_BITS2 - 1) / BN_BITS2;
+
+ BIGNUM2ZEN ( &x, a ) ;
+ BIGNUM2ZEN ( &y, r ) ;
+ BIGNUM2ZEN ( &e, p ) ;
+ BIGNUM2ZEN ( &n, m ) ;
+
+ if ( ptr_zencod_rsa_mod_exp ( &y, &x, &n, &e ) < 0 ) {
+ PERROR("zenbridge_rsa_mod_exp");
+ ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ return 1;
+ }
+}
+#endif /* !OPENSSL_NO_RSA */
+
+
+#ifndef OPENSSL_NO_DSA
+/* DSA stuff Functions
+ */
+static DSA_SIG *DSA_zencod_do_sign ( const unsigned char *dgst, int dlen, DSA *dsa )
+{
+ zen_nb_t p, q, g, x, y, r, s, data;
+ DSA_SIG *sig;
+ BIGNUM *bn_r = NULL;
+ BIGNUM *bn_s = NULL;
+ char msg[20];
+
+ CHEESE();
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_NOT_LOADED);
+ goto FAILED;
+ }
+
+ if ( dlen > 160 ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
+ goto FAILED;
+ }
+
+ /* Do in software if argument is too large for hardware */
+ if ( BN_num_bits(dsa->p) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ||
+ BN_num_bits(dsa->g) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ) {
+ const DSA_METHOD *meth;
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
+ meth = DSA_OpenSSL();
+ return meth->dsa_do_sign(dgst, dlen, dsa);
+ }
+
+ if ( !(bn_s = BN_new()) || !(bn_r = BN_new()) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
+ goto FAILED;
+ }
+
+ if ( !bn_expand(bn_r, 160) || !bn_expand(bn_s, 160) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BN_EXPAND_FAIL);
+ goto FAILED;
+ }
+
+ bn_r->top = bn_s->top = (160 + BN_BITS2 - 1) / BN_BITS2;
+ BIGNUM2ZEN ( &p, dsa->p ) ;
+ BIGNUM2ZEN ( &q, dsa->q ) ;
+ BIGNUM2ZEN ( &g, dsa->g ) ;
+ BIGNUM2ZEN ( &x, dsa->priv_key ) ;
+ BIGNUM2ZEN ( &y, dsa->pub_key ) ;
+ BIGNUM2ZEN ( &r, bn_r ) ;
+ BIGNUM2ZEN ( &s, bn_s ) ;
+ q.len = x.len = 160;
+
+ ypcmem(msg, dgst, 20);
+ ptr_zencod_init_number ( &data, 160, msg ) ;
+
+ if ( ptr_zencod_dsa_do_sign ( 0, &data, &y, &p, &q, &g, &x, &r, &s ) < 0 ) {
+ PERROR("zenbridge_dsa_do_sign");
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
+ goto FAILED;
+ }
+
+ if ( !( sig = DSA_SIG_new () ) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
+ goto FAILED;
+ }
+ sig->r = bn_r;
+ sig->s = bn_s;
+ return sig;
+
+ FAILED:
+ if (bn_r)
+ BN_free(bn_r);
+ if (bn_s)
+ BN_free(bn_s);
+ return NULL;
+}
+
+
+static int DSA_zencod_do_verify ( const unsigned char *dgst, int dlen, DSA_SIG *sig, DSA *dsa )
+{
+ zen_nb_t data, p, q, g, y, r, s, v;
+ char msg[20];
+ char v_data[20];
+ int ret;
+
+ CHEESE();
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_VERIFY, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ if ( dlen > 160 ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ /* Do in software if argument is too large for hardware */
+ if ( BN_num_bits(dsa->p) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ||
+ BN_num_bits(dsa->g) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ) {
+ const DSA_METHOD *meth;
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
+ meth = DSA_OpenSSL();
+ return meth->dsa_do_verify(dgst, dlen, sig, dsa);
+ }
+
+ BIGNUM2ZEN ( &p, dsa->p ) ;
+ BIGNUM2ZEN ( &q, dsa->q ) ;
+ BIGNUM2ZEN ( &g, dsa->g ) ;
+ BIGNUM2ZEN ( &y, dsa->pub_key ) ;
+ BIGNUM2ZEN ( &r, sig->r ) ;
+ BIGNUM2ZEN ( &s, sig->s ) ;
+ ptr_zencod_init_number ( &v, 160, v_data ) ;
+ ypcmem(msg, dgst, 20);
+ ptr_zencod_init_number ( &data, 160, msg ) ;
+
+ if ( ( ret = ptr_zencod_dsa_do_verify ( 0, &data, &p, &q, &g, &y, &r, &s, &v ) ) < 0 ) {
+ PERROR("zenbridge_dsa_do_verify");
+ ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_VERIFY, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ return ( ( ret == 0 ) ? 1 : ret ) ;
+}
+
+
+static int DSA_zencod_bn_mod_exp ( DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *m_ctx )
+{
+ CHEESE () ;
+
+ return zencod_bn_mod_exp ( r, a, p, m, ctx ) ;
+}
+#endif /* !OPENSSL_NO_DSA */
+
+
+#ifndef OPENSSl_NO_DH
+/* DH stuff Functions
+ */
+static int DH_zencod_generate_key ( DH *dh )
+{
+ BIGNUM *bn_prv = NULL;
+ BIGNUM *bn_pub = NULL;
+ zen_nb_t y, x, g, p;
+ int generate_x;
+
+ CHEESE();
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ /* Private key */
+ if ( dh->priv_key ) {
+ bn_prv = dh->priv_key;
+ generate_x = 0;
+ } else {
+ if (!(bn_prv = BN_new())) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
+ goto FAILED;
+ }
+ generate_x = 1;
+ }
+
+ /* Public key */
+ if ( dh->pub_key )
+ bn_pub = dh->pub_key;
+ else
+ if ( !( bn_pub = BN_new () ) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
+ goto FAILED;
+ }
+
+ /* Expand */
+ if ( !bn_wexpand ( bn_prv, dh->p->dmax ) ||
+ !bn_wexpand ( bn_pub, dh->p->dmax ) ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
+ goto FAILED;
+ }
+ bn_prv->top = dh->p->top;
+ bn_pub->top = dh->p->top;
+
+ /* Convert all keys */
+ BIGNUM2ZEN ( &p, dh->p ) ;
+ BIGNUM2ZEN ( &g, dh->g ) ;
+ BIGNUM2ZEN ( &y, bn_pub ) ;
+ BIGNUM2ZEN ( &x, bn_prv ) ;
+ x.len = DH_size(dh) * 8;
+
+ /* Adjust the lengths of P and G */
+ p.len = ptr_zencod_bytes2bits ( p.data, ZEN_BYTES ( p.len ) ) ;
+ g.len = ptr_zencod_bytes2bits ( g.data, ZEN_BYTES ( g.len ) ) ;
+
+ /* Send the request to the driver */
+ if ( ptr_zencod_dh_generate_key ( &y, &x, &g, &p, generate_x ) < 0 ) {
+ perror("zenbridge_dh_generate_key");
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_REQUEST_FAILED);
+ goto FAILED;
+ }
+
+ dh->priv_key = bn_prv;
+ dh->pub_key = bn_pub;
+
+ return 1;
+
+ FAILED:
+ if (!dh->priv_key && bn_prv)
+ BN_free(bn_prv);
+ if (!dh->pub_key && bn_pub)
+ BN_free(bn_pub);
+
+ return 0;
+}
+
+
+static int DH_zencod_compute_key ( unsigned char *key, const BIGNUM *pub_key, DH *dh )
+{
+ zen_nb_t y, x, p, k;
+
+ CHEESE();
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_COMPUTE, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ if ( !dh->priv_key ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_COMPUTE, ZENCOD_R_BAD_KEY_COMPONENTS);
+ return 0;
+ }
+
+ /* Convert all keys */
+ BIGNUM2ZEN ( &y, pub_key ) ;
+ BIGNUM2ZEN ( &x, dh->priv_key ) ;
+ BIGNUM2ZEN ( &p, dh->p ) ;
+ ptr_zencod_init_number ( &k, p.len, key ) ;
+
+ /* Adjust the lengths */
+ p.len = ptr_zencod_bytes2bits ( p.data, ZEN_BYTES ( p.len ) ) ;
+ y.len = ptr_zencod_bytes2bits ( y.data, ZEN_BYTES ( y.len ) ) ;
+ x.len = ptr_zencod_bytes2bits ( x.data, ZEN_BYTES ( x.len ) ) ;
+
+ /* Call the hardware */
+ if ( ptr_zencod_dh_compute_key ( &k, &y, &x, &p ) < 0 ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_DH_COMPUTE, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ /* The key must be written MSB -> LSB */
+ k.len = ptr_zencod_bytes2bits ( k.data, ZEN_BYTES ( k.len ) ) ;
+ esrever ( key, ZEN_BYTES ( k.len ) ) ;
+
+ return ZEN_BYTES ( k.len ) ;
+}
+
+
+static int DH_zencod_bn_mod_exp ( const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx )
+{
+ CHEESE () ;
+
+ return zencod_bn_mod_exp ( r, a, p, m, ctx ) ;
+}
+#endif /* !OPENSSL_NO_DH */
+
+
+/* RAND stuff Functions
+ */
+static void RAND_zencod_seed ( const void *buf, int num )
+{
+ /* Nothing to do cause our crypto accelerator provide a true random generator */
+}
+
+
+static int RAND_zencod_rand_bytes ( unsigned char *buf, int num )
+{
+ zen_nb_t r;
+
+ CHEESE();
+
+ if ( !zencod_dso ) {
+ ENGINEerr(ZENCOD_F_ZENCOD_RAND, ZENCOD_R_NOT_LOADED);
+ return 0;
+ }
+
+ ptr_zencod_init_number ( &r, num * 8, buf ) ;
+
+ if ( ptr_zencod_rand_bytes ( &r, ZENBRIDGE_RNG_DIRECT ) < 0 ) {
+ PERROR("zenbridge_rand_bytes");
+ ENGINEerr(ZENCOD_F_ZENCOD_RAND, ZENCOD_R_REQUEST_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int RAND_zencod_rand_status ( void )
+{
+ CHEESE () ;
+
+ return 1;
+}
+
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library.
+ */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn ( ENGINE *e, const char *id )
+{
+
+ if ( id && ( strcmp ( id, engine_zencod_id ) != 0 ) ) {
+ return 0 ;
+ }
+ if ( !bind_helper ( e ) ) {
+ return 0 ;
+ }
+
+ return 1 ;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN ()
+IMPLEMENT_DYNAMIC_BIND_FN ( bind_fn )
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+
+
+
+/*
+ * Adding "Digest" and "Cipher" tools ...
+ * This is in development ... ;-)
+ * In orfer to code this, i refer to hw_openbsd_dev_crypto and openssl engine made by Geoff Thorpe (if i'm rigth),
+ * and evp, sha md5 definitions etc ...
+ */
+/* First add some include ... */
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+#include <openssl/rc4.h>
+#include <openssl/des.h>
+
+
+/* Some variables declaration ... */
+/* DONS:
+ * Disable symetric computation except DES and 3DES, but let part of the code
+ */
+/* static int engine_digest_nids [ ] = { NID_sha1, NID_md5 } ; */
+static int engine_digest_nids [ ] = { } ;
+static int engine_digest_nids_num = 0 ;
+/* static int engine_cipher_nids [ ] = { NID_rc4, NID_rc4_40, NID_des_cbc, NID_des_ede3_cbc } ; */
+static int engine_cipher_nids [ ] = { NID_des_cbc, NID_des_ede3_cbc } ;
+static int engine_cipher_nids_num = 2 ;
+
+
+/* Function prototype ... */
+/* SHA stuff */
+static int engine_sha1_init ( EVP_MD_CTX *ctx ) ;
+static int engine_sha1_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count ) ;
+static int engine_sha1_final ( EVP_MD_CTX *ctx, unsigned char *md ) ;
+
+/* MD5 stuff */
+static int engine_md5_init ( EVP_MD_CTX *ctx ) ;
+static int engine_md5_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count ) ;
+static int engine_md5_final ( EVP_MD_CTX *ctx, unsigned char *md ) ;
+
+static int engine_md_cleanup ( EVP_MD_CTX *ctx ) ;
+static int engine_md_copy ( EVP_MD_CTX *to, const EVP_MD_CTX *from ) ;
+
+
+/* RC4 Stuff */
+static int engine_rc4_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc ) ;
+static int engine_rc4_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl ) ;
+
+/* DES Stuff */
+static int engine_des_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc ) ;
+static int engine_des_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl ) ;
+
+/* 3DES Stuff */
+static int engine_des_ede3_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc ) ;
+static int engine_des_ede3_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out,const unsigned char *in, unsigned int inl ) ;
+
+static int engine_cipher_cleanup ( EVP_CIPHER_CTX *ctx ) ; /* cleanup ctx */
+
+
+/* The one for SHA ... */
+static const EVP_MD engine_sha1_md =
+{
+ NID_sha1,
+ NID_sha1WithRSAEncryption,
+ SHA_DIGEST_LENGTH,
+ EVP_MD_FLAG_ONESHOT,
+ /* 0, */ /* EVP_MD_FLAG_ONESHOT = x0001 digest can only handle a single block
+ * XXX: set according to device info ... */
+ engine_sha1_init,
+ engine_sha1_update,
+ engine_sha1_final,
+ engine_md_copy, /* dev_crypto_sha_copy */
+ engine_md_cleanup, /* dev_crypto_sha_cleanup */
+ EVP_PKEY_RSA_method,
+ SHA_CBLOCK,
+ /* sizeof ( EVP_MD * ) + sizeof ( SHA_CTX ) */
+ sizeof ( ZEN_MD_DATA )
+ /* sizeof ( MD_CTX_DATA ) The message digest data stucture ... */
+} ;
+
+/* The one for MD5 ... */
+static const EVP_MD engine_md5_md =
+{
+ NID_md5,
+ NID_md5WithRSAEncryption,
+ MD5_DIGEST_LENGTH,
+ EVP_MD_FLAG_ONESHOT,
+ /* 0, */ /* EVP_MD_FLAG_ONESHOT = x0001 digest can only handle a single block
+ * XXX: set according to device info ... */
+ engine_md5_init,
+ engine_md5_update,
+ engine_md5_final,
+ engine_md_copy, /* dev_crypto_md5_copy */
+ engine_md_cleanup, /* dev_crypto_md5_cleanup */
+ EVP_PKEY_RSA_method,
+ MD5_CBLOCK,
+ /* sizeof ( EVP_MD * ) + sizeof ( MD5_CTX ) */
+ sizeof ( ZEN_MD_DATA )
+ /* sizeof ( MD_CTX_DATA ) The message digest data stucture ... */
+} ;
+
+
+/* The one for RC4 ... */
+#define EVP_RC4_KEY_SIZE 16
+
+/* Try something static ... */
+typedef struct
+{
+ unsigned int len ;
+ unsigned int first ;
+ unsigned char rc4_state [ 260 ] ;
+} NEW_ZEN_RC4_KEY ;
+
+#define rc4_data(ctx) ( (EVP_RC4_KEY *) ( ctx )->cipher_data )
+
+static const EVP_CIPHER engine_rc4 =
+{
+ NID_rc4,
+ 1,
+ 16, /* EVP_RC4_KEY_SIZE should be 128 bits */
+ 0, /* FIXME: key should be up to 256 bytes */
+ EVP_CIPH_VARIABLE_LENGTH,
+ engine_rc4_init_key,
+ engine_rc4_cipher,
+ engine_cipher_cleanup,
+ sizeof ( NEW_ZEN_RC4_KEY ),
+ NULL,
+ NULL,
+ NULL
+} ;
+
+/* The one for RC4_40 ... */
+static const EVP_CIPHER engine_rc4_40 =
+{
+ NID_rc4_40,
+ 1,
+ 5, /* 40 bits */
+ 0,
+ EVP_CIPH_VARIABLE_LENGTH,
+ engine_rc4_init_key,
+ engine_rc4_cipher,
+ engine_cipher_cleanup,
+ sizeof ( NEW_ZEN_RC4_KEY ),
+ NULL,
+ NULL,
+ NULL
+} ;
+
+/* The one for DES ... */
+
+/* Try something static ... */
+typedef struct
+{
+ unsigned char des_key [ 24 ] ;
+ unsigned char des_iv [ 8 ] ;
+} ZEN_DES_KEY ;
+
+static const EVP_CIPHER engine_des_cbc =
+ {
+ NID_des_cbc,
+ 8, 8, 8,
+ 0 | EVP_CIPH_CBC_MODE,
+ engine_des_init_key,
+ engine_des_cbc_cipher,
+ engine_cipher_cleanup,
+ sizeof(ZEN_DES_KEY),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL,
+ NULL
+ };
+
+/* The one for 3DES ... */
+
+/* Try something static ... */
+typedef struct
+{
+ unsigned char des3_key [ 24 ] ;
+ unsigned char des3_iv [ 8 ] ;
+} ZEN_3DES_KEY ;
+
+#define des_data(ctx) ( (DES_EDE_KEY *) ( ctx )->cipher_data )
+
+static const EVP_CIPHER engine_des_ede3_cbc =
+ {
+ NID_des_ede3_cbc,
+ 8, 8, 8,
+ 0 | EVP_CIPH_CBC_MODE,
+ engine_des_ede3_init_key,
+ engine_des_ede3_cbc_cipher,
+ engine_cipher_cleanup,
+ sizeof(ZEN_3DES_KEY),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL,
+ NULL
+ };
+
+
+/* General function cloned on hw_openbsd_dev_crypto one ... */
+static int engine_digests ( ENGINE *e, const EVP_MD **digest, const int **nids, int nid )
+{
+
+#ifdef DEBUG_ZENCOD_MD
+ fprintf ( stderr, "\t=>Function : static int engine_digests () called !\n" ) ;
+#endif
+
+ if ( !digest ) {
+ /* We are returning a list of supported nids */
+ *nids = engine_digest_nids ;
+ return engine_digest_nids_num ;
+ }
+ /* We are being asked for a specific digest */
+ if ( nid == NID_md5 ) {
+ *digest = &engine_md5_md ;
+ }
+ else if ( nid == NID_sha1 ) {
+ *digest = &engine_sha1_md ;
+ }
+ else {
+ *digest = NULL ;
+ return 0 ;
+ }
+ return 1 ;
+}
+
+
+/* SHA stuff Functions
+ */
+static int engine_sha1_init ( EVP_MD_CTX *ctx )
+{
+
+ int to_return = 0 ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_sha1_init ( (ZEN_MD_DATA *) ctx->md_data ) ;
+ to_return = !to_return ;
+
+ return to_return ;
+}
+
+
+static int engine_sha1_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count )
+{
+
+ zen_nb_t input ;
+ int to_return = 0 ;
+
+ /* Convert parameters ... */
+ input.len = count ;
+ input.data = (unsigned char *) data ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_sha1_update ( (ZEN_MD_DATA *) ctx->md_data, (const zen_nb_t *) &input ) ;
+ to_return = !to_return ;
+
+ return to_return ;
+}
+
+
+static int engine_sha1_final ( EVP_MD_CTX *ctx, unsigned char *md )
+{
+
+ zen_nb_t output ;
+ int to_return = 0 ;
+
+ /* Convert parameters ... */
+ output.len = SHA_DIGEST_LENGTH ;
+ output.data = md ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_sha1_do_final ( (ZEN_MD_DATA *) ctx->md_data, (zen_nb_t *) &output ) ;
+ to_return = !to_return ;
+
+ return to_return ;
+}
+
+
+
+/* MD5 stuff Functions
+ */
+static int engine_md5_init ( EVP_MD_CTX *ctx )
+{
+
+ int to_return = 0 ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_md5_init ( (ZEN_MD_DATA *) ctx->md_data ) ;
+ to_return = !to_return ;
+
+ return to_return ;
+}
+
+
+static int engine_md5_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count )
+{
+
+ zen_nb_t input ;
+ int to_return = 0 ;
+
+ /* Convert parameters ... */
+ input.len = count ;
+ input.data = (unsigned char *) data ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_md5_update ( (ZEN_MD_DATA *) ctx->md_data, (const zen_nb_t *) &input ) ;
+ to_return = !to_return ;
+
+ return to_return ;
+}
+
+
+static int engine_md5_final ( EVP_MD_CTX *ctx, unsigned char *md )
+{
+
+ zen_nb_t output ;
+ int to_return = 0 ;
+
+ /* Convert parameters ... */
+ output.len = MD5_DIGEST_LENGTH ;
+ output.data = md ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_md5_do_final ( (ZEN_MD_DATA *) ctx->md_data, (zen_nb_t *) &output ) ;
+ to_return = !to_return ;
+
+ return to_return ;
+}
+
+
+static int engine_md_cleanup ( EVP_MD_CTX *ctx )
+{
+
+ ZEN_MD_DATA *zen_md_data = (ZEN_MD_DATA *) ctx->md_data ;
+
+ if ( zen_md_data->HashBuffer != NULL ) {
+ OPENSSL_free ( zen_md_data->HashBuffer ) ;
+ zen_md_data->HashBufferSize = 0 ;
+ ctx->md_data = NULL ;
+ }
+
+ return 1 ;
+}
+
+
+static int engine_md_copy ( EVP_MD_CTX *to, const EVP_MD_CTX *from )
+{
+ const ZEN_MD_DATA *from_md = (ZEN_MD_DATA *) from->md_data ;
+ ZEN_MD_DATA *to_md = (ZEN_MD_DATA *) to->md_data ;
+
+ to_md->HashBuffer = OPENSSL_malloc ( from_md->HashBufferSize ) ;
+ memcpy ( to_md->HashBuffer, from_md->HashBuffer, from_md->HashBufferSize ) ;
+
+ return 1;
+}
+
+
+/* General function cloned on hw_openbsd_dev_crypto one ... */
+static int engine_ciphers ( ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid )
+{
+
+ if ( !cipher ) {
+ /* We are returning a list of supported nids */
+ *nids = engine_cipher_nids ;
+ return engine_cipher_nids_num ;
+ }
+ /* We are being asked for a specific cipher */
+ if ( nid == NID_rc4 ) {
+ *cipher = &engine_rc4 ;
+ }
+ else if ( nid == NID_rc4_40 ) {
+ *cipher = &engine_rc4_40 ;
+ }
+ else if ( nid == NID_des_cbc ) {
+ *cipher = &engine_des_cbc ;
+ }
+ else if ( nid == NID_des_ede3_cbc ) {
+ *cipher = &engine_des_ede3_cbc ;
+ }
+ else {
+ *cipher = NULL ;
+ return 0 ;
+ }
+
+ return 1 ;
+}
+
+
+static int engine_rc4_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc )
+{
+ int to_return = 0 ;
+ int i = 0 ;
+ int nb = 0 ;
+ NEW_ZEN_RC4_KEY *tmp_rc4_key = NULL ;
+
+ tmp_rc4_key = (NEW_ZEN_RC4_KEY *) ( ctx->cipher_data ) ;
+ tmp_rc4_key->first = 0 ;
+ tmp_rc4_key->len = ctx->key_len ;
+ tmp_rc4_key->rc4_state [ 0 ] = 0x00 ;
+ tmp_rc4_key->rc4_state [ 2 ] = 0x00 ;
+ nb = 256 / ctx->key_len ;
+ for ( i = 0; i < nb ; i++ ) {
+ memcpy ( &( tmp_rc4_key->rc4_state [ 4 + i*ctx->key_len ] ), key, ctx->key_len ) ;
+ }
+
+ to_return = 1 ;
+
+ return to_return ;
+}
+
+
+static int engine_rc4_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int in_len )
+{
+
+ zen_nb_t output, input ;
+ zen_nb_t rc4key ;
+ int to_return = 0 ;
+ NEW_ZEN_RC4_KEY *tmp_rc4_key = NULL ;
+
+ /* Convert parameters ... */
+ input.len = in_len ;
+ input.data = (unsigned char *) in ;
+ output.len = in_len ;
+ output.data = (unsigned char *) out ;
+
+ tmp_rc4_key = ( (NEW_ZEN_RC4_KEY *) ( ctx->cipher_data ) ) ;
+ rc4key.len = 260 ;
+ rc4key.data = &( tmp_rc4_key->rc4_state [ 0 ] ) ;
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_rc4_cipher ( &output, &input, (const zen_nb_t *) &rc4key, &( tmp_rc4_key->rc4_state [0] ), &( tmp_rc4_key->rc4_state [3] ), !tmp_rc4_key->first ) ;
+ to_return = !to_return ;
+
+ /* Update encryption state ... */
+ tmp_rc4_key->first = 1 ;
+ tmp_rc4_key = NULL ;
+
+ return to_return ;
+}
+
+
+static int engine_des_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc )
+{
+
+ ZEN_DES_KEY *tmp_des_key = NULL ;
+ int to_return = 0 ;
+
+ tmp_des_key = (ZEN_DES_KEY *) ( ctx->cipher_data ) ;
+ memcpy ( &( tmp_des_key->des_key [ 0 ] ), key, 8 ) ;
+ memcpy ( &( tmp_des_key->des_key [ 8 ] ), key, 8 ) ;
+ memcpy ( &( tmp_des_key->des_key [ 16 ] ), key, 8 ) ;
+ memcpy ( &( tmp_des_key->des_iv [ 0 ] ), iv, 8 ) ;
+
+ to_return = 1 ;
+
+ return to_return ;
+}
+
+
+static int engine_des_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl )
+{
+
+ zen_nb_t output, input ;
+ zen_nb_t deskey_1, deskey_2, deskey_3, iv ;
+ int to_return = 0 ;
+
+ /* Convert parameters ... */
+ input.len = inl ;
+ input.data = (unsigned char *) in ;
+ output.len = inl ;
+ output.data = out ;
+
+ /* Set key parameters ... */
+ deskey_1.len = 8 ;
+ deskey_2.len = 8 ;
+ deskey_3.len = 8 ;
+ deskey_1.data = (unsigned char *) ( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_key ;
+ deskey_2.data = (unsigned char *) &( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_key [ 8 ] ;
+ deskey_3.data = (unsigned char *) &( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_key [ 16 ] ;
+
+ /* Key correct iv ... */
+ memcpy ( ( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_iv, ctx->iv, 8 ) ;
+ iv.len = 8 ;
+ iv.data = (unsigned char *) ( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_iv ;
+
+ if ( ctx->encrypt == 0 ) {
+ memcpy ( ctx->iv, &( input.data [ input.len - 8 ] ), 8 ) ;
+ }
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_xdes_cipher ( &output, &input,
+ (zen_nb_t *) &deskey_1, (zen_nb_t *) &deskey_2, (zen_nb_t *) &deskey_3, &iv, ctx->encrypt ) ;
+ to_return = !to_return ;
+
+ /* But we need to set up the rigth iv ...
+ * Test ENCRYPT or DECRYPT mode to set iv ... */
+ if ( ctx->encrypt == 1 ) {
+ memcpy ( ctx->iv, &( output.data [ output.len - 8 ] ), 8 ) ;
+ }
+
+ return to_return ;
+}
+
+
+static int engine_des_ede3_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc )
+{
+
+ ZEN_3DES_KEY *tmp_3des_key = NULL ;
+ int to_return = 0 ;
+
+ tmp_3des_key = (ZEN_3DES_KEY *) ( ctx->cipher_data ) ;
+ memcpy ( &( tmp_3des_key->des3_key [ 0 ] ), key, 24 ) ;
+ memcpy ( &( tmp_3des_key->des3_iv [ 0 ] ), iv, 8 ) ;
+
+ to_return = 1;
+
+ return to_return ;
+}
+
+
+static int engine_des_ede3_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
+ unsigned int in_len )
+{
+
+ zen_nb_t output, input ;
+ zen_nb_t deskey_1, deskey_2, deskey_3, iv ;
+ int to_return = 0 ;
+
+ /* Convert parameters ... */
+ input.len = in_len ;
+ input.data = (unsigned char *) in ;
+ output.len = in_len ;
+ output.data = out ;
+
+ /* Set key ... */
+ deskey_1.len = 8 ;
+ deskey_2.len = 8 ;
+ deskey_3.len = 8 ;
+ deskey_1.data = (unsigned char *) ( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_key ;
+ deskey_2.data = (unsigned char *) &( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_key [ 8 ] ;
+ deskey_3.data = (unsigned char *) &( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_key [ 16 ] ;
+
+ /* Key correct iv ... */
+ memcpy ( ( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_iv, ctx->iv, 8 ) ;
+ iv.len = 8 ;
+ iv.data = (unsigned char *) ( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_iv ;
+
+ if ( ctx->encrypt == 0 ) {
+ memcpy ( ctx->iv, &( input.data [ input.len - 8 ] ), 8 ) ;
+ }
+
+ /* Test with zenbridge library ... */
+ to_return = ptr_zencod_xdes_cipher ( &output, &input,
+ (zen_nb_t *) &deskey_1, (zen_nb_t *) &deskey_2, (zen_nb_t *) &deskey_3, &iv, ctx->encrypt ) ;
+ to_return = !to_return ;
+
+ if ( ctx->encrypt == 1 ) {
+ memcpy ( ctx->iv, &( output.data [ output.len - 8 ] ), 8 ) ;
+ }
+
+ return to_return ;
+}
+
+
+static int engine_cipher_cleanup ( EVP_CIPHER_CTX *ctx )
+{
+
+ /* Set the key pointer ... */
+ if ( ctx->cipher->nid == NID_rc4 || ctx->cipher->nid == NID_rc4_40 ) {
+ }
+ else if ( ctx->cipher->nid == NID_des_cbc ) {
+ }
+ else if ( ctx->cipher->nid == NID_des_ede3_cbc ) {
+ }
+
+ return 1 ;
+}
+
+
+#endif /* !OPENSSL_NO_HW_ZENCOD */
+#endif /* !OPENSSL_NO_HW */
diff --git a/crypto/openssl/demos/engines/zencod/hw_zencod.ec b/crypto/openssl/demos/engines/zencod/hw_zencod.ec
new file mode 100644
index 0000000..1552c79
--- /dev/null
+++ b/crypto/openssl/demos/engines/zencod/hw_zencod.ec
@@ -0,0 +1,8 @@
+# configuration file for util/mkerr.pl
+#
+# use like this:
+#
+# perl ../../../util/mkerr.pl -conf hw_zencod.ec \
+# -nostatic -staticloader -write *.c
+
+L ZENCOD hw_zencod_err.h hw_zencod_err.c
diff --git a/crypto/openssl/demos/engines/zencod/hw_zencod.h b/crypto/openssl/demos/engines/zencod/hw_zencod.h
new file mode 100644
index 0000000..195345d
--- /dev/null
+++ b/crypto/openssl/demos/engines/zencod/hw_zencod.h
@@ -0,0 +1,160 @@
+/* File : /crypto/engine/vendor_defns/hw_zencod.h */
+/* ====================================================================
+ * Written by Donnat Frederic (frederic.donnat@zencod.com) from ZENCOD
+ * for "zencod" ENGINE integration in OpenSSL project.
+ */
+
+
+ #ifndef _HW_ZENCOD_H_
+#define _HW_ZENCOD_H_
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define ZENBRIDGE_MAX_KEYSIZE_RSA 2048
+#define ZENBRIDGE_MAX_KEYSIZE_RSA_CRT 1024
+#define ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN 1024
+#define ZENBRIDGE_MAX_KEYSIZE_DSA_VRFY 1024
+
+/* Library version computation */
+#define ZENBRIDGE_VERSION_MAJOR(x) (((x) >> 16) | 0xff)
+#define ZENBRIDGE_VERSION_MINOR(x) (((x) >> 8) | 0xff)
+#define ZENBRIDGE_VERSION_PATCH(x) (((x) >> 0) | 0xff)
+#define ZENBRIDGE_VERSION(x, y, z) ((x) << 16 | (y) << 8 | (z))
+
+/*
+ * Memory type
+ */
+typedef struct zencod_number_s {
+ unsigned long len;
+ unsigned char *data;
+} zen_nb_t;
+
+#define KEY zen_nb_t
+
+
+/*
+ * Misc
+ */
+typedef int t_zencod_lib_version (void);
+typedef int t_zencod_hw_version (void);
+typedef int t_zencod_test (void);
+typedef int t_zencod_dump_key (FILE *stream, char *msg, KEY *key);
+
+
+/*
+ * Key managment tools
+ */
+typedef KEY *t_zencod_new_number (unsigned long len, unsigned char *data);
+typedef int t_zencod_init_number (KEY *n, unsigned long len, unsigned char *data);
+typedef unsigned long t_zencod_bytes2bits (unsigned char *n, unsigned long bytes);
+typedef unsigned long t_zencod_bits2bytes (unsigned long bits);
+
+
+/*
+ * RSA API
+ */
+/* Compute modular exponential : y = x**e | n */
+typedef int t_zencod_rsa_mod_exp (KEY *y, KEY *x, KEY *n, KEY *e);
+/* Compute modular exponential : y1 = (x | p)**edp | p, y2 = (x | p)**edp | p, y = y2 + (qinv * (y1 - y2) | p) * q */
+typedef int t_zencod_rsa_mod_exp_crt (KEY *y, KEY *x, KEY *p, KEY *q,
+ KEY *edp, KEY *edq, KEY *qinv);
+
+
+/*
+ * DSA API
+ */
+typedef int t_zencod_dsa_do_sign (unsigned int hash, KEY *data, KEY *random,
+ KEY *p, KEY *q, KEY *g, KEY *x, KEY *r, KEY *s);
+typedef int t_zencod_dsa_do_verify (unsigned int hash, KEY *data,
+ KEY *p, KEY *q, KEY *g, KEY *y,
+ KEY *r, KEY *s, KEY *v);
+
+
+/*
+ * DH API
+ */
+ /* Key generation : compute public value y = g**x | n */
+typedef int t_zencod_dh_generate_key (KEY *y, KEY *x, KEY *g, KEY *n, int gen_x);
+typedef int t_zencod_dh_compute_key (KEY *k, KEY *y, KEY *x, KEY *n);
+
+
+/*
+ * RNG API
+ */
+#define ZENBRIDGE_RNG_DIRECT 0
+#define ZENBRIDGE_RNG_SHA1 1
+typedef int t_zencod_rand_bytes (KEY *rand, unsigned int flags);
+
+
+/*
+ * Math API
+ */
+typedef int t_zencod_math_mod_exp (KEY *r, KEY *a, KEY *e, KEY *n);
+
+
+
+
+/*
+ * Symetric API
+ */
+/* Define a data structure for digests operations */
+typedef struct ZEN_data_st
+{
+ unsigned int HashBufferSize ;
+ unsigned char *HashBuffer ;
+} ZEN_MD_DATA ;
+
+/*
+ * Functions for Digest (MD5, SHA1) stuff
+ */
+/* output : output data buffer */
+/* input : input data buffer */
+/* algo : hash algorithm, MD5 or SHA1 */
+/* typedef int t_zencod_hash ( KEY *output, const KEY *input, int algo ) ;
+ * typedef int t_zencod_sha_hash ( KEY *output, const KEY *input, int algo ) ;
+ */
+/* For now separate this stuff that mad it easier to test */
+typedef int t_zencod_md5_init ( ZEN_MD_DATA *data ) ;
+typedef int t_zencod_md5_update ( ZEN_MD_DATA *data, const KEY *input ) ;
+typedef int t_zencod_md5_do_final ( ZEN_MD_DATA *data, KEY *output ) ;
+
+typedef int t_zencod_sha1_init ( ZEN_MD_DATA *data ) ;
+typedef int t_zencod_sha1_update ( ZEN_MD_DATA *data, const KEY *input ) ;
+typedef int t_zencod_sha1_do_final ( ZEN_MD_DATA *data, KEY *output ) ;
+
+
+/*
+ * Functions for Cipher (RC4, DES, 3DES) stuff
+ */
+/* output : output data buffer */
+/* input : input data buffer */
+/* key : rc4 key data */
+/* index_1 : value of index x from RC4 key structure */
+/* index_2 : value of index y from RC4 key structure */
+/* Be carefull : RC4 key should be expanded before calling this method (Should we provide an expand function ??) */
+typedef int t_zencod_rc4_cipher ( KEY *output, const KEY *input, const KEY *key,
+ unsigned char *index_1, unsigned char *index_2, int mode ) ;
+
+/* output : output data buffer */
+/* input : input data buffer */
+/* key_1 : des first key data */
+/* key_2 : des second key data */
+/* key_3 : des third key data */
+/* iv : initial vector */
+/* mode : xdes mode (encrypt or decrypt) */
+/* Be carefull : In DES mode key_1 = key_2 = key_3 (as far as i can see !!) */
+typedef int t_zencod_xdes_cipher ( KEY *output, const KEY *input, const KEY *key_1,
+ const KEY *key_2, const KEY *key_3, const KEY *iv, int mode ) ;
+
+
+#undef KEY
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !_HW_ZENCOD_H_ */
diff --git a/crypto/openssl/demos/engines/zencod/hw_zencod_err.c b/crypto/openssl/demos/engines/zencod/hw_zencod_err.c
new file mode 100644
index 0000000..8ed0fff
--- /dev/null
+++ b/crypto/openssl/demos/engines/zencod/hw_zencod_err.c
@@ -0,0 +1,151 @@
+/* hw_zencod_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_zencod_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA ZENCOD_str_functs[]=
+ {
+{ERR_PACK(0,ZENCOD_F_ZENCOD_BN_MOD_EXP,0), "ZENCOD_BN_MOD_EXP"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_CTRL,0), "ZENCOD_CTRL"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_DH_COMPUTE,0), "ZENCOD_DH_COMPUTE"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_DH_GENERATE,0), "ZENCOD_DH_GENERATE"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_DSA_DO_SIGN,0), "ZENCOD_DSA_DO_SIGN"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_DSA_DO_VERIFY,0), "ZENCOD_DSA_DO_VERIFY"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_FINISH,0), "ZENCOD_FINISH"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_INIT,0), "ZENCOD_INIT"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_RAND,0), "ZENCOD_RAND"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_RSA_MOD_EXP,0), "ZENCOD_RSA_MOD_EXP"},
+{ERR_PACK(0,ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT,0), "ZENCOD_RSA_MOD_EXP_CRT"},
+{0,NULL}
+ };
+
+static ERR_STRING_DATA ZENCOD_str_reasons[]=
+ {
+{ZENCOD_R_ALREADY_LOADED ,"already loaded"},
+{ZENCOD_R_BAD_KEY_COMPONENTS ,"bad key components"},
+{ZENCOD_R_BN_EXPAND_FAIL ,"bn expand fail"},
+{ZENCOD_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"},
+{ZENCOD_R_DSO_FAILURE ,"dso failure"},
+{ZENCOD_R_NOT_LOADED ,"not loaded"},
+{ZENCOD_R_REQUEST_FAILED ,"request failed"},
+{ZENCOD_R_UNIT_FAILURE ,"unit failure"},
+{0,NULL}
+ };
+
+#endif
+
+#ifdef ZENCOD_LIB_NAME
+static ERR_STRING_DATA ZENCOD_lib_name[]=
+ {
+{0 ,ZENCOD_LIB_NAME},
+{0,NULL}
+ };
+#endif
+
+
+static int ZENCOD_lib_error_code=0;
+static int ZENCOD_error_init=1;
+
+static void ERR_load_ZENCOD_strings(void)
+ {
+ if (ZENCOD_lib_error_code == 0)
+ ZENCOD_lib_error_code=ERR_get_next_error_library();
+
+ if (ZENCOD_error_init)
+ {
+ ZENCOD_error_init=0;
+#ifndef OPENSSL_NO_ERR
+ ERR_load_strings(ZENCOD_lib_error_code,ZENCOD_str_functs);
+ ERR_load_strings(ZENCOD_lib_error_code,ZENCOD_str_reasons);
+#endif
+
+#ifdef ZENCOD_LIB_NAME
+ ZENCOD_lib_name->error = ERR_PACK(ZENCOD_lib_error_code,0,0);
+ ERR_load_strings(0,ZENCOD_lib_name);
+#endif
+ }
+ }
+
+static void ERR_unload_ZENCOD_strings(void)
+ {
+ if (ZENCOD_error_init == 0)
+ {
+#ifndef OPENSSL_NO_ERR
+ ERR_unload_strings(ZENCOD_lib_error_code,ZENCOD_str_functs);
+ ERR_unload_strings(ZENCOD_lib_error_code,ZENCOD_str_reasons);
+#endif
+
+#ifdef ZENCOD_LIB_NAME
+ ERR_unload_strings(0,ZENCOD_lib_name);
+#endif
+ ZENCOD_error_init=1;
+ }
+ }
+
+static void ERR_ZENCOD_error(int function, int reason, char *file, int line)
+ {
+ if (ZENCOD_lib_error_code == 0)
+ ZENCOD_lib_error_code=ERR_get_next_error_library();
+ ERR_PUT_error(ZENCOD_lib_error_code,function,reason,file,line);
+ }
diff --git a/crypto/openssl/demos/engines/zencod/hw_zencod_err.h b/crypto/openssl/demos/engines/zencod/hw_zencod_err.h
new file mode 100644
index 0000000..1b5dcb5
--- /dev/null
+++ b/crypto/openssl/demos/engines/zencod/hw_zencod_err.h
@@ -0,0 +1,95 @@
+/* ====================================================================
+ * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_ZENCOD_ERR_H
+#define HEADER_ZENCOD_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_ZENCOD_strings(void);
+static void ERR_unload_ZENCOD_strings(void);
+static void ERR_ZENCOD_error(int function, int reason, char *file, int line);
+#define ZENCODerr(f,r) ERR_ZENCOD_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the ZENCOD functions. */
+
+/* Function codes. */
+#define ZENCOD_F_ZENCOD_BN_MOD_EXP 100
+#define ZENCOD_F_ZENCOD_CTRL 101
+#define ZENCOD_F_ZENCOD_DH_COMPUTE 102
+#define ZENCOD_F_ZENCOD_DH_GENERATE 103
+#define ZENCOD_F_ZENCOD_DSA_DO_SIGN 104
+#define ZENCOD_F_ZENCOD_DSA_DO_VERIFY 105
+#define ZENCOD_F_ZENCOD_FINISH 106
+#define ZENCOD_F_ZENCOD_INIT 107
+#define ZENCOD_F_ZENCOD_RAND 108
+#define ZENCOD_F_ZENCOD_RSA_MOD_EXP 109
+#define ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT 110
+
+/* Reason codes. */
+#define ZENCOD_R_ALREADY_LOADED 100
+#define ZENCOD_R_BAD_KEY_COMPONENTS 101
+#define ZENCOD_R_BN_EXPAND_FAIL 102
+#define ZENCOD_R_CTRL_COMMAND_NOT_IMPLEMENTED 103
+#define ZENCOD_R_DSO_FAILURE 104
+#define ZENCOD_R_NOT_LOADED 105
+#define ZENCOD_R_REQUEST_FAILED 106
+#define ZENCOD_R_UNIT_FAILURE 107
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/openssl/demos/maurice/example1.c b/crypto/openssl/demos/maurice/example1.c
index 52152704..1ef8299 100644
--- a/crypto/openssl/demos/maurice/example1.c
+++ b/crypto/openssl/demos/maurice/example1.c
@@ -126,11 +126,11 @@ void main_encrypt(void)
void main_decrypt(void)
{
- char buf[512];
+ char buf[520];
char ebuf[512];
unsigned int buflen;
EVP_CIPHER_CTX ectx;
- unsigned char iv[8];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char *encryptKey;
unsigned int ekeylen;
EVP_PKEY *privateKey;
@@ -164,7 +164,6 @@ void main_decrypt(void)
read(STDIN, encryptKey, ekeylen);
read(STDIN, iv, sizeof(iv));
-
EVP_OpenInit(&ectx,
EVP_des_ede3_cbc(),
encryptKey,
@@ -185,7 +184,6 @@ void main_decrypt(void)
}
EVP_OpenUpdate(&ectx, buf, &buflen, ebuf, readlen);
-
write(STDOUT, buf, buflen);
}
diff --git a/crypto/openssl/demos/maurice/example3.c b/crypto/openssl/demos/maurice/example3.c
index c8462a4..03d8a20 100644
--- a/crypto/openssl/demos/maurice/example3.c
+++ b/crypto/openssl/demos/maurice/example3.c
@@ -57,7 +57,8 @@ void do_cipher(char *pw, int operation)
EVP_BytesToKey(ALG, EVP_md5(), "salu", pw, strlen(pw), 1, key, iv);
- EVP_CipherInit(&ectx, ALG, key, iv, operation);
+ EVP_CIPHER_CTX_init(&ectx);
+ EVP_CipherInit_ex(&ectx, ALG, NULL, key, iv, operation);
while(1)
{
@@ -79,7 +80,8 @@ void do_cipher(char *pw, int operation)
write(STDOUT, ebuf, ebuflen);
}
- EVP_CipherFinal(&ectx, ebuf, &ebuflen);
+ EVP_CipherFinal_ex(&ectx, ebuf, &ebuflen);
+ EVP_CIPHER_CTX_cleanup(&ectx);
write(STDOUT, ebuf, ebuflen);
}
diff --git a/crypto/openssl/demos/maurice/loadkeys.c b/crypto/openssl/demos/maurice/loadkeys.c
index 792371c..82fd22a 100644
--- a/crypto/openssl/demos/maurice/loadkeys.c
+++ b/crypto/openssl/demos/maurice/loadkeys.c
@@ -31,9 +31,7 @@ EVP_PKEY * ReadPublicKey(const char *certfile)
if (!fp)
return NULL;
- x509 = (X509 *)PEM_ASN1_read ((char *(*)())d2i_X509,
- PEM_STRING_X509,
- fp, NULL, NULL, NULL);
+ x509 = PEM_read_X509(fp, NULL, 0, NULL);
if (x509 == NULL)
{
@@ -61,10 +59,7 @@ EVP_PKEY *ReadPrivateKey(const char *keyfile)
if (!fp)
return NULL;
- pkey = (EVP_PKEY*)PEM_ASN1_read ((char *(*)())d2i_PrivateKey,
- PEM_STRING_EVP_PKEY,
- fp,
- NULL, NULL, NULL);
+ pkey = PEM_read_PrivateKey(fp, NULL, 0, NULL);
fclose (fp);
diff --git a/crypto/openssl/demos/sign/sign.c b/crypto/openssl/demos/sign/sign.c
index 0fdf0de..a6c66e1 100644
--- a/crypto/openssl/demos/sign/sign.c
+++ b/crypto/openssl/demos/sign/sign.c
@@ -96,7 +96,7 @@ int main ()
fp = fopen (keyfile, "r");
if (fp == NULL) exit (1);
- pkey = PEM_read_PrivateKey(fp, NULL, NULL);
+ pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
fclose (fp);
if (pkey == NULL) {
@@ -122,7 +122,7 @@ int main ()
fp = fopen (certfile, "r");
if (fp == NULL) exit (1);
- x509 = PEM_read_X509(fp, NULL, NULL);
+ x509 = PEM_read_X509(fp, NULL, NULL, NULL);
fclose (fp);
if (x509 == NULL) {
diff --git a/crypto/openssl/demos/spkigen.c b/crypto/openssl/demos/spkigen.c
index d878811..2cd5dfe 100644
--- a/crypto/openssl/demos/spkigen.c
+++ b/crypto/openssl/demos/spkigen.c
@@ -65,7 +65,8 @@ char *argv[];
fprintf(stderr,"please enter challenge string:");
fflush(stderr);
- fgets(buf,120,stdin);
+ buf[0]='\0';
+ fgets(buf,sizeof buf,stdin);
i=strlen(buf);
if (i > 0) buf[--i]='\0';
if (!ASN1_STRING_set((ASN1_STRING *)spki->spkac->challenge,
diff --git a/crypto/openssl/demos/ssl/cli.cpp b/crypto/openssl/demos/ssl/cli.cpp
index daea2bd..49cba5d 100644
--- a/crypto/openssl/demos/ssl/cli.cpp
+++ b/crypto/openssl/demos/ssl/cli.cpp
@@ -79,12 +79,12 @@ void main ()
str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
- Free (str);
+ OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
- Free (str);
+ OPENSSL_free (str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
diff --git a/crypto/openssl/demos/ssl/inetdsrv.cpp b/crypto/openssl/demos/ssl/inetdsrv.cpp
index 5b09227..efd70d2 100644
--- a/crypto/openssl/demos/ssl/inetdsrv.cpp
+++ b/crypto/openssl/demos/ssl/inetdsrv.cpp
@@ -65,12 +65,12 @@ void main ()
str = X509_NAME_oneline (X509_get_subject_name (client_cert));
CHK_NULL(str);
fprintf (log, "\t subject: %s\n", str);
- Free (str);
+ OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name (client_cert));
CHK_NULL(str);
fprintf (log, "\t issuer: %s\n", str);
- Free (str);
+ OPENSSL_free (str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
diff --git a/crypto/openssl/demos/ssl/serv.cpp b/crypto/openssl/demos/ssl/serv.cpp
index aec610d..b142c75 100644
--- a/crypto/openssl/demos/ssl/serv.cpp
+++ b/crypto/openssl/demos/ssl/serv.cpp
@@ -121,12 +121,12 @@ void main ()
str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
- Free (str);
+ OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
- Free (str);
+ OPENSSL_free (str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
diff --git a/crypto/openssl/demos/state_machine/state_machine.c b/crypto/openssl/demos/state_machine/state_machine.c
index 0140fbc..fef3f3e 100644
--- a/crypto/openssl/demos/state_machine/state_machine.c
+++ b/crypto/openssl/demos/state_machine/state_machine.c
@@ -191,6 +191,9 @@ int SSLStateMachine_read_extract(SSLStateMachine *pMachine,
fprintf(stderr,"SSL_read wants more data\n");
return 0;
}
+
+ SSLStateMachine_print_error(pMachine,"SSL_read error");
+ exit(8);
}
fprintf(stderr,"%d bytes of decrypted data read from state machine\n",n);
@@ -289,6 +292,8 @@ int main(int argc,char **argv)
int nFD;
const char *szCertificateFile;
const char *szKeyFile;
+ char rbuf[1];
+ int nrbuf=0;
if(argc != 4)
{
@@ -321,6 +326,14 @@ int main(int argc,char **argv)
/* Select socket for input */
FD_SET(nFD,&rfds);
+ /* check whether there's decrypted data */
+ if(!nrbuf)
+ nrbuf=SSLStateMachine_read_extract(pMachine,rbuf,1);
+
+ /* if there's decrypted data, check whether we can write it */
+ if(nrbuf)
+ FD_SET(1,&wfds);
+
/* Select socket for output */
if(SSLStateMachine_write_can_extract(pMachine))
FD_SET(nFD,&wfds);
@@ -346,21 +359,29 @@ int main(int argc,char **argv)
SSLStateMachine_read_inject(pMachine,buf,n);
}
- /* FIXME: we should only extract if stdout is ready */
- n=SSLStateMachine_read_extract(pMachine,buf,n);
- if(n < 0)
+ /* stdout is ready for output (and hence we have some to send it) */
+ if(FD_ISSET(1,&wfds))
{
- SSLStateMachine_print_error(pMachine,"read extract failed");
- break;
- }
- assert(n >= 0);
- if(n > 0)
- {
- int w;
+ assert(nrbuf == 1);
+ buf[0]=rbuf[0];
+ nrbuf=0;
- w=write(1,buf,n);
- /* FIXME: we should push back any unwritten data */
- assert(w == n);
+ n=SSLStateMachine_read_extract(pMachine,buf+1,sizeof buf-1);
+ if(n < 0)
+ {
+ SSLStateMachine_print_error(pMachine,"read extract failed");
+ break;
+ }
+ assert(n >= 0);
+ ++n;
+ if(n > 0) /* FIXME: has to be true now */
+ {
+ int w;
+
+ w=write(1,buf,n);
+ /* FIXME: we should push back any unwritten data */
+ assert(w == n);
+ }
}
/* Socket is ready for output (and therefore we have output to send) */
diff --git a/crypto/openssl/demos/tunala/A-client.pem b/crypto/openssl/demos/tunala/A-client.pem
new file mode 100644
index 0000000..a4caf6ef
--- /dev/null
+++ b/crypto/openssl/demos/tunala/A-client.pem
@@ -0,0 +1,84 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=NZ, L=Wellington, O=Really Irresponsible Authorisation Authority (RIAA), OU=Cert-stamping, CN=Jackov al-Trades/Email=none@fake.domain
+ Validity
+ Not Before: Jan 16 05:19:30 2002 GMT
+ Not After : Jan 14 05:19:30 2012 GMT
+ Subject: C=NZ, L=Auckland, O=Mordor, OU=SSL grunt things, CN=tunala-client/Email=client@fake.domain
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:b0:d3:56:5c:c8:7f:fb:f4:95:9d:04:84:4f:82:
+ b7:a2:75:5c:81:48:8c:56:5d:52:ee:38:e1:5c:c8:
+ 9a:70:8e:72:f2:00:1c:17:ef:df:b7:06:59:82:04:
+ f1:f6:49:11:12:a6:4d:cb:1e:ed:ac:59:1c:4a:d0:
+ 3d:de:e6:f2:8d:cd:39:c2:0f:e0:46:2f:db:cb:9f:
+ 47:f7:56:e7:f8:16:5f:68:71:fb:3a:e3:ab:d2:e5:
+ 05:b7:da:65:61:fe:6d:30:e4:12:a8:b5:c1:71:24:
+ 6b:aa:80:05:41:17:a0:8b:6e:8b:e6:04:cf:85:7b:
+ 2a:ac:a1:79:7d:f4:96:6e:77
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ F8:43:CB:4F:4D:4F:BC:6E:52:1A:FD:F9:7B:E1:12:3F:A7:A3:BA:93
+ X509v3 Authority Key Identifier:
+ keyid:49:FB:45:72:12:C4:CC:E1:45:A1:D3:08:9E:95:C4:2C:6D:55:3F:17
+ DirName:/C=NZ/L=Wellington/O=Really Irresponsible Authorisation Authority (RIAA)/OU=Cert-stamping/CN=Jackov al-Trades/Email=none@fake.domain
+ serial:00
+
+ Signature Algorithm: md5WithRSAEncryption
+ 8f:5f:0e:43:da:9d:61:43:7e:03:38:9a:e6:50:9d:42:e8:95:
+ 34:49:75:ec:04:8d:5c:85:99:94:70:a0:e7:1f:1e:a0:8b:0f:
+ d6:e2:cb:f7:35:d9:96:72:bd:a6:e9:8d:4e:b1:e2:ac:97:7f:
+ 2f:70:01:9d:aa:04:bc:d4:01:2b:63:77:a5:de:63:3c:a8:f5:
+ f2:72:af:ec:11:12:c0:d4:70:cf:71:a6:fb:e9:1d:b3:27:07:
+ aa:f2:b1:f3:87:d6:ab:8b:ce:c2:08:1b:3c:f9:ba:ff:77:71:
+ 86:09:ef:9e:4e:04:06:63:44:e9:93:20:90:c7:2d:50:c6:50:
+ f8:66
+-----BEGIN CERTIFICATE-----
+MIID9TCCA16gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBtDELMAkGA1UEBhMCTlox
+EzARBgNVBAcTCldlbGxpbmd0b24xPDA6BgNVBAoTM1JlYWxseSBJcnJlc3BvbnNp
+YmxlIEF1dGhvcmlzYXRpb24gQXV0aG9yaXR5IChSSUFBKTEWMBQGA1UECxMNQ2Vy
+dC1zdGFtcGluZzEZMBcGA1UEAxMQSmFja292IGFsLVRyYWRlczEfMB0GCSqGSIb3
+DQEJARYQbm9uZUBmYWtlLmRvbWFpbjAeFw0wMjAxMTYwNTE5MzBaFw0xMjAxMTQw
+NTE5MzBaMIGHMQswCQYDVQQGEwJOWjERMA8GA1UEBxMIQXVja2xhbmQxDzANBgNV
+BAoTBk1vcmRvcjEZMBcGA1UECxMQU1NMIGdydW50IHRoaW5nczEWMBQGA1UEAxMN
+dHVuYWxhLWNsaWVudDEhMB8GCSqGSIb3DQEJARYSY2xpZW50QGZha2UuZG9tYWlu
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw01ZcyH/79JWdBIRPgreidVyB
+SIxWXVLuOOFcyJpwjnLyABwX79+3BlmCBPH2SRESpk3LHu2sWRxK0D3e5vKNzTnC
+D+BGL9vLn0f3Vuf4Fl9ocfs646vS5QW32mVh/m0w5BKotcFxJGuqgAVBF6CLbovm
+BM+FeyqsoXl99JZudwIDAQABo4IBQDCCATwwCQYDVR0TBAIwADAsBglghkgBhvhC
+AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFPhD
+y09NT7xuUhr9+XvhEj+no7qTMIHhBgNVHSMEgdkwgdaAFEn7RXISxMzhRaHTCJ6V
+xCxtVT8XoYG6pIG3MIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3Rv
+bjE8MDoGA1UEChMzUmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNhdGlvbiBB
+dXRob3JpdHkgKFJJQUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkwFwYDVQQD
+ExBKYWNrb3YgYWwtVHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZha2UuZG9t
+YWluggEAMA0GCSqGSIb3DQEBBAUAA4GBAI9fDkPanWFDfgM4muZQnULolTRJdewE
+jVyFmZRwoOcfHqCLD9biy/c12ZZyvabpjU6x4qyXfy9wAZ2qBLzUAStjd6XeYzyo
+9fJyr+wREsDUcM9xpvvpHbMnB6rysfOH1quLzsIIGzz5uv93cYYJ755OBAZjROmT
+IJDHLVDGUPhm
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQCw01ZcyH/79JWdBIRPgreidVyBSIxWXVLuOOFcyJpwjnLyABwX
+79+3BlmCBPH2SRESpk3LHu2sWRxK0D3e5vKNzTnCD+BGL9vLn0f3Vuf4Fl9ocfs6
+46vS5QW32mVh/m0w5BKotcFxJGuqgAVBF6CLbovmBM+FeyqsoXl99JZudwIDAQAB
+AoGAU4chbqbPvkclPYzaq2yGLlneHrwUft+KwzlfS6L/QVgo+CQRIUWQmjaHpaGM
+YtjVFcg1S1QK1bUqZjTEZT0XKhfbYmqW8yYTfbcDEbnY7esoYlvIlW8qRlPRlTBE
+utKrtZafmVhLgoNawYGD0aLZofPqpYjbGUlrC7nrem2vNJECQQDVLD3Qb+OlEMET
+73ApnJhYsK3e+G2LTrtjrS8y5zS4+Xv61XUqvdV7ogzRl0tpvSAmMOItVyoYadkB
+S3xSIWX9AkEA1Fm1FhkQSZwGG5rf4c6gMN71jJ6JE3/kocdVa0sUjRevIupo4XQ2
+Vkykxi84MRP8cfHqyjewq7Ozv3op2MGWgwJBAKemsb66IJjzAkaBav7u70nhOf0/
++Dc1Zl7QF2y7NVW8sGrnccx5m+ot2lMD4AV6/kvK6jaqdKrapBZGnbGiHqkCQQDI
+T1r33mqz1R8Z2S2Jtzz6/McKf930a/dC+GLGVEutkILf39lRmytKmv/wB0jtWtoO
+rlJ5sLDSNzC+1cE1u997AkEAu3IrtGmLKiuS6kDj6W47m+iiTIsuSJtTJb1SbUaK
+fIoBNFxbvJYW6rUU9+PxpMRaEhzh5s24/jBOE+mlb17mRQ==
+-----END RSA PRIVATE KEY-----
diff --git a/crypto/openssl/demos/tunala/A-server.pem b/crypto/openssl/demos/tunala/A-server.pem
new file mode 100644
index 0000000..e9f37b1
--- /dev/null
+++ b/crypto/openssl/demos/tunala/A-server.pem
@@ -0,0 +1,84 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=NZ, L=Wellington, O=Really Irresponsible Authorisation Authority (RIAA), OU=Cert-stamping, CN=Jackov al-Trades/Email=none@fake.domain
+ Validity
+ Not Before: Jan 16 05:14:06 2002 GMT
+ Not After : Jan 14 05:14:06 2012 GMT
+ Subject: C=NZ, L=Wellington, O=Middle Earth, OU=SSL dev things, CN=tunala-server/Email=server@fake.domain
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a9:3e:62:87:97:13:6b:de:8f:bc:1d:0a:3f:65:
+ 0c:f9:76:a3:53:ce:97:30:27:0d:c6:df:72:1f:8d:
+ 5a:ce:58:23:6a:65:e5:e3:72:1a:8d:7f:fe:90:01:
+ ea:42:f1:9f:6e:7b:0a:bd:eb:52:15:7b:f4:3d:9c:
+ 4e:db:74:29:2b:d1:81:9d:b9:9e:18:2b:87:e1:da:
+ 50:20:3c:59:6c:c9:83:3e:2c:11:0b:78:1e:03:f4:
+ 56:3a:db:95:6a:75:33:85:a9:7b:cc:3c:4a:67:96:
+ f2:24:b2:a0:cb:2e:cc:52:18:16:6f:44:d9:29:64:
+ 07:2e:fb:56:cc:7c:dc:a2:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 70:AC:7A:B5:6E:97:C2:82:AF:11:9E:32:CB:8D:48:49:93:B7:DC:22
+ X509v3 Authority Key Identifier:
+ keyid:49:FB:45:72:12:C4:CC:E1:45:A1:D3:08:9E:95:C4:2C:6D:55:3F:17
+ DirName:/C=NZ/L=Wellington/O=Really Irresponsible Authorisation Authority (RIAA)/OU=Cert-stamping/CN=Jackov al-Trades/Email=none@fake.domain
+ serial:00
+
+ Signature Algorithm: md5WithRSAEncryption
+ 2e:cb:a3:cd:6d:a8:9d:d1:dc:e5:f0:e0:27:7e:4b:5a:90:a8:
+ 85:43:f0:05:f7:04:43:d7:5f:d1:a5:8f:5c:58:eb:fc:da:c6:
+ 7c:e0:0b:2b:98:72:95:f6:79:48:96:7a:fa:0c:6b:09:ec:c6:
+ 8c:91:74:45:9f:8f:0f:16:78:e3:66:14:fa:1e:f4:f0:23:ec:
+ cd:a9:52:77:20:4d:c5:05:2c:52:b6:7b:f3:42:33:fd:90:1f:
+ 3e:88:6f:9b:23:61:c8:80:3b:e6:57:84:2e:f7:26:c7:35:ed:
+ 00:8b:08:30:9b:aa:21:83:b6:6d:b8:7c:8a:9b:2a:ef:79:3d:
+ 96:31
+-----BEGIN CERTIFICATE-----
+MIID+zCCA2SgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBtDELMAkGA1UEBhMCTlox
+EzARBgNVBAcTCldlbGxpbmd0b24xPDA6BgNVBAoTM1JlYWxseSBJcnJlc3BvbnNp
+YmxlIEF1dGhvcmlzYXRpb24gQXV0aG9yaXR5IChSSUFBKTEWMBQGA1UECxMNQ2Vy
+dC1zdGFtcGluZzEZMBcGA1UEAxMQSmFja292IGFsLVRyYWRlczEfMB0GCSqGSIb3
+DQEJARYQbm9uZUBmYWtlLmRvbWFpbjAeFw0wMjAxMTYwNTE0MDZaFw0xMjAxMTQw
+NTE0MDZaMIGNMQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3RvbjEVMBMG
+A1UEChMMTWlkZGxlIEVhcnRoMRcwFQYDVQQLEw5TU0wgZGV2IHRoaW5nczEWMBQG
+A1UEAxMNdHVuYWxhLXNlcnZlcjEhMB8GCSqGSIb3DQEJARYSc2VydmVyQGZha2Uu
+ZG9tYWluMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpPmKHlxNr3o+8HQo/
+ZQz5dqNTzpcwJw3G33IfjVrOWCNqZeXjchqNf/6QAepC8Z9uewq961IVe/Q9nE7b
+dCkr0YGduZ4YK4fh2lAgPFlsyYM+LBELeB4D9FY625VqdTOFqXvMPEpnlvIksqDL
+LsxSGBZvRNkpZAcu+1bMfNyi1wIDAQABo4IBQDCCATwwCQYDVR0TBAIwADAsBglg
+hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
+BBYEFHCserVul8KCrxGeMsuNSEmTt9wiMIHhBgNVHSMEgdkwgdaAFEn7RXISxMzh
+RaHTCJ6VxCxtVT8XoYG6pIG3MIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2Vs
+bGluZ3RvbjE8MDoGA1UEChMzUmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNh
+dGlvbiBBdXRob3JpdHkgKFJJQUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkw
+FwYDVQQDExBKYWNrb3YgYWwtVHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZh
+a2UuZG9tYWluggEAMA0GCSqGSIb3DQEBBAUAA4GBAC7Lo81tqJ3R3OXw4Cd+S1qQ
+qIVD8AX3BEPXX9Glj1xY6/zaxnzgCyuYcpX2eUiWevoMawnsxoyRdEWfjw8WeONm
+FPoe9PAj7M2pUncgTcUFLFK2e/NCM/2QHz6Ib5sjYciAO+ZXhC73Jsc17QCLCDCb
+qiGDtm24fIqbKu95PZYx
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCpPmKHlxNr3o+8HQo/ZQz5dqNTzpcwJw3G33IfjVrOWCNqZeXj
+chqNf/6QAepC8Z9uewq961IVe/Q9nE7bdCkr0YGduZ4YK4fh2lAgPFlsyYM+LBEL
+eB4D9FY625VqdTOFqXvMPEpnlvIksqDLLsxSGBZvRNkpZAcu+1bMfNyi1wIDAQAB
+AoGANCwqHZhiAU/TyW6+WPqivEhpYw19p/dyFMuPF9DwnEmpaUROUQY8z0AUznn4
+qHhp6Jn/nrprTHowucl0ucweYIYVxZoUiUDFpxdFUbzMdFvo6HcyV1Pe4Rt81HaY
+KYWrTZ6PaPtN65hLms8NhPEdGcGAFlY1owYv4QNGq2bU1JECQQDd32LM0NSfyGmK
+4ziajqGcvzK9NO2XyV/nJsGlJZNgMh2zm1t7yR28l/6Q2uyU49cCN+2aYULZCAfs
+taNvxBspAkEAw0alNub+xj2AVQvaxOB1sGfKzsJjHCzKIxUXn/tJi3j0+2asmkBZ
+Umx1MWr9jKQBnCMciCRUbnMEZiElOxCN/wJAfAeQl6Z19gx206lJzzzEo3dOye54
+k02DSxijT8q9pBzf9bN3ZK987BybtiZr8p+bZiYVsSOF1wViSLURdD1QYQJAIaMU
+qH1n24wShBPTrmAfxbBLTgxL+Dl65Eoo1KT7iSvfv0JzbuqwuDL4iPeuD0DdCiE+
+M/FWHeRwGIuTFzaFzwJBANKwx0jZS/h093w9g0Clw6UzeA1P5VcAt9y+qMC9hO3c
+4KXwIxQAt9yRaFLpiIR9do5bjjKNnMguf3aO/XRSDQM=
+-----END RSA PRIVATE KEY-----
diff --git a/crypto/openssl/demos/tunala/CA.pem b/crypto/openssl/demos/tunala/CA.pem
new file mode 100644
index 0000000..7a55b54
--- /dev/null
+++ b/crypto/openssl/demos/tunala/CA.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID9zCCA2CgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtDELMAkGA1UEBhMCTlox
+EzARBgNVBAcTCldlbGxpbmd0b24xPDA6BgNVBAoTM1JlYWxseSBJcnJlc3BvbnNp
+YmxlIEF1dGhvcmlzYXRpb24gQXV0aG9yaXR5IChSSUFBKTEWMBQGA1UECxMNQ2Vy
+dC1zdGFtcGluZzEZMBcGA1UEAxMQSmFja292IGFsLVRyYWRlczEfMB0GCSqGSIb3
+DQEJARYQbm9uZUBmYWtlLmRvbWFpbjAeFw0wMjAxMTYwNTA5NTlaFw0xMjAxMTQw
+NTA5NTlaMIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3RvbjE8MDoG
+A1UEChMzUmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNhdGlvbiBBdXRob3Jp
+dHkgKFJJQUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkwFwYDVQQDExBKYWNr
+b3YgYWwtVHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZha2UuZG9tYWluMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7QdDfFIrJn3X24hKmpkyk3TG0Ivxd
+K2wWmDPXq1wjr8lUTwrA6hM5Ba9N36jLieWpXhviLOWu9DBza5GmtgCuXloATKTC
+94xOdKHlciTVujG3wDlLDB5e710Kar84nnj6VueL1RyZ0bmP5PANa4mbGW9Tqc7J
+CkBTTW2y9d0SgQIDAQABo4IBFTCCAREwHQYDVR0OBBYEFEn7RXISxMzhRaHTCJ6V
+xCxtVT8XMIHhBgNVHSMEgdkwgdaAFEn7RXISxMzhRaHTCJ6VxCxtVT8XoYG6pIG3
+MIG0MQswCQYDVQQGEwJOWjETMBEGA1UEBxMKV2VsbGluZ3RvbjE8MDoGA1UEChMz
+UmVhbGx5IElycmVzcG9uc2libGUgQXV0aG9yaXNhdGlvbiBBdXRob3JpdHkgKFJJ
+QUEpMRYwFAYDVQQLEw1DZXJ0LXN0YW1waW5nMRkwFwYDVQQDExBKYWNrb3YgYWwt
+VHJhZGVzMR8wHQYJKoZIhvcNAQkBFhBub25lQGZha2UuZG9tYWluggEAMAwGA1Ud
+EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAYQo95V/NY+eKxYxkhibZiUQygph+
+gTfgbDG20MsnH6+8//w5ArHauFCgDrf0P2VyACgq+N4pBTWFGaAaLwbjKy9HCe2E
+j9C91tO1CqDS4MJkDB5AP13FTkK6fP1ZCiTQranOAp3DlGWTTWsFVyW5kVfQ9diS
+ZOyJZ9Fit5XM2X0=
+-----END CERTIFICATE-----
diff --git a/crypto/openssl/demos/tunala/INSTALL b/crypto/openssl/demos/tunala/INSTALL
new file mode 100644
index 0000000..a65bbeb
--- /dev/null
+++ b/crypto/openssl/demos/tunala/INSTALL
@@ -0,0 +1,107 @@
+There are two ways to build this code;
+
+(1) Manually
+
+(2) Using all-singing all-dancing (all-confusing) autotools, ie. autoconf,
+automake, and their little friends (autoheader, etc).
+
+=================
+Building Manually
+=================
+
+There is a basic "Makefile" in this directory that gets moved out of the way and
+ignored when building with autoconf et al. This Makefile is suitable for
+building tunala on Linux using gcc. Any other platform probably requires some
+tweaking. Here are the various bits you might need to do if you want to build
+this way and the default Makefile isn't sufficient;
+
+* Compiler: Edit the "CC" definition in Makefile
+
+* Headers, features: tunala.h controls what happens in the non-autoconf world.
+ It, by default, assumes the system has *everything* (except autoconf's
+ "config.h") so if a target system is missing something it must define the
+ appropriate "NO_***" symbols in CFLAGS. These include;
+
+ - NO_HAVE_UNISTD_H, NO_HAVE_FCNTL_H, NO_HAVE_LIMITS_H
+ Indicates the compiling system doesn't have (or need) these header files.
+ - NO_HAVE_STRSTR, NO_HAVE_STRTOUL
+ Indicates the compiling system doesn't have these functions. Replacements
+ are compiled and used in breakage.c
+ - NO_HAVE_SELECT, NO_HAVE_SOCKET
+ Pointless symbols - these indicate select() and/or socket() are missing in
+ which case the program won't compile anyway.
+
+ If you want to specify any of these, add them with "-D" prefixed to each in
+ the CFLAGS definition in Makefile.
+
+* Compilation flags: edit DEBUG_FLAGS and/or CFLAGS directly to control the
+ flags passed to the compiler. This can also be used to change the degree of
+ optimisation.
+
+* Linker flags: some systems (eg. Solaris) require extra linker flags such as;
+ -ldl, -lsocket, -lnsl, etc. If unsure, bring up the man page for whichever
+ function is "undefined" when the linker fails - that usually indicates what
+ you need to add. Make changes to the LINK_FLAGS symbol.
+
+* Linker command: if a different linker syntax or even a different program is
+ required to link, edit the linker line directly in the "tunala:" target
+ definition - it currently assumes the "CC" (compiler) program is used to link.
+
+======================
+Building Automagically
+======================
+
+Automagic building is handled courtesy of autoconf, automake, etc. There are in
+fact two steps required to build, and only the first has to be done on a system
+with these tools installed (and if I was prepared to bloat out the CVS
+repository, I could store these extra files, but I'm not).
+
+First step: "autogunk.sh"
+-------------------------
+
+The "./autogunk.sh" script will call all the necessary autotool commands to
+create missing files and run automake and autoconf. The result is that a
+"./configure" script should be generated and a "Makefile.in" generated from the
+supplied "Makefile.am". NB: This script also moves the "manual" Makefile (see
+above) out of the way and calls it "Makefile.plain" - the "ungunk" script
+reverses this to leave the directory it was previously.
+
+Once "ungunk" has been run, the resulting directory should be able to build on
+other systems without autoconf, automake, or libtool. Which is what the second
+step describes;
+
+Second step: "./configure"
+--------------------------
+
+The second step is to run the generated "./configure" script to create a
+config.h header for your system and to generate a "Makefile" (generated from
+"Makefile.in") tweaked to compile on your system. This is the standard sort of
+thing you see in GNU packages, for example, and the standard tricks also work.
+Eg. to override "configure"'s choice of compiler, set the CC environment
+variable prior to running configure, eg.
+
+ CC=gcc ./configure
+
+would cause "gcc" to be used even if there is an otherwise preferable (to
+autoconf) native compiler on your system.
+
+After this run "make" and it should build the "tunala" executable.
+
+Notes
+-----
+
+- Some versions of autoconf (or automake?) generate a Makefile syntax that gives
+ trouble to some "make" programs on some systems (eg. OpenBSD). If this
+ happens, either build 'Manually' (see above) or use "gmake" instead of "make".
+ I don't like this either but like even less the idea of sifting into all the
+ script magic crud that's involved.
+
+- On a solaris system I tried, the "configure" script specified some broken
+ compiler flags in the resulting Makefile that don't even get echoed to
+ stdout/err when the error happens (evil!). If this happens, go into the
+ generated Makefile, find the two affected targets ("%.o:" and "%.lo"), and
+ remove the offending hidden option in the $(COMPILE) line all the sludge after
+ the two first lines of script (ie. after the "echo" and the "COMPILE" lines).
+ NB: This will probably only function if "--disable-shared" was used, otherwise
+ who knows what would result ...
+
diff --git a/crypto/openssl/demos/tunala/Makefile b/crypto/openssl/demos/tunala/Makefile
new file mode 100644
index 0000000..bef1704
--- /dev/null
+++ b/crypto/openssl/demos/tunala/Makefile
@@ -0,0 +1,41 @@
+# Edit these to suit
+#
+# Oh yeah, and please read the README too.
+
+
+SSL_HOMEDIR=../..
+SSL_INCLUDEDIR=$(SSL_HOMEDIR)/include
+SSL_LIBDIR=$(SSL_HOMEDIR)
+
+RM=rm -f
+CC=gcc
+DEBUG_FLAGS=-g -ggdb3 -Wall -Wshadow
+INCLUDE_FLAGS=-I$(SSL_INCLUDEDIR)
+CFLAGS=$(DEBUG_FLAGS) $(INCLUDE_FLAGS) -DNO_CONFIG_H
+COMPILE=$(CC) $(CFLAGS) -c
+
+# Edit, particularly the "-ldl" if not building with "dlfcn" support
+LINK_FLAGS=-L$(SSL_LIBDIR) -lssl -lcrypto -ldl
+
+SRCS=buffer.c cb.c ip.c sm.c tunala.c breakage.c
+OBJS=buffer.o cb.o ip.o sm.o tunala.o breakage.o
+
+TARGETS=tunala
+
+default: $(TARGETS)
+
+clean:
+ $(RM) $(OBJS) $(TARGETS) *.bak core
+
+.c.o:
+ $(COMPILE) $<
+
+tunala: $(OBJS)
+ $(CC) -o tunala $(OBJS) $(LINK_FLAGS)
+
+# Extra dependencies, should really use makedepend
+buffer.o: buffer.c tunala.h
+cb.o: cb.c tunala.h
+ip.o: ip.c tunala.h
+sm.o: sm.c tunala.h
+tunala.o: tunala.c tunala.h
diff --git a/crypto/openssl/demos/tunala/Makefile.am b/crypto/openssl/demos/tunala/Makefile.am
new file mode 100644
index 0000000..706c780
--- /dev/null
+++ b/crypto/openssl/demos/tunala/Makefile.am
@@ -0,0 +1,7 @@
+# Our includes come from the OpenSSL build-tree we're in
+INCLUDES = -I$(top_builddir)/../../include
+
+bin_PROGRAMS = tunala
+
+tunala_SOURCES = tunala.c buffer.c cb.c ip.c sm.c breakage.c
+tunala_LDADD = -L$(top_builddir)/../.. -lssl -lcrypto
diff --git a/crypto/openssl/demos/tunala/README b/crypto/openssl/demos/tunala/README
new file mode 100644
index 0000000..1569008
--- /dev/null
+++ b/crypto/openssl/demos/tunala/README
@@ -0,0 +1,233 @@
+This is intended to be an example of a state-machine driven SSL application. It
+acts as an SSL tunneler (functioning as either the server or client half,
+depending on command-line arguments). *PLEASE* read the comments in tunala.h
+before you treat this stuff as anything more than a curiosity - YOU HAVE BEEN
+WARNED!! There, that's the draconian bit out of the way ...
+
+
+Why "tunala"??
+--------------
+
+I thought I asked you to read tunala.h?? :-)
+
+
+Show me
+-------
+
+If you want to simply see it running, skip to the end and see some example
+command-line arguments to demonstrate with.
+
+
+Where to look and what to do?
+-----------------------------
+
+The code is split up roughly coinciding with the detaching of an "abstract" SSL
+state machine (which is the purpose of all this) and its surrounding application
+specifics. This is primarily to make it possible for me to know when I could cut
+corners and when I needed to be rigorous (or at least maintain the pretense as
+such :-).
+
+Network stuff:
+
+Basically, the network part of all this is what is supposed to be abstracted out
+of the way. The intention is to illustrate one way to stick OpenSSL's mechanisms
+inside a little memory-driven sandbox and operate it like a pure state-machine.
+So, the network code is inside both ip.c (general utility functions and gory
+IPv4 details) and tunala.c itself, which takes care of application specifics
+like the main select() loop. The connectivity between the specifics of this
+application (TCP/IP tunneling and the associated network code) and the
+underlying abstract SSL state machine stuff is through the use of the "buffer_t"
+type, declared in tunala.h and implemented in buffer.c.
+
+State machine:
+
+Which leaves us, generally speaking, with the abstract "state machine" code left
+over and this is sitting inside sm.c, with declarations inside tunala.h. As can
+be seen by the definition of the state_machine_t structure and the associated
+functions to manipulate it, there are the 3 OpenSSL "handles" plus 4 buffer_t
+structures dealing with IO on both the encrypted and unencrypted sides ("dirty"
+and "clean" respectively). The "SSL" handle is what facilitates the reading and
+writing of the unencrypted (tunneled) data. The two "BIO" handles act as the
+read and write channels for encrypted tunnel traffic - in other applications
+these are often socket BIOs so that the OpenSSL framework operates with the
+network layer directly. In this example, those two BIOs are memory BIOs
+(BIO_s_mem()) so that the sending and receiving of the tunnel traffic stays
+within the state-machine, and we can handle where this gets send to (or read
+from) ourselves.
+
+
+Why?
+----
+
+If you take a look at the "state_machine_t" section of tunala.h and the code in
+sm.c, you will notice that nothing related to the concept of 'transport' is
+involved. The binding to TCP/IP networking occurs in tunala.c, specifically
+within the "tunala_item_t" structure that associates a state_machine_t object
+with 4 file-descriptors. The way to best see where the bridge between the
+outside world (TCP/IP reads, writes, select()s, file-descriptors, etc) and the
+state machine is, is to examine the "tunala_item_io()" function in tunala.c.
+This is currently around lines 641-732 but of course could be subject to change.
+
+
+And...?
+-------
+
+Well, although that function is around 90 lines of code, it could easily have
+been a lot less only I was trying to address an easily missed "gotcha" (item (2)
+below). The main() code that drives the select/accept/IO loop initialises new
+tunala_item_t structures when connections arrive, and works out which
+file-descriptors go where depending on whether we're an SSL client or server
+(client --> accepted connection is clean and proxied is dirty, server -->
+accepted connection is dirty and proxied is clean). What that tunala_item_io()
+function is attempting to do is 2 things;
+
+ (1) Perform all reads and writes on the network directly into the
+ state_machine_t's buffers (based on a previous select() result), and only
+ then allow the abstact state_machine_t to "churn()" using those buffers.
+ This will cause the SSL machine to consume as much input data from the two
+ "IN" buffers as possible, and generate as much output data into the two
+ "OUT" buffers as possible. Back up in the main() function, the next main
+ loop loop will examine these output buffers and select() for writability
+ on the corresponding sockets if the buffers are non-empty.
+
+ (2) Handle the complicated tunneling-specific issue of cascading "close"s.
+ This is the reason for most of the complexity in the logic - if one side
+ of the tunnel is closed, you can't simply close the other side and throw
+ away the whole thing - (a) there may still be outgoing data on the other
+ side of the tunnel that hasn't been sent yet, (b) the close (or things
+ happening during the close) may cause more data to be generated that needs
+ sending on the other side. Of course, this logic is complicated yet futher
+ by the fact that it's different depending on which side closes first :-)
+ state_machine_close_clean() will indicate to the state machine that the
+ unencrypted side of the tunnel has closed, so any existing outgoing data
+ needs to be flushed, and the SSL stream needs to be closed down using the
+ appropriate shutdown sequence. state_machine_close_dirty() is simpler
+ because it indicates that the SSL stream has been disconnected, so all
+ that remains before closing the other side is to flush out anything that
+ remains and wait for it to all be sent.
+
+Anyway, with those things in mind, the code should be a little easier to follow
+in terms of "what is *this* bit supposed to achieve??!!".
+
+
+How might this help?
+--------------------
+
+Well, the reason I wrote this is that there seemed to be rather a flood of
+questions of late on the openssl-dev and openssl-users lists about getting this
+whole IO logic thing sorted out, particularly by those who were trying to either
+use non-blocking IO, or wanted SSL in an environment where "something else" was
+handling the network already and they needed to operate in memory only. This
+code is loosely based on some other stuff I've been working on, although that
+stuff is far more complete, far more dependant on a whole slew of other
+network/framework code I don't want to incorporate here, and far harder to look
+at for 5 minutes and follow where everything is going. I will be trying over
+time to suck in a few things from that into this demo in the hopes it might be
+more useful, and maybe to even make this demo usable as a utility of its own.
+Possible things include:
+
+ * controlling multiple processes/threads - this can be used to combat
+ latencies and get passed file-descriptor limits on some systems, and it uses
+ a "controller" process/thread that maintains IPC links with the
+ processes/threads doing the real work.
+
+ * cert verification rules - having some say over which certs get in or out :-)
+
+ * control over SSL protocols and cipher suites
+
+ * A few other things you can already do in s_client and s_server :-)
+
+ * Support (and control over) session resuming, particularly when functioning
+ as an SSL client.
+
+If you have a particular environment where this model might work to let you "do
+SSL" without having OpenSSL be aware of the transport, then you should find you
+could use the state_machine_t structure (or your own variant thereof) and hook
+it up to your transport stuff in much the way tunala.c matches it up with those
+4 file-descriptors. The state_machine_churn(), state_machine_close_clean(), and
+state_machine_close_dirty() functions are the main things to understand - after
+that's done, you just have to ensure you're feeding and bleeding the 4
+state_machine buffers in a logical fashion. This state_machine loop handles not
+only handshakes and normal streaming, but also renegotiates - there's no special
+handling required beyond keeping an eye on those 4 buffers and keeping them in
+sync with your outer "loop" logic. Ie. if one of the OUT buffers is not empty,
+you need to find an opportunity to try and forward its data on. If one of the IN
+buffers is not full, you should keep an eye out for data arriving that should be
+placed there.
+
+This approach could hopefully also allow you to run the SSL protocol in very
+different environments. As an example, you could support encrypted event-driven
+IPC where threads/processes pass messages to each other inside an SSL layer;
+each IPC-message's payload would be in fact the "dirty" content, and the "clean"
+payload coming out of the tunnel at each end would be the real intended message.
+Likewise, this could *easily* be made to work across unix domain sockets, or
+even entirely different network/comms protocols.
+
+This is also a quick and easy way to do VPN if you (and the remote network's
+gateway) support virtual network devices that are encapsulted in a single
+network connection, perhaps PPP going through an SSL tunnel?
+
+
+Suggestions
+-----------
+
+Please let me know if you find this useful, or if there's anything wrong or
+simply too confusing about it. Patches are also welcome, but please attach a
+description of what it changes and why, and "diff -urN" format is preferred.
+Mail to geoff@openssl.org should do the trick.
+
+
+Example
+-------
+
+Here is an example of how to use "tunala" ...
+
+First, it's assumed that OpenSSL has already built, and that you are building
+inside the ./demos/tunala/ directory. If not - please correct the paths and
+flags inside the Makefile. Likewise, if you want to tweak the building, it's
+best to try and do so in the makefile (eg. removing the debug flags and adding
+optimisation flags).
+
+Secondly, this code has mostly only been tested on Linux. However, some
+autoconf/etc support has been added and the code has been compiled on openbsd
+and solaris using that.
+
+Thirdly, if you are Win32, you probably need to do some *major* rewriting of
+ip.c to stand a hope in hell. Good luck, and please mail me the diff if you do
+this, otherwise I will take a look at another time. It can certainly be done,
+but it's very non-POSIXy.
+
+See the INSTALL document for details on building.
+
+Now, if you don't have an executable "tunala" compiled, go back to "First,...".
+Rinse and repeat.
+
+Inside one console, try typing;
+
+(i) ./tunala -listen localhost:8080 -proxy localhost:8081 -cacert CA.pem \
+ -cert A-client.pem -out_totals -v_peer -v_strict
+
+In another console, type;
+
+(ii) ./tunala -listen localhost:8081 -proxy localhost:23 -cacert CA.pem \
+ -cert A-server.pem -server 1 -out_totals -v_peer -v_strict
+
+Now if you open another console and "telnet localhost 8080", you should be
+tunneled through to the telnet service on your local machine (if it's running -
+you could change it to port "22" and tunnel ssh instead if you so desired). When
+you logout of the telnet session, the tunnel should cleanly shutdown and show
+you some traffic stats in both consoles. Feel free to experiment. :-)
+
+Notes:
+
+ - the format for the "-listen" argument can skip the host part (eg. "-listen
+ 8080" is fine). If you do, the listening socket will listen on all interfaces
+ so you can connect from other machines for example. Using the "localhost"
+ form listens only on 127.0.0.1 so you can only connect locally (unless, of
+ course, you've set up weird stuff with your networking in which case probably
+ none of the above applies).
+
+ - ./tunala -? gives you a list of other command-line options, but tunala.c is
+ also a good place to look :-)
+
+
diff --git a/crypto/openssl/demos/tunala/autogunk.sh b/crypto/openssl/demos/tunala/autogunk.sh
new file mode 100755
index 0000000..c9783c6
--- /dev/null
+++ b/crypto/openssl/demos/tunala/autogunk.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# This script tries to follow the "GNU way" w.r.t. the autobits.
+# This does of course generate a number of irritating files.
+# Try to get over it (I am getting there myself).
+
+# This should generate any missing crud, and then run autoconf which should turn
+# configure.in into a "./configure" script and "Makefile.am" into a
+# "Makefile.in". Then running "./configure" should turn "Makefile.in" into
+# "Makefile" and should generate the config.h containing your systems various
+# settings. I know ... what a hassle ...
+
+# Also, sometimes these autobits things generate bizarre output (looking like
+# errors). So I direct everything "elsewhere" ...
+
+(aclocal
+autoheader
+libtoolize --copy --force
+automake --foreign --add-missing --copy
+autoconf) 1> /dev/null 2>&1
+
+# Move the "no-autotools" Makefile out of the way
+if test ! -f Makefile.plain; then
+ mv Makefile Makefile.plain
+fi
diff --git a/crypto/openssl/demos/tunala/autoungunk.sh b/crypto/openssl/demos/tunala/autoungunk.sh
new file mode 100755
index 0000000..14d1079
--- /dev/null
+++ b/crypto/openssl/demos/tunala/autoungunk.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# This script tries to clean up as much as is possible from whatever diabolical
+# mess has been left in the directory thanks to autoconf, automake, and their
+# friends.
+
+if test -f Makefile; then
+ make distclean
+ rm -f Makefile
+fi
+
+if test -f Makefile.plain; then
+ mv Makefile.plain Makefile
+fi
+
+rm -f aclocal.m4 config.* configure install-sh \
+ missing mkinstalldirs stamp-h.* Makefile.in \
+ ltconfig ltmain.sh
diff --git a/crypto/openssl/demos/tunala/breakage.c b/crypto/openssl/demos/tunala/breakage.c
new file mode 100644
index 0000000..dcdd64b
--- /dev/null
+++ b/crypto/openssl/demos/tunala/breakage.c
@@ -0,0 +1,66 @@
+#include "tunala.h"
+
+int int_strtoul(const char *str, unsigned long *val)
+{
+#ifdef HAVE_STRTOUL
+ char *tmp;
+ unsigned long ret = strtoul(str, &tmp, 10);
+ if((str == tmp) || (*tmp != '\0'))
+ /* The value didn't parse cleanly */
+ return 0;
+ if(ret == ULONG_MAX)
+ /* We hit a limit */
+ return 0;
+ *val = ret;
+ return 1;
+#else
+ char buf[2];
+ unsigned long ret = 0;
+ buf[1] = '\0';
+ if(str == '\0')
+ /* An empty string ... */
+ return 0;
+ while(*str != '\0') {
+ /* We have to multiply 'ret' by 10 before absorbing the next
+ * digit. If this will overflow, catch it now. */
+ if(ret && (((ULONG_MAX + 10) / ret) < 10))
+ return 0;
+ ret *= 10;
+ if(!isdigit(*str))
+ return 0;
+ buf[0] = *str;
+ ret += atoi(buf);
+ str++;
+ }
+ *val = ret;
+ return 1;
+#endif
+}
+
+#ifndef HAVE_STRSTR
+char *int_strstr(const char *haystack, const char *needle)
+{
+ const char *sub_haystack = haystack, *sub_needle = needle;
+ unsigned int offset = 0;
+ if(!needle)
+ return haystack;
+ if(!haystack)
+ return NULL;
+ while((*sub_haystack != '\0') && (*sub_needle != '\0')) {
+ if(sub_haystack[offset] == sub_needle) {
+ /* sub_haystack is still a candidate */
+ offset++;
+ sub_needle++;
+ } else {
+ /* sub_haystack is no longer a possibility */
+ sub_haystack++;
+ offset = 0;
+ sub_needle = needle;
+ }
+ }
+ if(*sub_haystack == '\0')
+ /* Found nothing */
+ return NULL;
+ return sub_haystack;
+}
+#endif
diff --git a/crypto/openssl/demos/tunala/buffer.c b/crypto/openssl/demos/tunala/buffer.c
new file mode 100644
index 0000000..c5cd004
--- /dev/null
+++ b/crypto/openssl/demos/tunala/buffer.c
@@ -0,0 +1,205 @@
+#include "tunala.h"
+
+#ifndef NO_BUFFER
+
+void buffer_init(buffer_t *buf)
+{
+ buf->used = 0;
+ buf->total_in = buf->total_out = 0;
+}
+
+void buffer_close(buffer_t *buf)
+{
+ /* Our data is static - nothing needs "release", just reset it */
+ buf->used = 0;
+}
+
+/* Code these simple ones in compact form */
+unsigned int buffer_used(buffer_t *buf) {
+ return buf->used; }
+unsigned int buffer_unused(buffer_t *buf) {
+ return (MAX_DATA_SIZE - buf->used); }
+int buffer_full(buffer_t *buf) {
+ return (buf->used == MAX_DATA_SIZE ? 1 : 0); }
+int buffer_notfull(buffer_t *buf) {
+ return (buf->used < MAX_DATA_SIZE ? 1 : 0); }
+int buffer_empty(buffer_t *buf) {
+ return (buf->used == 0 ? 1 : 0); }
+int buffer_notempty(buffer_t *buf) {
+ return (buf->used > 0 ? 1 : 0); }
+unsigned long buffer_total_in(buffer_t *buf) {
+ return buf->total_in; }
+unsigned long buffer_total_out(buffer_t *buf) {
+ return buf->total_out; }
+
+/* These 3 static (internal) functions don't adjust the "total" variables as
+ * it's not sure when they're called how it should be interpreted. Only the
+ * higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these
+ * values. */
+#if 0 /* To avoid "unused" warnings */
+static unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
+ unsigned int size)
+{
+ unsigned int added = MAX_DATA_SIZE - buf->used;
+ if(added > size)
+ added = size;
+ if(added == 0)
+ return 0;
+ memcpy(buf->data + buf->used, ptr, added);
+ buf->used += added;
+ buf->total_in += added;
+ return added;
+}
+
+static unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap)
+{
+ unsigned int moved, tomove = from->used;
+ if((int)tomove > cap)
+ tomove = cap;
+ if(tomove == 0)
+ return 0;
+ moved = buffer_adddata(to, from->data, tomove);
+ if(moved == 0)
+ return 0;
+ buffer_takedata(from, NULL, moved);
+ return moved;
+}
+#endif
+
+static unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
+ unsigned int size)
+{
+ unsigned int taken = buf->used;
+ if(taken > size)
+ taken = size;
+ if(taken == 0)
+ return 0;
+ if(ptr)
+ memcpy(ptr, buf->data, taken);
+ buf->used -= taken;
+ /* Do we have to scroll? */
+ if(buf->used > 0)
+ memmove(buf->data, buf->data + taken, buf->used);
+ return taken;
+}
+
+#ifndef NO_IP
+
+int buffer_from_fd(buffer_t *buf, int fd)
+{
+ int toread = buffer_unused(buf);
+ if(toread == 0)
+ /* Shouldn't be called in this case! */
+ abort();
+ toread = read(fd, buf->data + buf->used, toread);
+ if(toread > 0) {
+ buf->used += toread;
+ buf->total_in += toread;
+ }
+ return toread;
+}
+
+int buffer_to_fd(buffer_t *buf, int fd)
+{
+ int towrite = buffer_used(buf);
+ if(towrite == 0)
+ /* Shouldn't be called in this case! */
+ abort();
+ towrite = write(fd, buf->data, towrite);
+ if(towrite > 0) {
+ buffer_takedata(buf, NULL, towrite);
+ buf->total_out += towrite;
+ }
+ return towrite;
+}
+
+#endif /* !defined(NO_IP) */
+
+#ifndef NO_OPENSSL
+
+static void int_ssl_check(SSL *s, int ret)
+{
+ int e = SSL_get_error(s, ret);
+ switch(e) {
+ /* These seem to be harmless and already "dealt with" by our
+ * non-blocking environment. NB: "ZERO_RETURN" is the clean
+ * "error" indicating a successfully closed SSL tunnel. We let
+ * this happen because our IO loop should not appear to have
+ * broken on this condition - and outside the IO loop, the
+ * "shutdown" state is checked. */
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ case SSL_ERROR_ZERO_RETURN:
+ return;
+ /* These seem to be indications of a genuine error that should
+ * result in the SSL tunnel being regarded as "dead". */
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ SSL_set_app_data(s, (char *)1);
+ return;
+ default:
+ break;
+ }
+ /* For any other errors that (a) exist, and (b) crop up - we need to
+ * interpret what to do with them - so "politely inform" the caller that
+ * the code needs updating here. */
+ abort();
+}
+
+void buffer_from_SSL(buffer_t *buf, SSL *ssl)
+{
+ int ret;
+ if(!ssl || buffer_full(buf))
+ return;
+ ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
+ if(ret > 0) {
+ buf->used += ret;
+ buf->total_in += ret;
+ }
+ if(ret < 0)
+ int_ssl_check(ssl, ret);
+}
+
+void buffer_to_SSL(buffer_t *buf, SSL *ssl)
+{
+ int ret;
+ if(!ssl || buffer_empty(buf))
+ return;
+ ret = SSL_write(ssl, buf->data, buf->used);
+ if(ret > 0) {
+ buffer_takedata(buf, NULL, ret);
+ buf->total_out += ret;
+ }
+ if(ret < 0)
+ int_ssl_check(ssl, ret);
+}
+
+void buffer_from_BIO(buffer_t *buf, BIO *bio)
+{
+ int ret;
+ if(!bio || buffer_full(buf))
+ return;
+ ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
+ if(ret > 0) {
+ buf->used += ret;
+ buf->total_in += ret;
+ }
+}
+
+void buffer_to_BIO(buffer_t *buf, BIO *bio)
+{
+ int ret;
+ if(!bio || buffer_empty(buf))
+ return;
+ ret = BIO_write(bio, buf->data, buf->used);
+ if(ret > 0) {
+ buffer_takedata(buf, NULL, ret);
+ buf->total_out += ret;
+ }
+}
+
+#endif /* !defined(NO_OPENSSL) */
+
+#endif /* !defined(NO_BUFFER) */
diff --git a/crypto/openssl/demos/tunala/cb.c b/crypto/openssl/demos/tunala/cb.c
new file mode 100644
index 0000000..cd32f74
--- /dev/null
+++ b/crypto/openssl/demos/tunala/cb.c
@@ -0,0 +1,133 @@
+#include "tunala.h"
+
+#ifndef NO_OPENSSL
+
+/* For callbacks generating output, here are their file-descriptors. */
+static FILE *fp_cb_ssl_info = NULL;
+static FILE *fp_cb_ssl_verify = NULL;
+/* Output level:
+ * 0 = nothing,
+ * 1 = minimal, just errors,
+ * 2 = minimal, all steps,
+ * 3 = detail, all steps */
+static unsigned int cb_ssl_verify_level = 1;
+
+/* Other static rubbish (to mirror s_cb.c where required) */
+static int int_verify_depth = 10;
+
+/* This function is largely borrowed from the one used in OpenSSL's "s_client"
+ * and "s_server" utilities. */
+void cb_ssl_info(const SSL *s, int where, int ret)
+{
+ const char *str1, *str2;
+ int w;
+
+ if(!fp_cb_ssl_info)
+ return;
+
+ w = where & ~SSL_ST_MASK;
+ str1 = (w & SSL_ST_CONNECT ? "SSL_connect" : (w & SSL_ST_ACCEPT ?
+ "SSL_accept" : "undefined")),
+ str2 = SSL_state_string_long(s);
+
+ if (where & SSL_CB_LOOP)
+ fprintf(fp_cb_ssl_info, "(%s) %s\n", str1, str2);
+ else if (where & SSL_CB_EXIT) {
+ if (ret == 0)
+ fprintf(fp_cb_ssl_info, "(%s) failed in %s\n", str1, str2);
+/* In a non-blocking model, we get a few of these "error"s simply because we're
+ * calling "reads" and "writes" on the state-machine that are virtual NOPs
+ * simply to avoid wasting the time seeing if we *should* call them. Removing
+ * this case makes the "-out_state" output a lot easier on the eye. */
+#if 0
+ else if (ret < 0)
+ fprintf(fp_cb_ssl_info, "%s:error in %s\n", str1, str2);
+#endif
+ }
+}
+
+void cb_ssl_info_set_output(FILE *fp)
+{
+ fp_cb_ssl_info = fp;
+}
+
+static const char *int_reason_no_issuer = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT";
+static const char *int_reason_not_yet = "X509_V_ERR_CERT_NOT_YET_VALID";
+static const char *int_reason_before = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD";
+static const char *int_reason_expired = "X509_V_ERR_CERT_HAS_EXPIRED";
+static const char *int_reason_after = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD";
+
+/* Stolen wholesale from apps/s_cb.c :-) And since then, mutilated ... */
+int cb_ssl_verify(int ok, X509_STORE_CTX *ctx)
+{
+ char buf1[256]; /* Used for the subject name */
+ char buf2[256]; /* Used for the issuer name */
+ const char *reason = NULL; /* Error reason (if any) */
+ X509 *err_cert;
+ int err, depth;
+
+ if(!fp_cb_ssl_verify || (cb_ssl_verify_level == 0))
+ return ok;
+ err_cert = X509_STORE_CTX_get_current_cert(ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+ depth = X509_STORE_CTX_get_error_depth(ctx);
+
+ buf1[0] = buf2[0] = '\0';
+ /* Fill buf1 */
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf1, 256);
+ /* Fill buf2 */
+ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf2, 256);
+ switch (ctx->error) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ reason = int_reason_no_issuer;
+ break;
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ reason = int_reason_not_yet;
+ break;
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ reason = int_reason_before;
+ break;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ reason = int_reason_expired;
+ break;
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ reason = int_reason_after;
+ break;
+ }
+
+ if((cb_ssl_verify_level == 1) && ok)
+ return ok;
+ fprintf(fp_cb_ssl_verify, "chain-depth=%d, ", depth);
+ if(reason)
+ fprintf(fp_cb_ssl_verify, "error=%s\n", reason);
+ else
+ fprintf(fp_cb_ssl_verify, "error=%d\n", err);
+ if(cb_ssl_verify_level < 3)
+ return ok;
+ fprintf(fp_cb_ssl_verify, "--> subject = %s\n", buf1);
+ fprintf(fp_cb_ssl_verify, "--> issuer = %s\n", buf2);
+ if(!ok)
+ fprintf(fp_cb_ssl_verify,"--> verify error:num=%d:%s\n",err,
+ X509_verify_cert_error_string(err));
+ fprintf(fp_cb_ssl_verify, "--> verify return:%d\n",ok);
+ return ok;
+}
+
+void cb_ssl_verify_set_output(FILE *fp)
+{
+ fp_cb_ssl_verify = fp;
+}
+
+void cb_ssl_verify_set_depth(unsigned int verify_depth)
+{
+ int_verify_depth = verify_depth;
+}
+
+void cb_ssl_verify_set_level(unsigned int level)
+{
+ if(level < 4)
+ cb_ssl_verify_level = level;
+}
+
+#endif /* !defined(NO_OPENSSL) */
+
diff --git a/crypto/openssl/demos/tunala/configure.in b/crypto/openssl/demos/tunala/configure.in
new file mode 100644
index 0000000..b2a6ffc
--- /dev/null
+++ b/crypto/openssl/demos/tunala/configure.in
@@ -0,0 +1,28 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(tunala.c)
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(tunala, 0.0.1-dev)
+
+dnl Checks for programs. (Though skip libtool)
+AC_PROG_CC
+dnl AC_PROG_LIBTOOL
+dnl AM_PROG_LIBTOOL
+
+dnl Checks for libraries.
+AC_CHECK_LIB(dl, dlopen)
+AC_CHECK_LIB(socket, socket)
+AC_CHECK_LIB(nsl, gethostbyname)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h unistd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(strstr strtoul)
+AC_CHECK_FUNCS(select socket)
+AC_CHECK_FUNCS(dlopen)
+
+AC_OUTPUT(Makefile)
diff --git a/crypto/openssl/demos/tunala/ip.c b/crypto/openssl/demos/tunala/ip.c
new file mode 100644
index 0000000..96ef4e6
--- /dev/null
+++ b/crypto/openssl/demos/tunala/ip.c
@@ -0,0 +1,146 @@
+#include "tunala.h"
+
+#ifndef NO_IP
+
+#define IP_LISTENER_BACKLOG 511 /* So if it gets masked by 256 or some other
+ such value it'll still be respectable */
+
+/* Any IP-related initialisations. For now, this means blocking SIGPIPE */
+int ip_initialise(void)
+{
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ if(sigaction(SIGPIPE, &sa, NULL) != 0)
+ return 0;
+ return 1;
+}
+
+int ip_create_listener_split(const char *ip, unsigned short port)
+{
+ struct sockaddr_in in_addr;
+ int fd = -1;
+ int reuseVal = 1;
+
+ /* Create the socket */
+ if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
+ goto err;
+ /* Set the SO_REUSEADDR flag - servers act weird without it */
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)(&reuseVal),
+ sizeof(reuseVal)) != 0)
+ goto err;
+ /* Prepare the listen address stuff */
+ in_addr.sin_family = AF_INET;
+ memcpy(&in_addr.sin_addr.s_addr, ip, 4);
+ in_addr.sin_port = htons(port);
+ /* Bind to the required port/address/interface */
+ if(bind(fd, (struct sockaddr *)&in_addr, sizeof(struct sockaddr_in)) != 0)
+ goto err;
+ /* Start "listening" */
+ if(listen(fd, IP_LISTENER_BACKLOG) != 0)
+ goto err;
+ return fd;
+err:
+ if(fd != -1)
+ close(fd);
+ return -1;
+}
+
+int ip_create_connection_split(const char *ip, unsigned short port)
+{
+ struct sockaddr_in in_addr;
+ int flags, fd = -1;
+
+ /* Create the socket */
+ if((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
+ goto err;
+ /* Make it non-blocking */
+ if(((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
+ (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0))
+ goto err;
+ /* Prepare the connection address stuff */
+ in_addr.sin_family = AF_INET;
+ memcpy(&in_addr.sin_addr.s_addr, ip, 4);
+ in_addr.sin_port = htons(port);
+ /* Start a connect (non-blocking, in all likelihood) */
+ if((connect(fd, (struct sockaddr *)&in_addr,
+ sizeof(struct sockaddr_in)) != 0) &&
+ (errno != EINPROGRESS))
+ goto err;
+ return fd;
+err:
+ if(fd != -1)
+ close(fd);
+ return -1;
+}
+
+static char all_local_ip[] = {0x00,0x00,0x00,0x00};
+
+int ip_parse_address(const char *address, const char **parsed_ip,
+ unsigned short *parsed_port, int accept_all_ip)
+{
+ char buf[256];
+ struct hostent *lookup;
+ unsigned long port;
+ const char *ptr = strstr(address, ":");
+ const char *ip = all_local_ip;
+
+ if(!ptr) {
+ /* We assume we're listening on all local interfaces and have
+ * only specified a port. */
+ if(!accept_all_ip)
+ return 0;
+ ptr = address;
+ goto determine_port;
+ }
+ if((ptr - address) > 255)
+ return 0;
+ memset(buf, 0, 256);
+ memcpy(buf, address, ptr - address);
+ ptr++;
+ if((lookup = gethostbyname(buf)) == NULL) {
+ /* Spit a message to differentiate between lookup failures and
+ * bad strings. */
+ fprintf(stderr, "hostname lookup for '%s' failed\n", buf);
+ return 0;
+ }
+ ip = lookup->h_addr_list[0];
+determine_port:
+ if(strlen(ptr) < 1)
+ return 0;
+ if(!int_strtoul(ptr, &port) || (port > 65535))
+ return 0;
+ *parsed_ip = ip;
+ *parsed_port = (unsigned short)port;
+ return 1;
+}
+
+int ip_create_listener(const char *address)
+{
+ const char *ip;
+ unsigned short port;
+
+ if(!ip_parse_address(address, &ip, &port, 1))
+ return -1;
+ return ip_create_listener_split(ip, port);
+}
+
+int ip_create_connection(const char *address)
+{
+ const char *ip;
+ unsigned short port;
+
+ if(!ip_parse_address(address, &ip, &port, 0))
+ return -1;
+ return ip_create_connection_split(ip, port);
+}
+
+int ip_accept_connection(int listen_fd)
+{
+ return accept(listen_fd, NULL, NULL);
+}
+
+#endif /* !defined(NO_IP) */
+
diff --git a/crypto/openssl/demos/tunala/sm.c b/crypto/openssl/demos/tunala/sm.c
new file mode 100644
index 0000000..25359e6
--- /dev/null
+++ b/crypto/openssl/demos/tunala/sm.c
@@ -0,0 +1,151 @@
+#include "tunala.h"
+
+#ifndef NO_TUNALA
+
+void state_machine_init(state_machine_t *machine)
+{
+ machine->ssl = NULL;
+ machine->bio_intossl = machine->bio_fromssl = NULL;
+ buffer_init(&machine->clean_in);
+ buffer_init(&machine->clean_out);
+ buffer_init(&machine->dirty_in);
+ buffer_init(&machine->dirty_out);
+}
+
+void state_machine_close(state_machine_t *machine)
+{
+ if(machine->ssl)
+ SSL_free(machine->ssl);
+/* SSL_free seems to decrement the reference counts already so doing this goes
+ * kaboom. */
+#if 0
+ if(machine->bio_intossl)
+ BIO_free(machine->bio_intossl);
+ if(machine->bio_fromssl)
+ BIO_free(machine->bio_fromssl);
+#endif
+ buffer_close(&machine->clean_in);
+ buffer_close(&machine->clean_out);
+ buffer_close(&machine->dirty_in);
+ buffer_close(&machine->dirty_out);
+ state_machine_init(machine);
+}
+
+buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type)
+{
+ switch(type) {
+ case SM_CLEAN_IN:
+ return &machine->clean_in;
+ case SM_CLEAN_OUT:
+ return &machine->clean_out;
+ case SM_DIRTY_IN:
+ return &machine->dirty_in;
+ case SM_DIRTY_OUT:
+ return &machine->dirty_out;
+ default:
+ break;
+ }
+ /* Should never get here */
+ abort();
+ return NULL;
+}
+
+SSL *state_machine_get_SSL(state_machine_t *machine)
+{
+ return machine->ssl;
+}
+
+int state_machine_set_SSL(state_machine_t *machine, SSL *ssl, int is_server)
+{
+ if(machine->ssl)
+ /* Shouldn't ever be set twice */
+ abort();
+ machine->ssl = ssl;
+ /* Create the BIOs to handle the dirty side of the SSL */
+ if((machine->bio_intossl = BIO_new(BIO_s_mem())) == NULL)
+ abort();
+ if((machine->bio_fromssl = BIO_new(BIO_s_mem())) == NULL)
+ abort();
+ /* Hook up the BIOs on the dirty side of the SSL */
+ SSL_set_bio(machine->ssl, machine->bio_intossl, machine->bio_fromssl);
+ if(is_server)
+ SSL_set_accept_state(machine->ssl);
+ else
+ SSL_set_connect_state(machine->ssl);
+ /* If we're the first one to generate traffic - do it now otherwise we
+ * go into the next select empty-handed and our peer will not send data
+ * but will similarly wait for us. */
+ return state_machine_churn(machine);
+}
+
+/* Performs the data-IO loop and returns zero if the machine should close */
+int state_machine_churn(state_machine_t *machine)
+{
+ unsigned int loop;
+ if(machine->ssl == NULL) {
+ if(buffer_empty(&machine->clean_out))
+ /* Time to close this state-machine altogether */
+ return 0;
+ else
+ /* Still buffered data on the clean side to go out */
+ return 1;
+ }
+ /* Do this loop twice to cover any dependencies about which precise
+ * order of reads and writes is required. */
+ for(loop = 0; loop < 2; loop++) {
+ buffer_to_SSL(&machine->clean_in, machine->ssl);
+ buffer_to_BIO(&machine->dirty_in, machine->bio_intossl);
+ buffer_from_SSL(&machine->clean_out, machine->ssl);
+ buffer_from_BIO(&machine->dirty_out, machine->bio_fromssl);
+ }
+ /* We close on the SSL side if the info callback noticed some problems
+ * or an SSL shutdown was underway and shutdown traffic had all been
+ * sent. */
+ if(SSL_get_app_data(machine->ssl) || (SSL_get_shutdown(machine->ssl) &&
+ buffer_empty(&machine->dirty_out))) {
+ /* Great, we can seal off the dirty side completely */
+ if(!state_machine_close_dirty(machine))
+ return 0;
+ }
+ /* Either the SSL is alive and well, or the closing process still has
+ * outgoing data waiting to be sent */
+ return 1;
+}
+
+/* Called when the clean side of the SSL has lost its connection */
+int state_machine_close_clean(state_machine_t *machine)
+{
+ /* Well, first thing to do is null out the clean-side buffers - they're
+ * no use any more. */
+ buffer_close(&machine->clean_in);
+ buffer_close(&machine->clean_out);
+ /* And start an SSL shutdown */
+ if(machine->ssl)
+ SSL_shutdown(machine->ssl);
+ /* This is an "event", so flush the SSL of any generated traffic */
+ state_machine_churn(machine);
+ if(buffer_empty(&machine->dirty_in) &&
+ buffer_empty(&machine->dirty_out))
+ return 0;
+ return 1;
+}
+
+/* Called when the dirty side of the SSL has lost its connection. This is pretty
+ * terminal as all that can be left to do is send any buffered output on the
+ * clean side - after that, we're done. */
+int state_machine_close_dirty(state_machine_t *machine)
+{
+ buffer_close(&machine->dirty_in);
+ buffer_close(&machine->dirty_out);
+ buffer_close(&machine->clean_in);
+ if(machine->ssl)
+ SSL_free(machine->ssl);
+ machine->ssl = NULL;
+ machine->bio_intossl = machine->bio_fromssl = NULL;
+ if(buffer_empty(&machine->clean_out))
+ return 0;
+ return 1;
+}
+
+#endif /* !defined(NO_TUNALA) */
+
diff --git a/crypto/openssl/demos/tunala/tunala.c b/crypto/openssl/demos/tunala/tunala.c
new file mode 100644
index 0000000..e802a62
--- /dev/null
+++ b/crypto/openssl/demos/tunala/tunala.c
@@ -0,0 +1,1093 @@
+#if defined(NO_BUFFER) || defined(NO_IP) || defined(NO_OPENSSL)
+#error "Badness, NO_BUFFER, NO_IP or NO_OPENSSL is defined, turn them *off*"
+#endif
+
+/* Include our bits'n'pieces */
+#include "tunala.h"
+
+
+/********************************************/
+/* Our local types that specify our "world" */
+/********************************************/
+
+/* These represent running "tunnels". Eg. if you wanted to do SSL in a
+ * "message-passing" scanario, the "int" file-descriptors might be replaced by
+ * thread or process IDs, and the "select" code might be replaced by message
+ * handling code. Whatever. */
+typedef struct _tunala_item_t {
+ /* The underlying SSL state machine. This is a data-only processing unit
+ * and we communicate with it by talking to its four "buffers". */
+ state_machine_t sm;
+ /* The file-descriptors for the "dirty" (encrypted) side of the SSL
+ * setup. In actuality, this is typically a socket and both values are
+ * identical. */
+ int dirty_read, dirty_send;
+ /* The file-descriptors for the "clean" (unencrypted) side of the SSL
+ * setup. These could be stdin/stdout, a socket (both values the same),
+ * or whatever you like. */
+ int clean_read, clean_send;
+} tunala_item_t;
+
+/* This structure is used as the data for running the main loop. Namely, in a
+ * network format such as this, it is stuff for select() - but as pointed out,
+ * when moving the real-world to somewhere else, this might be replaced by
+ * something entirely different. It's basically the stuff that controls when
+ * it's time to do some "work". */
+typedef struct _select_sets_t {
+ int max; /* As required as the first argument to select() */
+ fd_set reads, sends, excepts; /* As passed to select() */
+} select_sets_t;
+typedef struct _tunala_selector_t {
+ select_sets_t last_selected; /* Results of the last select() */
+ select_sets_t next_select; /* What we'll next select on */
+} tunala_selector_t;
+
+/* This structure is *everything*. We do it to avoid the use of globals so that,
+ * for example, it would be easier to shift things around between async-IO,
+ * thread-based, or multi-fork()ed (or combinations thereof). */
+typedef struct _tunala_world_t {
+ /* The file-descriptor we "listen" on for new connections */
+ int listen_fd;
+ /* The array of tunnels */
+ tunala_item_t *tunnels;
+ /* the number of tunnels in use and allocated, respectively */
+ unsigned int tunnels_used, tunnels_size;
+ /* Our outside "loop" context stuff */
+ tunala_selector_t selector;
+ /* Our SSL_CTX, which is configured as the SSL client or server and has
+ * the various cert-settings and callbacks configured. */
+ SSL_CTX *ssl_ctx;
+ /* Simple flag with complex logic :-) Indicates whether we're an SSL
+ * server or an SSL client. */
+ int server_mode;
+} tunala_world_t;
+
+/*****************************/
+/* Internal static functions */
+/*****************************/
+
+static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
+ const char *CAfile, const char *cert, const char *key,
+ const char *dcert, const char *dkey, const char *cipher_list,
+ const char *dh_file, const char *dh_special, int ctx_options,
+ int out_state, int out_verify, int verify_mode,
+ unsigned int verify_depth);
+static void selector_init(tunala_selector_t *selector);
+static void selector_add_listener(tunala_selector_t *selector, int fd);
+static void selector_add_tunala(tunala_selector_t *selector, tunala_item_t *t);
+static int selector_select(tunala_selector_t *selector);
+/* This returns -1 for error, 0 for no new connections, or 1 for success, in
+ * which case *newfd is populated. */
+static int selector_get_listener(tunala_selector_t *selector, int fd, int *newfd);
+static int tunala_world_new_item(tunala_world_t *world, int fd,
+ const char *ip, unsigned short port, int flipped);
+static void tunala_world_del_item(tunala_world_t *world, unsigned int idx);
+static int tunala_item_io(tunala_selector_t *selector, tunala_item_t *item);
+
+/*********************************************/
+/* MAIN FUNCTION (and its utility functions) */
+/*********************************************/
+
+static const char *def_proxyhost = "127.0.0.1:443";
+static const char *def_listenhost = "127.0.0.1:8080";
+static int def_max_tunnels = 50;
+static const char *def_cacert = NULL;
+static const char *def_cert = NULL;
+static const char *def_key = NULL;
+static const char *def_dcert = NULL;
+static const char *def_dkey = NULL;
+static const char *def_engine_id = NULL;
+static int def_server_mode = 0;
+static int def_flipped = 0;
+static const char *def_cipher_list = NULL;
+static const char *def_dh_file = NULL;
+static const char *def_dh_special = NULL;
+static int def_ctx_options = 0;
+static int def_verify_mode = 0;
+static unsigned int def_verify_depth = 10;
+static int def_out_state = 0;
+static unsigned int def_out_verify = 0;
+static int def_out_totals = 0;
+static int def_out_conns = 0;
+
+static const char *helpstring =
+"\n'Tunala' (A tunneler with a New Zealand accent)\n"
+"Usage: tunala [options], where options are from;\n"
+" -listen [host:]<port> (default = 127.0.0.1:8080)\n"
+" -proxy <host>:<port> (default = 127.0.0.1:443)\n"
+" -maxtunnels <num> (default = 50)\n"
+" -cacert <path|NULL> (default = NULL)\n"
+" -cert <path|NULL> (default = NULL)\n"
+" -key <path|NULL> (default = whatever '-cert' is)\n"
+" -dcert <path|NULL> (usually for DSA, default = NULL)\n"
+" -dkey <path|NULL> (usually for DSA, default = whatever '-dcert' is)\n"
+" -engine <id|NULL> (default = NULL)\n"
+" -server <0|1> (default = 0, ie. an SSL client)\n"
+" -flipped <0|1> (makes SSL servers be network clients, and vice versa)\n"
+" -cipher <list> (specifies cipher list to use)\n"
+" -dh_file <path> (a PEM file containing DH parameters to use)\n"
+" -dh_special <NULL|generate|standard> (see below: def=NULL)\n"
+" -no_ssl2 (disable SSLv2)\n"
+" -no_ssl3 (disable SSLv3)\n"
+" -no_tls1 (disable TLSv1)\n"
+" -v_peer (verify the peer certificate)\n"
+" -v_strict (do not continue if peer doesn't authenticate)\n"
+" -v_once (no verification in renegotiates)\n"
+" -v_depth <num> (limit certificate chain depth, default = 10)\n"
+" -out_conns (prints client connections and disconnections)\n"
+" -out_state (prints SSL handshake states)\n"
+" -out_verify <0|1|2|3> (prints certificate verification states: def=1)\n"
+" -out_totals (prints out byte-totals when a tunnel closes)\n"
+" -<h|help|?> (displays this help screen)\n"
+"Notes:\n"
+"(1) It is recommended to specify a cert+key when operating as an SSL server.\n"
+" If you only specify '-cert', the same file must contain a matching\n"
+" private key.\n"
+"(2) Either dh_file or dh_special can be used to specify where DH parameters\n"
+" will be obtained from (or '-dh_special NULL' for the default choice) but\n"
+" you cannot specify both. For dh_special, 'generate' will create new DH\n"
+" parameters on startup, and 'standard' will use embedded parameters\n"
+" instead.\n"
+"(3) Normally an ssl client connects to an ssl server - so that an 'ssl client\n"
+" tunala' listens for 'clean' client connections and proxies ssl, and an\n"
+" 'ssl server tunala' listens for ssl connections and proxies 'clean'. With\n"
+" '-flipped 1', this behaviour is reversed so that an 'ssl server tunala'\n"
+" listens for clean client connections and proxies ssl (but participating\n"
+" as an ssl *server* in the SSL/TLS protocol), and an 'ssl client tunala'\n"
+" listens for ssl connections (participating as an ssl *client* in the\n"
+" SSL/TLS protocol) and proxies 'clean' to the end destination. This can\n"
+" be useful for allowing network access to 'servers' where only the server\n"
+" needs to authenticate the client (ie. the other way is not required).\n"
+" Even with client and server authentication, this 'technique' mitigates\n"
+" some DoS (denial-of-service) potential as it will be the network client\n"
+" having to perform the first private key operation rather than the other\n"
+" way round.\n"
+"(4) The 'technique' used by setting '-flipped 1' is probably compatible with\n"
+" absolutely nothing except another complimentary instance of 'tunala'\n"
+" running with '-flipped 1'. :-)\n";
+
+/* Default DH parameters for use with "-dh_special standard" ... stolen striaght
+ * from s_server. */
+static unsigned char dh512_p[]={
+ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
+ 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
+ 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
+ 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
+ 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
+ 0x47,0x74,0xE8,0x33,
+ };
+static unsigned char dh512_g[]={
+ 0x02,
+ };
+
+/* And the function that parses the above "standard" parameters, again, straight
+ * out of s_server. */
+static DH *get_dh512(void)
+ {
+ DH *dh=NULL;
+
+ if ((dh=DH_new()) == NULL) return(NULL);
+ dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
+ dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
+ if ((dh->p == NULL) || (dh->g == NULL))
+ return(NULL);
+ return(dh);
+ }
+
+/* Various help/error messages used by main() */
+static int usage(const char *errstr, int isunknownarg)
+{
+ if(isunknownarg)
+ fprintf(stderr, "Error: unknown argument '%s'\n", errstr);
+ else
+ fprintf(stderr, "Error: %s\n", errstr);
+ fprintf(stderr, "%s\n", helpstring);
+ return 1;
+}
+
+static int err_str0(const char *str0)
+{
+ fprintf(stderr, "%s\n", str0);
+ return 1;
+}
+
+static int err_str1(const char *fmt, const char *str1)
+{
+ fprintf(stderr, fmt, str1);
+ fprintf(stderr, "\n");
+ return 1;
+}
+
+static int parse_max_tunnels(const char *s, unsigned int *maxtunnels)
+{
+ unsigned long l;
+ if(!int_strtoul(s, &l) || (l < 1) || (l > 1024)) {
+ fprintf(stderr, "Error, '%s' is an invalid value for "
+ "maxtunnels\n", s);
+ return 0;
+ }
+ *maxtunnels = (unsigned int)l;
+ return 1;
+}
+
+static int parse_server_mode(const char *s, int *servermode)
+{
+ unsigned long l;
+ if(!int_strtoul(s, &l) || (l > 1)) {
+ fprintf(stderr, "Error, '%s' is an invalid value for the "
+ "server mode\n", s);
+ return 0;
+ }
+ *servermode = (int)l;
+ return 1;
+}
+
+static int parse_dh_special(const char *s, const char **dh_special)
+{
+ if((strcmp(s, "NULL") == 0) || (strcmp(s, "generate") == 0) ||
+ (strcmp(s, "standard") == 0)) {
+ *dh_special = s;
+ return 1;
+ }
+ fprintf(stderr, "Error, '%s' is an invalid value for 'dh_special'\n", s);
+ return 0;
+}
+
+static int parse_verify_level(const char *s, unsigned int *verify_level)
+{
+ unsigned long l;
+ if(!int_strtoul(s, &l) || (l > 3)) {
+ fprintf(stderr, "Error, '%s' is an invalid value for "
+ "out_verify\n", s);
+ return 0;
+ }
+ *verify_level = (unsigned int)l;
+ return 1;
+}
+
+static int parse_verify_depth(const char *s, unsigned int *verify_depth)
+{
+ unsigned long l;
+ if(!int_strtoul(s, &l) || (l < 1) || (l > 50)) {
+ fprintf(stderr, "Error, '%s' is an invalid value for "
+ "verify_depth\n", s);
+ return 0;
+ }
+ *verify_depth = (unsigned int)l;
+ return 1;
+}
+
+/* Some fprintf format strings used when tunnels close */
+static const char *io_stats_dirty =
+" SSL traffic; %8lu bytes in, %8lu bytes out\n";
+static const char *io_stats_clean =
+" clear traffic; %8lu bytes in, %8lu bytes out\n";
+
+int main(int argc, char *argv[])
+{
+ unsigned int loop;
+ int newfd;
+ tunala_world_t world;
+ tunala_item_t *t_item;
+ const char *proxy_ip;
+ unsigned short proxy_port;
+ /* Overridables */
+ const char *proxyhost = def_proxyhost;
+ const char *listenhost = def_listenhost;
+ unsigned int max_tunnels = def_max_tunnels;
+ const char *cacert = def_cacert;
+ const char *cert = def_cert;
+ const char *key = def_key;
+ const char *dcert = def_dcert;
+ const char *dkey = def_dkey;
+ const char *engine_id = def_engine_id;
+ int server_mode = def_server_mode;
+ int flipped = def_flipped;
+ const char *cipher_list = def_cipher_list;
+ const char *dh_file = def_dh_file;
+ const char *dh_special = def_dh_special;
+ int ctx_options = def_ctx_options;
+ int verify_mode = def_verify_mode;
+ unsigned int verify_depth = def_verify_depth;
+ int out_state = def_out_state;
+ unsigned int out_verify = def_out_verify;
+ int out_totals = def_out_totals;
+ int out_conns = def_out_conns;
+
+/* Parse command-line arguments */
+next_arg:
+ argc--; argv++;
+ if(argc > 0) {
+ if(strcmp(*argv, "-listen") == 0) {
+ if(argc < 2)
+ return usage("-listen requires an argument", 0);
+ argc--; argv++;
+ listenhost = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-proxy") == 0) {
+ if(argc < 2)
+ return usage("-proxy requires an argument", 0);
+ argc--; argv++;
+ proxyhost = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-maxtunnels") == 0) {
+ if(argc < 2)
+ return usage("-maxtunnels requires an argument", 0);
+ argc--; argv++;
+ if(!parse_max_tunnels(*argv, &max_tunnels))
+ return 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-cacert") == 0) {
+ if(argc < 2)
+ return usage("-cacert requires an argument", 0);
+ argc--; argv++;
+ if(strcmp(*argv, "NULL") == 0)
+ cacert = NULL;
+ else
+ cacert = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-cert") == 0) {
+ if(argc < 2)
+ return usage("-cert requires an argument", 0);
+ argc--; argv++;
+ if(strcmp(*argv, "NULL") == 0)
+ cert = NULL;
+ else
+ cert = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-key") == 0) {
+ if(argc < 2)
+ return usage("-key requires an argument", 0);
+ argc--; argv++;
+ if(strcmp(*argv, "NULL") == 0)
+ key = NULL;
+ else
+ key = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-dcert") == 0) {
+ if(argc < 2)
+ return usage("-dcert requires an argument", 0);
+ argc--; argv++;
+ if(strcmp(*argv, "NULL") == 0)
+ dcert = NULL;
+ else
+ dcert = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-dkey") == 0) {
+ if(argc < 2)
+ return usage("-dkey requires an argument", 0);
+ argc--; argv++;
+ if(strcmp(*argv, "NULL") == 0)
+ dkey = NULL;
+ else
+ dkey = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-engine") == 0) {
+ if(argc < 2)
+ return usage("-engine requires an argument", 0);
+ argc--; argv++;
+ engine_id = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-server") == 0) {
+ if(argc < 2)
+ return usage("-server requires an argument", 0);
+ argc--; argv++;
+ if(!parse_server_mode(*argv, &server_mode))
+ return 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-flipped") == 0) {
+ if(argc < 2)
+ return usage("-flipped requires an argument", 0);
+ argc--; argv++;
+ if(!parse_server_mode(*argv, &flipped))
+ return 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-cipher") == 0) {
+ if(argc < 2)
+ return usage("-cipher requires an argument", 0);
+ argc--; argv++;
+ cipher_list = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-dh_file") == 0) {
+ if(argc < 2)
+ return usage("-dh_file requires an argument", 0);
+ if(dh_special)
+ return usage("cannot mix -dh_file with "
+ "-dh_special", 0);
+ argc--; argv++;
+ dh_file = *argv;
+ goto next_arg;
+ } else if(strcmp(*argv, "-dh_special") == 0) {
+ if(argc < 2)
+ return usage("-dh_special requires an argument", 0);
+ if(dh_file)
+ return usage("cannot mix -dh_file with "
+ "-dh_special", 0);
+ argc--; argv++;
+ if(!parse_dh_special(*argv, &dh_special))
+ return 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-no_ssl2") == 0) {
+ ctx_options |= SSL_OP_NO_SSLv2;
+ goto next_arg;
+ } else if(strcmp(*argv, "-no_ssl3") == 0) {
+ ctx_options |= SSL_OP_NO_SSLv3;
+ goto next_arg;
+ } else if(strcmp(*argv, "-no_tls1") == 0) {
+ ctx_options |= SSL_OP_NO_TLSv1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-v_peer") == 0) {
+ verify_mode |= SSL_VERIFY_PEER;
+ goto next_arg;
+ } else if(strcmp(*argv, "-v_strict") == 0) {
+ verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ goto next_arg;
+ } else if(strcmp(*argv, "-v_once") == 0) {
+ verify_mode |= SSL_VERIFY_CLIENT_ONCE;
+ goto next_arg;
+ } else if(strcmp(*argv, "-v_depth") == 0) {
+ if(argc < 2)
+ return usage("-v_depth requires an argument", 0);
+ argc--; argv++;
+ if(!parse_verify_depth(*argv, &verify_depth))
+ return 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-out_state") == 0) {
+ out_state = 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-out_verify") == 0) {
+ if(argc < 2)
+ return usage("-out_verify requires an argument", 0);
+ argc--; argv++;
+ if(!parse_verify_level(*argv, &out_verify))
+ return 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-out_totals") == 0) {
+ out_totals = 1;
+ goto next_arg;
+ } else if(strcmp(*argv, "-out_conns") == 0) {
+ out_conns = 1;
+ goto next_arg;
+ } else if((strcmp(*argv, "-h") == 0) ||
+ (strcmp(*argv, "-help") == 0) ||
+ (strcmp(*argv, "-?") == 0)) {
+ fprintf(stderr, "%s\n", helpstring);
+ return 0;
+ } else
+ return usage(*argv, 1);
+ }
+ /* Run any sanity checks we want here */
+ if(!cert && !dcert && server_mode)
+ fprintf(stderr, "WARNING: you are running an SSL server without "
+ "a certificate - this may not work!\n");
+
+ /* Initialise network stuff */
+ if(!ip_initialise())
+ return err_str0("ip_initialise failed");
+ /* Create the SSL_CTX */
+ if((world.ssl_ctx = initialise_ssl_ctx(server_mode, engine_id,
+ cacert, cert, key, dcert, dkey, cipher_list, dh_file,
+ dh_special, ctx_options, out_state, out_verify,
+ verify_mode, verify_depth)) == NULL)
+ return err_str1("initialise_ssl_ctx(engine_id=%s) failed",
+ (engine_id == NULL) ? "NULL" : engine_id);
+ if(engine_id)
+ fprintf(stderr, "Info, engine '%s' initialised\n", engine_id);
+ /* Create the listener */
+ if((world.listen_fd = ip_create_listener(listenhost)) == -1)
+ return err_str1("ip_create_listener(%s) failed", listenhost);
+ fprintf(stderr, "Info, listening on '%s'\n", listenhost);
+ if(!ip_parse_address(proxyhost, &proxy_ip, &proxy_port, 0))
+ return err_str1("ip_parse_address(%s) failed", proxyhost);
+ fprintf(stderr, "Info, proxying to '%s' (%d.%d.%d.%d:%d)\n", proxyhost,
+ (int)proxy_ip[0], (int)proxy_ip[1],
+ (int)proxy_ip[2], (int)proxy_ip[3], (int)proxy_port);
+ fprintf(stderr, "Info, set maxtunnels to %d\n", (int)max_tunnels);
+ fprintf(stderr, "Info, set to operate as an SSL %s\n",
+ (server_mode ? "server" : "client"));
+ /* Initialise the rest of the stuff */
+ world.tunnels_used = world.tunnels_size = 0;
+ world.tunnels = NULL;
+ world.server_mode = server_mode;
+ selector_init(&world.selector);
+
+/* We're ready to loop */
+main_loop:
+ /* Should we listen for *new* tunnels? */
+ if(world.tunnels_used < max_tunnels)
+ selector_add_listener(&world.selector, world.listen_fd);
+ /* We should add in our existing tunnels */
+ for(loop = 0; loop < world.tunnels_used; loop++)
+ selector_add_tunala(&world.selector, world.tunnels + loop);
+ /* Now do the select */
+ switch(selector_select(&world.selector)) {
+ case -1:
+ fprintf(stderr, "selector_select returned a badness error.\n");
+ goto shouldnt_happen;
+ case 0:
+ fprintf(stderr, "Warn, selector_select returned 0 - signal?""?\n");
+ goto main_loop;
+ default:
+ break;
+ }
+ /* Accept new connection if we should and can */
+ if((world.tunnels_used < max_tunnels) && (selector_get_listener(
+ &world.selector, world.listen_fd,
+ &newfd) == 1)) {
+ /* We have a new connection */
+ if(!tunala_world_new_item(&world, newfd, proxy_ip,
+ proxy_port, flipped))
+ fprintf(stderr, "tunala_world_new_item failed\n");
+ else if(out_conns)
+ fprintf(stderr, "Info, new tunnel opened, now up to "
+ "%d\n", world.tunnels_used);
+ }
+ /* Give each tunnel its moment, note the while loop is because it makes
+ * the logic easier than with "for" to deal with an array that may shift
+ * because of deletes. */
+ loop = 0;
+ t_item = world.tunnels;
+ while(loop < world.tunnels_used) {
+ if(!tunala_item_io(&world.selector, t_item)) {
+ /* We're closing whether for reasons of an error or a
+ * natural close. Don't increment loop or t_item because
+ * the next item is moving to us! */
+ if(!out_totals)
+ goto skip_totals;
+ fprintf(stderr, "Tunnel closing, traffic stats follow\n");
+ /* Display the encrypted (over the network) stats */
+ fprintf(stderr, io_stats_dirty,
+ buffer_total_in(state_machine_get_buffer(
+ &t_item->sm,SM_DIRTY_IN)),
+ buffer_total_out(state_machine_get_buffer(
+ &t_item->sm,SM_DIRTY_OUT)));
+ /* Display the local (tunnelled) stats. NB: Data we
+ * *receive* is data sent *out* of the state_machine on
+ * its 'clean' side. Hence the apparent back-to-front
+ * OUT/IN mixup here :-) */
+ fprintf(stderr, io_stats_clean,
+ buffer_total_out(state_machine_get_buffer(
+ &t_item->sm,SM_CLEAN_OUT)),
+ buffer_total_in(state_machine_get_buffer(
+ &t_item->sm,SM_CLEAN_IN)));
+skip_totals:
+ tunala_world_del_item(&world, loop);
+ if(out_conns)
+ fprintf(stderr, "Info, tunnel closed, down to %d\n",
+ world.tunnels_used);
+ }
+ else {
+ /* Move to the next item */
+ loop++;
+ t_item++;
+ }
+ }
+ goto main_loop;
+ /* Should never get here */
+shouldnt_happen:
+ abort();
+ return 1;
+}
+
+/****************/
+/* OpenSSL bits */
+/****************/
+
+static int ctx_set_cert(SSL_CTX *ctx, const char *cert, const char *key)
+{
+ FILE *fp = NULL;
+ X509 *x509 = NULL;
+ EVP_PKEY *pkey = NULL;
+ int toret = 0; /* Assume an error */
+
+ /* cert */
+ if(cert) {
+ if((fp = fopen(cert, "r")) == NULL) {
+ fprintf(stderr, "Error opening cert file '%s'\n", cert);
+ goto err;
+ }
+ if(!PEM_read_X509(fp, &x509, NULL, NULL)) {
+ fprintf(stderr, "Error reading PEM cert from '%s'\n",
+ cert);
+ goto err;
+ }
+ if(!SSL_CTX_use_certificate(ctx, x509)) {
+ fprintf(stderr, "Error, cert in '%s' can not be used\n",
+ cert);
+ goto err;
+ }
+ /* Clear the FILE* for reuse in the "key" code */
+ fclose(fp);
+ fp = NULL;
+ fprintf(stderr, "Info, operating with cert in '%s'\n", cert);
+ /* If a cert was given without matching key, we assume the same
+ * file contains the required key. */
+ if(!key)
+ key = cert;
+ } else {
+ if(key)
+ fprintf(stderr, "Error, can't specify a key without a "
+ "corresponding certificate\n");
+ else
+ fprintf(stderr, "Error, ctx_set_cert called with "
+ "NULLs!\n");
+ goto err;
+ }
+ /* key */
+ if(key) {
+ if((fp = fopen(key, "r")) == NULL) {
+ fprintf(stderr, "Error opening key file '%s'\n", key);
+ goto err;
+ }
+ if(!PEM_read_PrivateKey(fp, &pkey, NULL, NULL)) {
+ fprintf(stderr, "Error reading PEM key from '%s'\n",
+ key);
+ goto err;
+ }
+ if(!SSL_CTX_use_PrivateKey(ctx, pkey)) {
+ fprintf(stderr, "Error, key in '%s' can not be used\n",
+ key);
+ goto err;
+ }
+ fprintf(stderr, "Info, operating with key in '%s'\n", key);
+ } else
+ fprintf(stderr, "Info, operating without a cert or key\n");
+ /* Success */
+ toret = 1; err:
+ if(x509)
+ X509_free(x509);
+ if(pkey)
+ EVP_PKEY_free(pkey);
+ if(fp)
+ fclose(fp);
+ return toret;
+}
+
+static int ctx_set_dh(SSL_CTX *ctx, const char *dh_file, const char *dh_special)
+{
+ DH *dh = NULL;
+ FILE *fp = NULL;
+
+ if(dh_special) {
+ if(strcmp(dh_special, "NULL") == 0)
+ return 1;
+ if(strcmp(dh_special, "standard") == 0) {
+ if((dh = get_dh512()) == NULL) {
+ fprintf(stderr, "Error, can't parse 'standard'"
+ " DH parameters\n");
+ return 0;
+ }
+ fprintf(stderr, "Info, using 'standard' DH parameters\n");
+ goto do_it;
+ }
+ if(strcmp(dh_special, "generate") != 0)
+ /* This shouldn't happen - screening values is handled
+ * in main(). */
+ abort();
+ fprintf(stderr, "Info, generating DH parameters ... ");
+ fflush(stderr);
+ if((dh = DH_generate_parameters(512, DH_GENERATOR_5,
+ NULL, NULL)) == NULL) {
+ fprintf(stderr, "error!\n");
+ return 0;
+ }
+ fprintf(stderr, "complete\n");
+ goto do_it;
+ }
+ /* So, we're loading dh_file */
+ if((fp = fopen(dh_file, "r")) == NULL) {
+ fprintf(stderr, "Error, couldn't open '%s' for DH parameters\n",
+ dh_file);
+ return 0;
+ }
+ dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
+ fclose(fp);
+ if(dh == NULL) {
+ fprintf(stderr, "Error, could not parse DH parameters from '%s'\n",
+ dh_file);
+ return 0;
+ }
+ fprintf(stderr, "Info, using DH parameters from file '%s'\n", dh_file);
+do_it:
+ SSL_CTX_set_tmp_dh(ctx, dh);
+ DH_free(dh);
+ return 1;
+}
+
+static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
+ const char *CAfile, const char *cert, const char *key,
+ const char *dcert, const char *dkey, const char *cipher_list,
+ const char *dh_file, const char *dh_special, int ctx_options,
+ int out_state, int out_verify, int verify_mode,
+ unsigned int verify_depth)
+{
+ SSL_CTX *ctx = NULL, *ret = NULL;
+ SSL_METHOD *meth;
+ ENGINE *e = NULL;
+
+ OpenSSL_add_ssl_algorithms();
+ SSL_load_error_strings();
+
+ meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method());
+ if(meth == NULL)
+ goto err;
+ if(engine_id) {
+ ENGINE_load_builtin_engines();
+ if((e = ENGINE_by_id(engine_id)) == NULL) {
+ fprintf(stderr, "Error obtaining '%s' engine, openssl "
+ "errors follow\n", engine_id);
+ goto err;
+ }
+ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+ fprintf(stderr, "Error assigning '%s' engine, openssl "
+ "errors follow\n", engine_id);
+ goto err;
+ }
+ ENGINE_free(e);
+ }
+ if((ctx = SSL_CTX_new(meth)) == NULL)
+ goto err;
+ /* cacert */
+ if(CAfile) {
+ if(!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx),
+ CAfile, NULL)) {
+ fprintf(stderr, "Error loading CA cert(s) in '%s'\n",
+ CAfile);
+ goto err;
+ }
+ fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n",
+ CAfile);
+ } else
+ fprintf(stderr, "Info, operating without a CA cert(-list)\n");
+ if(!SSL_CTX_set_default_verify_paths(ctx)) {
+ fprintf(stderr, "Error setting default verify paths\n");
+ goto err;
+ }
+
+ /* cert and key */
+ if((cert || key) && !ctx_set_cert(ctx, cert, key))
+ goto err;
+ /* dcert and dkey */
+ if((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey))
+ goto err;
+
+ /* cipher_list */
+ if(cipher_list) {
+ if(!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
+ fprintf(stderr, "Error setting cipher list '%s'\n",
+ cipher_list);
+ goto err;
+ }
+ fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list);
+ } else
+ fprintf(stderr, "Info, operating with default cipher list\n");
+
+ /* dh_file & dh_special */
+ if((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special))
+ goto err;
+
+ /* ctx_options */
+ SSL_CTX_set_options(ctx, ctx_options);
+
+ /* out_state (output of SSL handshake states to screen). */
+ if(out_state)
+ cb_ssl_info_set_output(stderr);
+
+ /* out_verify */
+ if(out_verify > 0) {
+ cb_ssl_verify_set_output(stderr);
+ cb_ssl_verify_set_level(out_verify);
+ }
+
+ /* verify_depth */
+ cb_ssl_verify_set_depth(verify_depth);
+
+ /* Success! (includes setting verify_mode) */
+ SSL_CTX_set_info_callback(ctx, cb_ssl_info);
+ SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify);
+ ret = ctx;
+err:
+ if(!ret) {
+ ERR_print_errors_fp(stderr);
+ if(ctx)
+ SSL_CTX_free(ctx);
+ }
+ return ret;
+}
+
+/*****************/
+/* Selector bits */
+/*****************/
+
+static void selector_sets_init(select_sets_t *s)
+{
+ s->max = 0;
+ FD_ZERO(&s->reads);
+ FD_ZERO(&s->sends);
+ FD_ZERO(&s->excepts);
+}
+static void selector_init(tunala_selector_t *selector)
+{
+ selector_sets_init(&selector->last_selected);
+ selector_sets_init(&selector->next_select);
+}
+
+#define SEL_EXCEPTS 0x00
+#define SEL_READS 0x01
+#define SEL_SENDS 0x02
+static void selector_add_raw_fd(tunala_selector_t *s, int fd, int flags)
+{
+ FD_SET(fd, &s->next_select.excepts);
+ if(flags & SEL_READS)
+ FD_SET(fd, &s->next_select.reads);
+ if(flags & SEL_SENDS)
+ FD_SET(fd, &s->next_select.sends);
+ /* Adjust "max" */
+ if(s->next_select.max < (fd + 1))
+ s->next_select.max = fd + 1;
+}
+
+static void selector_add_listener(tunala_selector_t *selector, int fd)
+{
+ selector_add_raw_fd(selector, fd, SEL_READS);
+}
+
+static void selector_add_tunala(tunala_selector_t *s, tunala_item_t *t)
+{
+ /* Set clean read if sm.clean_in is not full */
+ if(t->clean_read != -1) {
+ selector_add_raw_fd(s, t->clean_read,
+ (buffer_full(state_machine_get_buffer(&t->sm,
+ SM_CLEAN_IN)) ? SEL_EXCEPTS : SEL_READS));
+ }
+ /* Set clean send if sm.clean_out is not empty */
+ if(t->clean_send != -1) {
+ selector_add_raw_fd(s, t->clean_send,
+ (buffer_empty(state_machine_get_buffer(&t->sm,
+ SM_CLEAN_OUT)) ? SEL_EXCEPTS : SEL_SENDS));
+ }
+ /* Set dirty read if sm.dirty_in is not full */
+ if(t->dirty_read != -1) {
+ selector_add_raw_fd(s, t->dirty_read,
+ (buffer_full(state_machine_get_buffer(&t->sm,
+ SM_DIRTY_IN)) ? SEL_EXCEPTS : SEL_READS));
+ }
+ /* Set dirty send if sm.dirty_out is not empty */
+ if(t->dirty_send != -1) {
+ selector_add_raw_fd(s, t->dirty_send,
+ (buffer_empty(state_machine_get_buffer(&t->sm,
+ SM_DIRTY_OUT)) ? SEL_EXCEPTS : SEL_SENDS));
+ }
+}
+
+static int selector_select(tunala_selector_t *selector)
+{
+ memcpy(&selector->last_selected, &selector->next_select,
+ sizeof(select_sets_t));
+ selector_sets_init(&selector->next_select);
+ return select(selector->last_selected.max,
+ &selector->last_selected.reads,
+ &selector->last_selected.sends,
+ &selector->last_selected.excepts, NULL);
+}
+
+/* This returns -1 for error, 0 for no new connections, or 1 for success, in
+ * which case *newfd is populated. */
+static int selector_get_listener(tunala_selector_t *selector, int fd, int *newfd)
+{
+ if(FD_ISSET(fd, &selector->last_selected.excepts))
+ return -1;
+ if(!FD_ISSET(fd, &selector->last_selected.reads))
+ return 0;
+ if((*newfd = ip_accept_connection(fd)) == -1)
+ return -1;
+ return 1;
+}
+
+/************************/
+/* "Tunala" world stuff */
+/************************/
+
+static int tunala_world_make_room(tunala_world_t *world)
+{
+ unsigned int newsize;
+ tunala_item_t *newarray;
+
+ if(world->tunnels_used < world->tunnels_size)
+ return 1;
+ newsize = (world->tunnels_size == 0 ? 16 :
+ ((world->tunnels_size * 3) / 2));
+ if((newarray = malloc(newsize * sizeof(tunala_item_t))) == NULL)
+ return 0;
+ memset(newarray, 0, newsize * sizeof(tunala_item_t));
+ if(world->tunnels_used > 0)
+ memcpy(newarray, world->tunnels,
+ world->tunnels_used * sizeof(tunala_item_t));
+ if(world->tunnels_size > 0)
+ free(world->tunnels);
+ /* migrate */
+ world->tunnels = newarray;
+ world->tunnels_size = newsize;
+ return 1;
+}
+
+static int tunala_world_new_item(tunala_world_t *world, int fd,
+ const char *ip, unsigned short port, int flipped)
+{
+ tunala_item_t *item;
+ int newfd;
+ SSL *new_ssl = NULL;
+
+ if(!tunala_world_make_room(world))
+ return 0;
+ if((new_ssl = SSL_new(world->ssl_ctx)) == NULL) {
+ fprintf(stderr, "Error creating new SSL\n");
+ ERR_print_errors_fp(stderr);
+ return 0;
+ }
+ item = world->tunnels + (world->tunnels_used++);
+ state_machine_init(&item->sm);
+ item->clean_read = item->clean_send =
+ item->dirty_read = item->dirty_send = -1;
+ if((newfd = ip_create_connection_split(ip, port)) == -1)
+ goto err;
+ /* Which way round? If we're a server, "fd" is the dirty side and the
+ * connection we open is the clean one. For a client, it's the other way
+ * around. Unless, of course, we're "flipped" in which case everything
+ * gets reversed. :-) */
+ if((world->server_mode && !flipped) ||
+ (!world->server_mode && flipped)) {
+ item->dirty_read = item->dirty_send = fd;
+ item->clean_read = item->clean_send = newfd;
+ } else {
+ item->clean_read = item->clean_send = fd;
+ item->dirty_read = item->dirty_send = newfd;
+ }
+ /* We use the SSL's "app_data" to indicate a call-back induced "kill" */
+ SSL_set_app_data(new_ssl, NULL);
+ if(!state_machine_set_SSL(&item->sm, new_ssl, world->server_mode))
+ goto err;
+ return 1;
+err:
+ tunala_world_del_item(world, world->tunnels_used - 1);
+ return 0;
+
+}
+
+static void tunala_world_del_item(tunala_world_t *world, unsigned int idx)
+{
+ tunala_item_t *item = world->tunnels + idx;
+ if(item->clean_read != -1)
+ close(item->clean_read);
+ if(item->clean_send != item->clean_read)
+ close(item->clean_send);
+ item->clean_read = item->clean_send = -1;
+ if(item->dirty_read != -1)
+ close(item->dirty_read);
+ if(item->dirty_send != item->dirty_read)
+ close(item->dirty_send);
+ item->dirty_read = item->dirty_send = -1;
+ state_machine_close(&item->sm);
+ /* OK, now we fix the item array */
+ if(idx + 1 < world->tunnels_used)
+ /* We need to scroll entries to the left */
+ memmove(world->tunnels + idx,
+ world->tunnels + (idx + 1),
+ (world->tunnels_used - (idx + 1)) *
+ sizeof(tunala_item_t));
+ world->tunnels_used--;
+}
+
+static int tunala_item_io(tunala_selector_t *selector, tunala_item_t *item)
+{
+ int c_r, c_s, d_r, d_s; /* Four boolean flags */
+
+ /* Take ourselves out of the gene-pool if there was an except */
+ if((item->clean_read != -1) && FD_ISSET(item->clean_read,
+ &selector->last_selected.excepts))
+ return 0;
+ if((item->clean_send != -1) && FD_ISSET(item->clean_send,
+ &selector->last_selected.excepts))
+ return 0;
+ if((item->dirty_read != -1) && FD_ISSET(item->dirty_read,
+ &selector->last_selected.excepts))
+ return 0;
+ if((item->dirty_send != -1) && FD_ISSET(item->dirty_send,
+ &selector->last_selected.excepts))
+ return 0;
+ /* Grab our 4 IO flags */
+ c_r = c_s = d_r = d_s = 0;
+ if(item->clean_read != -1)
+ c_r = FD_ISSET(item->clean_read, &selector->last_selected.reads);
+ if(item->clean_send != -1)
+ c_s = FD_ISSET(item->clean_send, &selector->last_selected.sends);
+ if(item->dirty_read != -1)
+ d_r = FD_ISSET(item->dirty_read, &selector->last_selected.reads);
+ if(item->dirty_send != -1)
+ d_s = FD_ISSET(item->dirty_send, &selector->last_selected.sends);
+ /* If no IO has happened for us, skip needless data looping */
+ if(!c_r && !c_s && !d_r && !d_s)
+ return 1;
+ if(c_r)
+ c_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
+ SM_CLEAN_IN), item->clean_read) <= 0);
+ if(c_s)
+ c_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
+ SM_CLEAN_OUT), item->clean_send) <= 0);
+ if(d_r)
+ d_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
+ SM_DIRTY_IN), item->dirty_read) <= 0);
+ if(d_s)
+ d_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
+ SM_DIRTY_OUT), item->dirty_send) <= 0);
+ /* If any of the flags is non-zero, that means they need closing */
+ if(c_r) {
+ close(item->clean_read);
+ if(item->clean_send == item->clean_read)
+ item->clean_send = -1;
+ item->clean_read = -1;
+ }
+ if(c_s && (item->clean_send != -1)) {
+ close(item->clean_send);
+ if(item->clean_send == item->clean_read)
+ item->clean_read = -1;
+ item->clean_send = -1;
+ }
+ if(d_r) {
+ close(item->dirty_read);
+ if(item->dirty_send == item->dirty_read)
+ item->dirty_send = -1;
+ item->dirty_read = -1;
+ }
+ if(d_s && (item->dirty_send != -1)) {
+ close(item->dirty_send);
+ if(item->dirty_send == item->dirty_read)
+ item->dirty_read = -1;
+ item->dirty_send = -1;
+ }
+ /* This function name is attributed to the term donated by David
+ * Schwartz on openssl-dev, message-ID:
+ * <NCBBLIEPOCNJOAEKBEAKEEDGLIAA.davids@webmaster.com>. :-) */
+ if(!state_machine_churn(&item->sm))
+ /* If the SSL closes, it will also zero-out the _in buffers
+ * and will in future process just outgoing data. As and
+ * when the outgoing data has gone, it will return zero
+ * here to tell us to bail out. */
+ return 0;
+ /* Otherwise, we return zero if both sides are dead. */
+ if(((item->clean_read == -1) || (item->clean_send == -1)) &&
+ ((item->dirty_read == -1) || (item->dirty_send == -1)))
+ return 0;
+ /* If only one side closed, notify the SSL of this so it can take
+ * appropriate action. */
+ if((item->clean_read == -1) || (item->clean_send == -1)) {
+ if(!state_machine_close_clean(&item->sm))
+ return 0;
+ }
+ if((item->dirty_read == -1) || (item->dirty_send == -1)) {
+ if(!state_machine_close_dirty(&item->sm))
+ return 0;
+ }
+ return 1;
+}
+
diff --git a/crypto/openssl/demos/tunala/tunala.h b/crypto/openssl/demos/tunala/tunala.h
new file mode 100644
index 0000000..b4c8ec7
--- /dev/null
+++ b/crypto/openssl/demos/tunala/tunala.h
@@ -0,0 +1,214 @@
+/* Tunala ("Tunneler with a New Zealand accent")
+ *
+ * Written by Geoff Thorpe, but endorsed/supported by noone. Please use this is
+ * if it's useful or informative to you, but it's only here as a scratchpad for
+ * ideas about how you might (or might not) program with OpenSSL. If you deploy
+ * this is in a mission-critical environment, and have not read, understood,
+ * audited, and modified this code to your satisfaction, and the result is that
+ * all hell breaks loose and you are looking for a new employer, then it proves
+ * nothing except perhaps that Darwinism is alive and well. Let's just say, *I*
+ * don't use this in a mission-critical environment, so it would be stupid for
+ * anyone to assume that it is solid and/or tested enough when even its author
+ * doesn't place that much trust in it. You have been warned.
+ *
+ * With thanks to Cryptographic Appliances, Inc.
+ */
+
+#ifndef _TUNALA_H
+#define _TUNALA_H
+
+/* pull in autoconf fluff */
+#ifndef NO_CONFIG_H
+#include "config.h"
+#else
+/* We don't have autoconf, we have to set all of these unless a tweaked Makefile
+ * tells us not to ... */
+/* headers */
+#ifndef NO_HAVE_SELECT
+#define HAVE_SELECT
+#endif
+#ifndef NO_HAVE_SOCKET
+#define HAVE_SOCKET
+#endif
+#ifndef NO_HAVE_UNISTD_H
+#define HAVE_UNISTD_H
+#endif
+#ifndef NO_HAVE_FCNTL_H
+#define HAVE_FCNTL_H
+#endif
+#ifndef NO_HAVE_LIMITS_H
+#define HAVE_LIMITS_H
+#endif
+/* features */
+#ifndef NO_HAVE_STRSTR
+#define HAVE_STRSTR
+#endif
+#ifndef NO_HAVE_STRTOUL
+#define HAVE_STRTOUL
+#endif
+#endif
+
+#if !defined(HAVE_SELECT) || !defined(HAVE_SOCKET)
+#error "can't build without some network basics like select() and socket()"
+#endif
+
+#include <stdlib.h>
+#ifndef NO_SYSTEM_H
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <netdb.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#endif /* !defined(NO_SYSTEM_H) */
+
+#ifndef NO_OPENSSL
+#include <openssl/err.h>
+#include <openssl/engine.h>
+#include <openssl/ssl.h>
+#endif /* !defined(NO_OPENSSL) */
+
+#ifndef OPENSSL_NO_BUFFER
+/* This is the generic "buffer" type that is used when feeding the
+ * state-machine. It's basically a FIFO with respect to the "adddata" &
+ * "takedata" type functions that operate on it. */
+#define MAX_DATA_SIZE 16384
+typedef struct _buffer_t {
+ unsigned char data[MAX_DATA_SIZE];
+ unsigned int used;
+ /* Statistical values - counts the total number of bytes read in and
+ * read out (respectively) since "buffer_init()" */
+ unsigned long total_in, total_out;
+} buffer_t;
+
+/* Initialise a buffer structure before use */
+void buffer_init(buffer_t *buf);
+/* Cleanup a buffer structure - presently not needed, but if buffer_t is
+ * converted to using dynamic allocation, this would be required - so should be
+ * called to protect against an explosion of memory leaks later if the change is
+ * made. */
+void buffer_close(buffer_t *buf);
+
+/* Basic functions to manipulate buffers */
+
+unsigned int buffer_used(buffer_t *buf); /* How much data in the buffer */
+unsigned int buffer_unused(buffer_t *buf); /* How much space in the buffer */
+int buffer_full(buffer_t *buf); /* Boolean, is it full? */
+int buffer_notfull(buffer_t *buf); /* Boolean, is it not full? */
+int buffer_empty(buffer_t *buf); /* Boolean, is it empty? */
+int buffer_notempty(buffer_t *buf); /* Boolean, is it not empty? */
+unsigned long buffer_total_in(buffer_t *buf); /* Total bytes written to buffer */
+unsigned long buffer_total_out(buffer_t *buf); /* Total bytes read from buffer */
+
+#if 0 /* Currently used only within buffer.c - better to expose only
+ * higher-level functions anyway */
+/* Add data to the tail of the buffer, returns the amount that was actually
+ * added (so, you need to check if return value is less than size) */
+unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
+ unsigned int size);
+
+/* Take data from the front of the buffer (and scroll the rest forward). If
+ * "ptr" is NULL, this just removes data off the front of the buffer. Return
+ * value is the amount actually removed (can be less than size if the buffer has
+ * too little data). */
+unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
+ unsigned int size);
+
+/* Flushes as much data as possible out of the "from" buffer into the "to"
+ * buffer. Return value is the amount moved. The amount moved can be restricted
+ * to a maximum by specifying "cap" - setting it to -1 means no limit. */
+unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap);
+#endif
+
+#ifndef NO_IP
+/* Read or write between a file-descriptor and a buffer */
+int buffer_from_fd(buffer_t *buf, int fd);
+int buffer_to_fd(buffer_t *buf, int fd);
+#endif /* !defined(NO_IP) */
+
+#ifndef NO_OPENSSL
+/* Read or write between an SSL or BIO and a buffer */
+void buffer_from_SSL(buffer_t *buf, SSL *ssl);
+void buffer_to_SSL(buffer_t *buf, SSL *ssl);
+void buffer_from_BIO(buffer_t *buf, BIO *bio);
+void buffer_to_BIO(buffer_t *buf, BIO *bio);
+
+/* Callbacks */
+void cb_ssl_info(const SSL *s, int where, int ret);
+void cb_ssl_info_set_output(FILE *fp); /* Called if output should be sent too */
+int cb_ssl_verify(int ok, X509_STORE_CTX *ctx);
+void cb_ssl_verify_set_output(FILE *fp);
+void cb_ssl_verify_set_depth(unsigned int verify_depth);
+void cb_ssl_verify_set_level(unsigned int level);
+#endif /* !defined(NO_OPENSSL) */
+#endif /* !defined(OPENSSL_NO_BUFFER) */
+
+#ifndef NO_TUNALA
+#ifdef OPENSSL_NO_BUFFER
+#error "TUNALA section of tunala.h requires BUFFER support"
+#endif
+typedef struct _state_machine_t {
+ SSL *ssl;
+ BIO *bio_intossl;
+ BIO *bio_fromssl;
+ buffer_t clean_in, clean_out;
+ buffer_t dirty_in, dirty_out;
+} state_machine_t;
+typedef enum {
+ SM_CLEAN_IN, SM_CLEAN_OUT,
+ SM_DIRTY_IN, SM_DIRTY_OUT
+} sm_buffer_t;
+void state_machine_init(state_machine_t *machine);
+void state_machine_close(state_machine_t *machine);
+buffer_t *state_machine_get_buffer(state_machine_t *machine, sm_buffer_t type);
+SSL *state_machine_get_SSL(state_machine_t *machine);
+int state_machine_set_SSL(state_machine_t *machine, SSL *ssl, int is_server);
+/* Performs the data-IO loop and returns zero if the machine should close */
+int state_machine_churn(state_machine_t *machine);
+/* Is used to handle closing conditions - namely when one side of the tunnel has
+ * closed but the other should finish flushing. */
+int state_machine_close_clean(state_machine_t *machine);
+int state_machine_close_dirty(state_machine_t *machine);
+#endif /* !defined(NO_TUNALA) */
+
+#ifndef NO_IP
+/* Initialise anything related to the networking. This includes blocking pesky
+ * SIGPIPE signals. */
+int ip_initialise(void);
+/* ip is the 4-byte ip address (eg. 127.0.0.1 is {0x7F,0x00,0x00,0x01}), port is
+ * the port to listen on (host byte order), and the return value is the
+ * file-descriptor or -1 on error. */
+int ip_create_listener_split(const char *ip, unsigned short port);
+/* Same semantics as above. */
+int ip_create_connection_split(const char *ip, unsigned short port);
+/* Converts a string into the ip/port before calling the above */
+int ip_create_listener(const char *address);
+int ip_create_connection(const char *address);
+/* Just does a string conversion on its own. NB: If accept_all_ip is non-zero,
+ * then the address string could be just a port. Ie. it's suitable for a
+ * listening address but not a connecting address. */
+int ip_parse_address(const char *address, const char **parsed_ip,
+ unsigned short *port, int accept_all_ip);
+/* Accepts an incoming connection through the listener. Assumes selects and
+ * what-not have deemed it an appropriate thing to do. */
+int ip_accept_connection(int listen_fd);
+#endif /* !defined(NO_IP) */
+
+/* These functions wrap up things that can be portability hassles. */
+int int_strtoul(const char *str, unsigned long *val);
+#ifdef HAVE_STRSTR
+#define int_strstr strstr
+#else
+char *int_strstr(const char *haystack, const char *needle);
+#endif
+
+#endif /* !defined(_TUNALA_H) */
diff --git a/crypto/openssl/demos/x509/README b/crypto/openssl/demos/x509/README
new file mode 100644
index 0000000..88f9d6c
--- /dev/null
+++ b/crypto/openssl/demos/x509/README
@@ -0,0 +1,3 @@
+This directory contains examples of how to contruct
+various X509 structures. Certificates, certificate requests
+and CRLs.
diff --git a/crypto/openssl/demos/x509/mkcert.c b/crypto/openssl/demos/x509/mkcert.c
new file mode 100644
index 0000000..8304d30
--- /dev/null
+++ b/crypto/openssl/demos/x509/mkcert.c
@@ -0,0 +1,168 @@
+/* Certificate creation. Demonstrates some certificate related
+ * operations.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <openssl/pem.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/engine.h>
+
+int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days);
+int add_ext(X509 *cert, int nid, char *value);
+
+int main(int argc, char **argv)
+ {
+ BIO *bio_err;
+ X509 *x509=NULL;
+ EVP_PKEY *pkey=NULL;
+
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ mkcert(&x509,&pkey,512,0,365);
+
+ RSA_print_fp(stdout,pkey->pkey.rsa,0);
+ X509_print_fp(stdout,x509);
+
+ PEM_write_PrivateKey(stdout,pkey,NULL,NULL,0,NULL, NULL);
+ PEM_write_X509(stdout,x509);
+
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+
+ ENGINE_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+
+ CRYPTO_mem_leaks(bio_err);
+ BIO_free(bio_err);
+ return(0);
+ }
+
+static void callback(int p, int n, void *arg)
+ {
+ char c='B';
+
+ if (p == 0) c='.';
+ if (p == 1) c='+';
+ if (p == 2) c='*';
+ if (p == 3) c='\n';
+ fputc(c,stderr);
+ }
+
+int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
+ {
+ X509 *x;
+ EVP_PKEY *pk;
+ RSA *rsa;
+ X509_NAME *name=NULL;
+
+ if ((pkeyp == NULL) || (*pkeyp == NULL))
+ {
+ if ((pk=EVP_PKEY_new()) == NULL)
+ {
+ abort();
+ return(0);
+ }
+ }
+ else
+ pk= *pkeyp;
+
+ if ((x509p == NULL) || (*x509p == NULL))
+ {
+ if ((x=X509_new()) == NULL)
+ goto err;
+ }
+ else
+ x= *x509p;
+
+ rsa=RSA_generate_key(bits,RSA_F4,callback,NULL);
+ if (!EVP_PKEY_assign_RSA(pk,rsa))
+ {
+ abort();
+ goto err;
+ }
+ rsa=NULL;
+
+ X509_set_version(x,2);
+ ASN1_INTEGER_set(X509_get_serialNumber(x),serial);
+ X509_gmtime_adj(X509_get_notBefore(x),0);
+ X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
+ X509_set_pubkey(x,pk);
+
+ name=X509_get_subject_name(x);
+
+ /* This function creates and adds the entry, working out the
+ * correct string type and performing checks on its length.
+ * Normally we'd check the return value for errors...
+ */
+ X509_NAME_add_entry_by_txt(name,"C",
+ MBSTRING_ASC, "UK", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name,"CN",
+ MBSTRING_ASC, "OpenSSL Group", -1, -1, 0);
+
+ /* Its self signed so set the issuer name to be the same as the
+ * subject.
+ */
+ X509_set_issuer_name(x,name);
+
+ /* Add various extensions: standard extensions */
+ add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
+ add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");
+
+ add_ext(x, NID_subject_key_identifier, "hash");
+
+ /* Some Netscape specific extensions */
+ add_ext(x, NID_netscape_cert_type, "sslCA");
+
+ add_ext(x, NID_netscape_comment, "example comment extension");
+
+
+#ifdef CUSTOM_EXT
+ /* Maybe even add our own extension based on existing */
+ {
+ int nid;
+ nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
+ X509V3_EXT_add_alias(nid, NID_netscape_comment);
+ add_ext(x, nid, "example comment alias");
+ }
+#endif
+
+ if (!X509_sign(x,pk,EVP_md5()))
+ goto err;
+
+ *x509p=x;
+ *pkeyp=pk;
+ return(1);
+err:
+ return(0);
+ }
+
+/* Add extension using V3 code: we can set the config file as NULL
+ * because we wont reference any other sections.
+ */
+
+int add_ext(X509 *cert, int nid, char *value)
+ {
+ X509_EXTENSION *ex;
+ X509V3_CTX ctx;
+ /* This sets the 'context' of the extensions. */
+ /* No configuration database */
+ X509V3_set_ctx_nodb(&ctx);
+ /* Issuer and subject certs: both the target since it is self signed,
+ * no request and no CRL
+ */
+ X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
+ ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
+ if (!ex)
+ return 0;
+
+ X509_add_ext(cert,ex,-1);
+ X509_EXTENSION_free(ex);
+ return 1;
+ }
+
diff --git a/crypto/openssl/demos/x509/mkreq.c b/crypto/openssl/demos/x509/mkreq.c
new file mode 100644
index 0000000..d69dcc3
--- /dev/null
+++ b/crypto/openssl/demos/x509/mkreq.c
@@ -0,0 +1,157 @@
+/* Certificate request creation. Demonstrates some request related
+ * operations.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <openssl/pem.h>
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+#include <openssl/engine.h>
+
+int mkreq(X509_REQ **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days);
+int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value);
+
+int main(int argc, char **argv)
+ {
+ BIO *bio_err;
+ X509_REQ *req=NULL;
+ EVP_PKEY *pkey=NULL;
+
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+ bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
+
+ mkreq(&req,&pkey,512,0,365);
+
+ RSA_print_fp(stdout,pkey->pkey.rsa,0);
+ X509_REQ_print_fp(stdout,req);
+
+ PEM_write_X509_REQ(stdout,req);
+
+ X509_REQ_free(req);
+ EVP_PKEY_free(pkey);
+
+ ENGINE_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+
+ CRYPTO_mem_leaks(bio_err);
+ BIO_free(bio_err);
+ return(0);
+ }
+
+static void callback(int p, int n, void *arg)
+ {
+ char c='B';
+
+ if (p == 0) c='.';
+ if (p == 1) c='+';
+ if (p == 2) c='*';
+ if (p == 3) c='\n';
+ fputc(c,stderr);
+ }
+
+int mkreq(X509_REQ **req, EVP_PKEY **pkeyp, int bits, int serial, int days)
+ {
+ X509_REQ *x;
+ EVP_PKEY *pk;
+ RSA *rsa;
+ X509_NAME *name=NULL;
+ STACK_OF(X509_EXTENSION) *exts = NULL;
+
+ if ((pk=EVP_PKEY_new()) == NULL)
+ goto err;
+
+ if ((x=X509_REQ_new()) == NULL)
+ goto err;
+
+ rsa=RSA_generate_key(bits,RSA_F4,callback,NULL);
+ if (!EVP_PKEY_assign_RSA(pk,rsa))
+ goto err;
+
+ rsa=NULL;
+
+ X509_REQ_set_pubkey(x,pk);
+
+ name=X509_REQ_get_subject_name(x);
+
+ /* This function creates and adds the entry, working out the
+ * correct string type and performing checks on its length.
+ * Normally we'd check the return value for errors...
+ */
+ X509_NAME_add_entry_by_txt(name,"C",
+ MBSTRING_ASC, "UK", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name,"CN",
+ MBSTRING_ASC, "OpenSSL Group", -1, -1, 0);
+
+#ifdef REQUEST_EXTENSIONS
+ /* Certificate requests can contain extensions, which can be used
+ * to indicate the extensions the requestor would like added to
+ * their certificate. CAs might ignore them however or even choke
+ * if they are present.
+ */
+
+ /* For request extensions they are all packed in a single attribute.
+ * We save them in a STACK and add them all at once later...
+ */
+
+ exts = sk_X509_EXTENSION_new_null();
+ /* Standard extenions */
+
+ add_ext(exts, NID_key_usage, "critical,digitalSignature,keyEncipherment");
+
+ /* This is a typical use for request extensions: requesting a value for
+ * subject alternative name.
+ */
+
+ add_ext(exts, NID_subject_alt_name, "email:steve@openssl.org");
+
+ /* Some Netscape specific extensions */
+ add_ext(exts, NID_netscape_cert_type, "client,email");
+
+
+
+#ifdef CUSTOM_EXT
+ /* Maybe even add our own extension based on existing */
+ {
+ int nid;
+ nid = OBJ_create("1.2.3.4", "MyAlias", "My Test Alias Extension");
+ X509V3_EXT_add_alias(nid, NID_netscape_comment);
+ add_ext(x, nid, "example comment alias");
+ }
+#endif
+
+ /* Now we've created the extensions we add them to the request */
+
+ X509_REQ_add_extensions(x, exts);
+
+ sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+
+#endif
+
+ if (!X509_REQ_sign(x,pk,EVP_md5()))
+ goto err;
+
+ *req=x;
+ *pkeyp=pk;
+ return(1);
+err:
+ return(0);
+ }
+
+/* Add extension using V3 code: we can set the config file as NULL
+ * because we wont reference any other sections.
+ */
+
+int add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value)
+ {
+ X509_EXTENSION *ex;
+ ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
+ if (!ex)
+ return 0;
+ sk_X509_EXTENSION_push(sk, ex);
+
+ return 1;
+ }
+
OpenPOWER on IntegriCloud