[openssl-dev] [openssl.org #3101] [PATCH] Add CMP (RFC 4210) implementation

Viljanen, Miikka via RT rt at openssl.org
Fri Jul 17 13:59:06 UTC 2015


Hello,

please find attached an updated version of the patch. The following changes have been made:
- patch is now relative to openssl-master branch as of 2015-07-17
- code has been reformatted to fit with the current openssl style
- unnecessary ASN1 function declarations have been cleaned up
- functions and structures that should not be declared publicly have been moved to private header files
- HTTP code now shares as much code as possible with the implementation in OCSP

I'm still importing some patches and updating the code, but I wanted to send the current version in already so that you might be able to review the current state.

best regards,
Miikka



_____________________________________________
From: "Viljanen, Miikka (NSN - FI/Espoo)" <miikka.viljanen at nsn.com>
Sent: Fri, 15 Aug 2014 16:29:05 +0300
To: rt at openssl.org
CC: martin.peylo at nsn.com
Subject: Re: [openssl.org #3101] [PATCH] Add CMP (RFC 4210) implementation

Hi,
attached is the latest version of our CMP code. There haven't been any major changes, just some code cleanup and a few minor new features and bugfixes:

- added support for setting certificate policy OIDs in the request
- added support for RA verified proof of posession
- added support for using a TLS connection
- fixed a number of memory leaks (thanks Valgrind!)
- refactored some small parts of the code and added comments
- some POD documentation updates and clarifications

The EJBCA CMP test server is not up at the moment as it probably hasn't been used much during the last year, but the Insta test server should be up and usable with the instructions from the previous mail.


Something like this, for example (add -proxy 1.2.3.4 and -proxyport 8080 if needed):

wget ftp://ftp.openssl.org/snapshot/openssl-1.0.2-stable-SNAP-20140815.tar.gz 
tar xvfz openssl-1.0.2-stable-SNAP-20140815.tar.gz
cd openssl-1.0.2-stable-SNAP-20140815
patch -p1 < /PATH/cmp.patch 
./config && make depend && make stacks && make
mkdir certs
./apps/openssl genrsa -out certs/cl_key.pem 2048
./apps/openssl cmp -cmd ir -server pki.certificate.fi:8700 -path pkix/ -user 3078 -pass insta -newkey certs/cl_key.pem -certout certs/cl_cert.pem -subject "/CN=CMP Test User" -recipient "/C=FI/O=Insta Demo/CN=Insta Demo CA" -extracertsout certs/cacert.pem
 ./apps/openssl x509 -in certs/cl_cert.pem -text

best regards,
Miikka



Index: openssl-1.0.1h-cmp/crypto/err/err_all.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/err/err_all.c	(revision 750)
+++ openssl-1.0.1h-cmp/crypto/err/err_all.c	(working copy)
@@ -108,6 +108,11 @@
 #include <openssl/jpake.h>
 #endif
 
+#ifndef OPENSSL_NO_CMP
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#endif
+
 void ERR_load_crypto_strings(void)
 	{
 #ifndef OPENSSL_NO_ERR
@@ -164,5 +169,9 @@
 #ifndef OPENSSL_NO_JPAKE
 	ERR_load_JPAKE_strings();
 #endif
+#ifndef OPENSSL_NO_CMP
+	ERR_load_CMP_strings();
+	ERR_load_CRMF_strings();
 #endif
+#endif
 	}
Index: openssl-1.0.1h-cmp/crypto/err/err.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/err/err.c	(revision 750)
+++ openssl-1.0.1h-cmp/crypto/err/err.c	(working copy)
@@ -156,6 +156,8 @@
 {ERR_PACK(ERR_LIB_FIPS,0,0)		,"FIPS routines"},
 {ERR_PACK(ERR_LIB_CMS,0,0)		,"CMS routines"},
 {ERR_PACK(ERR_LIB_HMAC,0,0)		,"HMAC routines"},
+{ERR_PACK(ERR_LIB_CMP,0,0)		,"CMP routines"},
+{ERR_PACK(ERR_LIB_CRMF,0,0)		,"CRMF routines"},
 {0,NULL},
 	};
 
@@ -203,6 +205,8 @@
 {ERR_R_ENGINE_LIB			,"ENGINE lib"},
 {ERR_R_OCSP_LIB				,"OCSP lib"},
 {ERR_R_TS_LIB				,"TS lib"},
+{ERR_R_CMP_LIB				,"CMP lib"},
+{ERR_R_CRMF_LIB				,"CRMF lib"},
 
 {ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
 {ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
Index: openssl-1.0.1h-cmp/crypto/err/openssl.ec
===================================================================
--- openssl-1.0.1h-cmp/crypto/err/openssl.ec	(revision 750)
+++ openssl-1.0.1h-cmp/crypto/err/openssl.ec	(working copy)
@@ -35,6 +35,8 @@
 L HMAC		crypto/hmac/hmac.h		crypto/hmac/hmac_err.c
 L CMS		crypto/cms/cms.h		crypto/cms/cms_err.c
 L JPAKE		crypto/jpake/jpake.h		crypto/jpake/jpake_err.c
+L CMP		crypto/cmp/cmp.h		crypto/cmp/cmp_err.c
+L CRMF		crypto/crmf/crmf.h		crypto/crmf/crmf_err.c
 
 # additional header files to be scanned for function names
 L NONE		crypto/x509/x509_vfy.h		NONE
Index: openssl-1.0.1h-cmp/crypto/err/err.h
===================================================================
--- openssl-1.0.1h-cmp/crypto/err/err.h	(revision 750)
+++ openssl-1.0.1h-cmp/crypto/err/err.h	(working copy)
@@ -198,6 +198,8 @@
 #define ERR_LIB_TS		47
 #define ERR_LIB_HMAC		48
 #define ERR_LIB_JPAKE		49
+#define ERR_LIB_CMP		50
+#define ERR_LIB_CRMF		51
 
 #define ERR_LIB_USER		128
 
@@ -234,6 +236,8 @@
 #define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),__FILE__,__LINE__)
 #define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__)
 #define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__)
+#define CMPerr(f,r) ERR_PUT_error(ERR_LIB_CMP,(f),(r),__FILE__,__LINE__)
+#define CRMFerr(f,r) ERR_PUT_error(ERR_LIB_CRMF,(f),(r),__FILE__,__LINE__)
 
 /* Borland C seems too stupid to be able to shift and do longs in
  * the pre-processor :-( */
@@ -290,6 +294,8 @@
 #define ERR_R_ECDH_LIB  ERR_LIB_ECDH	 /* 43 */
 #define ERR_R_STORE_LIB ERR_LIB_STORE    /* 44 */
 #define ERR_R_TS_LIB	ERR_LIB_TS       /* 45 */
+#define ERR_R_CMP_LIB	ERR_LIB_CMP      /* 50 */
+#define ERR_R_CRMF_LIB	ERR_LIB_CRMF     /* 51 */
 
 #define ERR_R_NESTED_ASN1_ERROR			58
 #define ERR_R_BAD_ASN1_OBJECT_HEADER		59
Index: openssl-1.0.1h-cmp/crypto/cmp/Makefile
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/Makefile	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/Makefile	(revision 765)
@@ -0,0 +1,76 @@
+#
+# OpenSSL/cmp/Makefile
+#
+
+DIR=	cmp
+TOP=	../..
+CC=	cc
+INCLUDES= -I.. -I$(TOP) -I../../include
+CFLAG=
+MAKEFILE=	Makefile
+AR=		ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG) -Wall -DCMP_DEBUG
+
+GENERAL=Makefile README
+TEST=
+APPS=
+
+LIB=$(TOP)/libcrypto.a
+LIBSRC= cmp_asn.c cmp_lib.c cmp_msg.c cmp_vfy.c cmp_ctx.c cmp_err.c cmp_http.c cmp_ses.c
+LIBOBJ= cmp_asn.o cmp_lib.o cmp_msg.o cmp_vfy.o cmp_ctx.o cmp_err.o cmp_http.o cmp_ses.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= cmp.h
+HEADER=	$(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+top:
+	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:	lib 
+
+lib:	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB) || echo Never mind.
+	@touch lib
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+
+links:
+	@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+	@headerlist="$(EXHEADER)"; for i in $$headerlist ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	@[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
+	$(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(LIBSRC)
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp.h
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp.h	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp.h	(revision 764)
@@ -0,0 +1,1363 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* cmp.h
+ * CMP (RFC 4210) header file for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#ifndef HEADER_CMP_H
+#define HEADER_CMP_H
+
+#include <openssl/ossl_typ.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/safestack.h>
+
+#ifdef HAVE_CURL
+#include <curl/curl.h>
+#endif
+
+#include <openssl/crmf.h>
+
+#define CMP_VERSION 2L
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+
+/* ########################################################################## *
+ * ASN.1 DECLARATIONS
+ * ########################################################################## */
+
+/*
+	 RevAnnContent ::= SEQUENCE {
+		 status				 PKIStatus,
+		 certId				 CertId,
+		 willBeRevokedAt	 GeneralizedTime,
+		 badSinceDate		 GeneralizedTime,
+		 crlDetails			 Extensions  OPTIONAL
+		 -- extra CRL details (e.g., crl number, reason, location, etc.)
+	 }
+ */
+typedef struct cmp_revanncontent_st
+	{
+	ASN1_INTEGER			 *status;
+	CRMF_CERTID				 *certId;
+	ASN1_GENERALIZEDTIME	 *willBeRevokedAt;
+	ASN1_GENERALIZEDTIME	 *badSinceDate;
+	X509_EXTENSIONS			 *crlDetails;
+	} CMP_REVANNCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_REVANNCONTENT)
+
+/*
+	 Challenge ::= SEQUENCE {
+		 owf				 AlgorithmIdentifier  OPTIONAL,
+
+		 -- MUST be present in the first Challenge; MAY be omitted in
+		 -- any subsequent Challenge in POPODecKeyChallContent (if
+		 -- omitted, then the owf used in the immediately preceding
+		 -- Challenge is to be used).
+
+		 witness			 OCTET STRING,
+		 -- the result of applying the one-way function (owf) to a
+		 -- randomly-generated INTEGER, A.	[Note that a different
+		 -- INTEGER MUST be used for each Challenge.]
+		 challenge			 OCTET STRING
+		 -- the encryption (under the public key for which the cert.
+		 -- request is being made) of Rand, where Rand is specified as
+		 --   Rand ::= SEQUENCE {
+		 --		 int	  INTEGER,
+		 --		  - the randomly-generated INTEGER A (above)
+		 --		 sender   GeneralName
+		 --		  - the sender's name (as included in PKIHeader)
+		 --   }
+	 }
+ */
+typedef struct cmp_challenge_st
+	{
+	X509_ALGOR		  *owf;
+	ASN1_OCTET_STRING *whitness;
+	ASN1_OCTET_STRING *challenge;
+	} CMP_CHALLENGE;
+DECLARE_ASN1_FUNCTIONS(CMP_CHALLENGE)
+DECLARE_STACK_OF(CMP_CHALLENGE)
+
+#if 0
+/* the RFC explicitly allows substituting CMPCertificate with X509:
+ *
+	  CMPCertificate ::= CHOICE {
+		 x509v3PKCert		 Certificate
+	  }
+   -- This syntax, while bits-on-the-wire compatible with the
+   -- standard X.509 definition of "Certificate", allows the
+   -- possibility of future certificate types (such as X.509
+   -- attribute certificates, WAP WTLS certificates, or other kinds
+   -- of certificates) within this certificate management protocol,
+   -- should a need ever arise to support such generality.  Those
+   -- implementations that do not foresee a need to ever support
+   -- other certificate types MAY, if they wish, comment out the
+   -- above structure and "un-comment" the following one prior to
+   -- compiling this ASN.1 module.  (Note that interoperability
+   -- with implementations that don't do this will be unaffected by
+   -- this change.)
+
+   -- CMPCertificate ::= Certificate
+ */
+#define CMP_CMPCERTIFICATE_X509V3PKCERT   0
+typedef struct cmp_cmpcertificate_st
+	{
+	int type;
+	union
+		{
+		X509 *x509v3PKCert;
+		} value;
+	} CMP_CMPCERTIFICATE;
+DECLARE_ASN1_FUNCTIONS(CMP_CMPCERTIFICATE)
+DECLARE_STACK_OF(CMP_CMPCERTIFICATE)
+#endif 
+
+
+/*
+	 CAKeyUpdAnnContent ::= SEQUENCE {
+		 oldWithNew   CMPCertificate, -- old pub signed with new priv
+		 newWithOld   CMPCertificate, -- new pub signed with old priv
+		 newWithNew   CMPCertificate  -- new pub signed with new priv
+	 }
+ */
+typedef struct cmp_cakeyupdanncontent_st
+	{
+	/* the RFC explicitly allows substituting CMPCertificate with X509 */
+	X509 *oldWithNew;
+	X509 *newWithOld;
+	X509 *newWithNew;
+	} CMP_CAKEYUPDANNCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_CAKEYUPDANNCONTENT)
+
+/* declared already here as it will be used in CMP_PKIMESSAGE (nested) and infotype and * value*/
+typedef STACK_OF(CMP_PKIMESSAGE) CMP_PKIMESSAGES;
+DECLARE_ASN1_FUNCTIONS(CMP_PKIMESSAGES)
+
+/* ESS_SIGNING_CERT comes from ts.h, but ESS_SIGNING_CERT_it isn't declared there */
+DECLARE_ASN1_ITEM(ESS_SIGNING_CERT)
+DECLARE_STACK_OF(ESS_SIGNING_CERT)
+
+/*
+	 InfoTypeAndValue ::= SEQUENCE {
+		 infoType				OBJECT IDENTIFIER,
+		 infoValue				ANY DEFINED BY infoType  OPTIONAL
+	 }
+ */
+typedef struct cmp_infotypeandvalue_st
+	{
+	ASN1_OBJECT *infoType;
+	union
+		{
+		char *ptr;
+		/* NID_id_it_caProtEncCert - CA Protocol Encryption Certificate  */
+		X509 *caProtEncCert;
+		/* NID_id_it_signKeyPairTypes - Signing Key Pair Types	*/
+		STACK_OF(X509_ALGOR) *signKeyPairTypes;
+		/* NID_id_it_encKeyPairTypes - Encryption/Key Agreement Key Pair Types	*/
+		STACK_OF(X509_ALGOR) *encKeyPairTypes;
+		/* NID_id_it_preferredSymmAlg - Preferred Symmetric Algorithm  */
+		X509_ALGOR *preferredSymmAlg;
+		/* NID_id_it_caKeyUpdateInfo - Updated CA Key Pair	*/
+		CMP_CAKEYUPDANNCONTENT *caKeyUpdateInfo;
+		/* NID_id_it_currentCRL - CRL  */
+		X509_CRL *currentCRL;
+		/* NID_id_it_unsupportedOIDs - Unsupported Object Identifiers  */
+		STACK_OF(ASN1_OBJECT) *unsupportedOIDs;
+		/* NID_id_it_keyPairParamReq - Key Pair Parameters Request	*/
+		ASN1_OBJECT *keyPairParamReq;
+		/* NID_id_it_keyPairParamRep - Key Pair Parameters Response  */
+		X509_ALGOR *keyPairParamRep;
+		/* NID_id_it_revPassphrase - Revocation Passphrase	*/
+		CRMF_ENCRYPTEDVALUE *revPassphrase;
+		/* NID_id_it_implicitConfirm - ImplicitConfirm	*/
+		ASN1_NULL *implicitConfirm;
+		/* NID_id_it_confirmWaitTime - ConfirmWaitTime	*/
+		ASN1_GENERALIZEDTIME *confirmWaitTime;
+		/* NID_id_it_origPKIMessage - origPKIMessage  */
+		CMP_PKIMESSAGES *origPKIMessage;
+		/* NID_id_it_suppLangTags - Supported Language Tags */
+		STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
+		/* this is to be used for so far undeclared objects */
+		ASN1_TYPE *other;
+		} infoValue;
+	} CMP_INFOTYPEANDVALUE;
+DECLARE_ASN1_FUNCTIONS(CMP_INFOTYPEANDVALUE)
+DECLARE_STACK_OF(CMP_INFOTYPEANDVALUE)
+
+#if 0
+/* TODO: that should be changed to be a real CMP_PKIFREETEXT type? */
+/*
+ PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+	 -- text encoded as UTF-8 String [RFC3629] (note: each
+	 -- UTF8String MAY include an [RFC3066] language tag
+	 -- to indicate the language of the contained text
+	 -- see [RFC2482] for details)
+ */
+DECLARE_STACK_OF(ASN1_UTF8STRING)
+typedef STACK_OF(ASN1_UTF8STRING) CMP_PKIFREETEXT;
+DECLARE_ASN1_FUNCTIONS(CMP_PKIFREETEXT)
+#endif
+
+/*
+	 PKIFailureInfo ::= BIT STRING {
+	 -- since we can fail in more than one way!
+	 -- More codes may be added in the future if/when required.
+		 badAlg				 (0),
+		 -- unrecognized or unsupported Algorithm Identifier
+		 badMessageCheck	 (1),
+		 -- integrity check failed (e.g., signature did not verify)
+		 badRequest			 (2),
+		 -- transaction not permitted or supported
+		 badTime			 (3),
+		 -- messageTime was not sufficiently close to the system time,
+		 -- as defined by local policy
+		 badCertId			 (4),
+		 -- no certificate could be found matching the provided criteria
+		 badDataFormat		 (5),
+		 -- the data submitted has the wrong format
+		 wrongAuthority		 (6),
+		 -- the authority indicated in the request is different from the
+		 -- one creating the response token
+		 incorrectData		 (7),
+		 -- the requester's data is incorrect (for notary services)
+		 missingTimeStamp	 (8),
+		 -- when the timestamp is missing but should be there
+		 -- (by policy)
+		 badPOP				 (9),
+		 -- the proof-of-possession failed
+		 certRevoked		 (10),
+			-- the certificate has already been revoked
+		 certConfirmed		 (11),
+			-- the certificate has already been confirmed
+		 wrongIntegrity		 (12),
+			-- invalid integrity, password based instead of signature or
+			-- vice versa
+		 badRecipientNonce	 (13),
+			-- invalid recipient nonce, either missing or wrong value
+		 timeNotAvailable	 (14),
+			-- the TSA's time source is not available
+		 unacceptedPolicy	 (15),
+			-- the requested TSA policy is not supported by the TSA.
+		 unacceptedExtension (16),
+			-- the requested extension is not supported by the TSA.
+		 addInfoNotAvailable (17),
+			-- the additional information requested could not be
+			-- understood or is not available
+		 badSenderNonce		 (18),
+			-- invalid sender nonce, either missing or wrong size
+		 badCertTemplate	 (19),
+			-- invalid cert. template or missing mandatory information
+		 signerNotTrusted	 (20),
+			-- signer of the message unknown or not trusted
+		 transactionIdInUse  (21),
+			-- the transaction identifier is already in use
+		 unsupportedVersion  (22),
+			-- the version of the message is not supported
+		 notAuthorized		 (23),
+			-- the sender was not authorized to make the preceding
+			-- request or perform the preceding action
+		 systemUnavail		 (24),
+		 -- the request cannot be handled due to system unavailability
+		 systemFailure		 (25),
+		 -- the request cannot be handled due to system failure
+		 duplicateCertReq	 (26)
+		 -- certificate cannot be issued because a duplicate
+		 -- certificate already exists
+	 }
+	 */
+#define CMP_PKIFAILUREINFO_badAlg				 0
+#define CMP_PKIFAILUREINFO_badMessageCheck		 1
+#define CMP_PKIFAILUREINFO_badRequest			 2
+#define CMP_PKIFAILUREINFO_badTime				 3
+#define CMP_PKIFAILUREINFO_badCertId			 4
+#define CMP_PKIFAILUREINFO_badDataFormat		 5
+#define CMP_PKIFAILUREINFO_wrongAuthority		 6
+#define CMP_PKIFAILUREINFO_incorrectData		 7
+#define CMP_PKIFAILUREINFO_missingTimeStamp		 8
+#define CMP_PKIFAILUREINFO_badPOP				 9
+#define CMP_PKIFAILUREINFO_certRevoked			10
+#define CMP_PKIFAILUREINFO_certConfirmed		11
+#define CMP_PKIFAILUREINFO_wrongIntegrity		12
+#define CMP_PKIFAILUREINFO_badRecipientNonce	13
+#define CMP_PKIFAILUREINFO_timeNotAvailable		14
+#define CMP_PKIFAILUREINFO_unacceptedPolicy		15
+#define CMP_PKIFAILUREINFO_unacceptedExtension	16
+#define CMP_PKIFAILUREINFO_addInfoNotAvailable	17
+#define CMP_PKIFAILUREINFO_badSenderNonce		18
+#define CMP_PKIFAILUREINFO_badCertTemplate		19
+#define CMP_PKIFAILUREINFO_signerNotTrusted		20
+#define CMP_PKIFAILUREINFO_transactionIdInUse	21
+#define CMP_PKIFAILUREINFO_unsupportedVersion	22
+#define CMP_PKIFAILUREINFO_notAuthorized		23
+#define CMP_PKIFAILUREINFO_systemUnavail		24
+#define CMP_PKIFAILUREINFO_systemFailure		25
+#define CMP_PKIFAILUREINFO_duplicateCertReq		26
+#define CMP_PKIFAILUREINFO_MAX					26
+typedef ASN1_BIT_STRING CMP_PKIFAILUREINFO;
+
+#define CMP_CTX_FAILINFO_badAlg				 (1 << 0)
+#define CMP_CTX_FAILINFO_badMessageCheck	 (1 << 1)
+#define CMP_CTX_FAILINFO_badRequest			 (1 << 2)
+#define CMP_CTX_FAILINFO_badTime			 (1 << 3)
+#define CMP_CTX_FAILINFO_badCertId			 (1 << 4)
+#define CMP_CTX_FAILINFO_badDataFormat		 (1 << 5)
+#define CMP_CTX_FAILINFO_wrongAuthority		 (1 << 6)
+#define CMP_CTX_FAILINFO_incorrectData		 (1 << 7)
+#define CMP_CTX_FAILINFO_missingTimeStamp	 (1 << 8)
+#define CMP_CTX_FAILINFO_badPOP				 (1 << 9)
+#define CMP_CTX_FAILINFO_certRevoked		 (1 << 10)
+#define CMP_CTX_FAILINFO_certConfirmed		 (1 << 11)
+#define CMP_CTX_FAILINFO_wrongIntegrity		 (1 << 12)
+#define CMP_CTX_FAILINFO_badRecipientNonce	 (1 << 13)
+#define CMP_CTX_FAILINFO_timeNotAvailable	 (1 << 14)
+#define CMP_CTX_FAILINFO_unacceptedPolicy	 (1 << 15)
+#define CMP_CTX_FAILINFO_unacceptedExtension (1 << 16)
+#define CMP_CTX_FAILINFO_addInfoNotAvailable (1 << 17)
+#define CMP_CTX_FAILINFO_badSenderNonce		 (1 << 18)
+#define CMP_CTX_FAILINFO_badCertTemplate	 (1 << 19)
+#define CMP_CTX_FAILINFO_signerNotTrusted	 (1 << 20)
+#define CMP_CTX_FAILINFO_transactionIdInUse  (1 << 21)
+#define CMP_CTX_FAILINFO_unsupportedVersion  (1 << 22)
+#define CMP_CTX_FAILINFO_notAuthorized		 (1 << 23)
+#define CMP_CTX_FAILINFO_systemUnavail		 (1 << 24)
+#define CMP_CTX_FAILINFO_systemFailure		 (1 << 25)
+#define CMP_CTX_FAILINFO_duplicateCertReq	 (1 << 26)
+
+/*
+	 PKIStatus ::= INTEGER {
+		 accepted				 (0),
+		 -- you got exactly what you asked for
+		 grantedWithMods		(1),
+		 -- you got something like what you asked for; the
+		 -- requester is responsible for ascertaining the differences
+		 rejection				(2),
+		 -- you don't get it, more information elsewhere in the message
+		 waiting				(3),
+		 -- the request body part has not yet been processed; expect to
+		 -- hear more later (note: proper handling of this status
+		 -- response MAY use the polling req/rep PKIMessages specified
+		 -- in Section 5.3.22; alternatively, polling in the underlying
+		 -- transport layer MAY have some utility in this regard)
+		 revocationWarning		(4),
+		 -- this message contains a warning that a revocation is
+		 -- imminent
+		 revocationNotification (5),
+		 -- notification that a revocation has occurred
+		 keyUpdateWarning		(6)
+		 -- update already done for the oldCertId specified in
+		 -- CertReqMsg
+	 }
+	 */
+#define CMP_PKISTATUS_accepted					0
+#define CMP_PKISTATUS_grantedWithMods			1
+#define CMP_PKISTATUS_rejection					2
+#define CMP_PKISTATUS_waiting					3
+#define CMP_PKISTATUS_revocationWarning			4
+#define CMP_PKISTATUS_revocationNotification	5
+#define CMP_PKISTATUS_keyUpdateWarning			6
+
+typedef ASN1_INTEGER CMP_PKISTATUS;
+DECLARE_ASN1_FUNCTIONS(CMP_PKISTATUS)
+
+/*
+	 CertOrEncCert ::= CHOICE {
+		 certificate	 [0] CMPCertificate,
+		 encryptedCert	 [1] EncryptedValue
+	 }
+ */
+#define CMP_CERTORENCCERT_CERTIFICATE	0
+#define CMP_CERTORENCCERT_ENCRYPTEDCERT 1
+typedef struct cmp_certorenccert_st
+	{
+	int type;
+	union
+		{
+		/* the RFC explicitly allows substituting CMPCertificate with X509 */
+		X509  *certificate;
+		CRMF_ENCRYPTEDVALUE *encryptedCert;
+		} value;
+	} CMP_CERTORENCCERT;
+DECLARE_ASN1_FUNCTIONS(CMP_CERTORENCCERT)
+
+/*
+	 CertifiedKeyPair ::= SEQUENCE {
+		 certOrEncCert		 CertOrEncCert,
+		 privateKey		 [0] EncryptedValue		 OPTIONAL,
+		 -- see [CRMF] for comment on encoding
+		 publicationInfo [1] PKIPublicationInfo  OPTIONAL
+	 }
+ */
+typedef struct cmp_certifiedkeypair_st
+	{
+	CMP_CERTORENCCERT		*certOrEncCert;
+	CRMF_ENCRYPTEDVALUE		*privateKey;
+	CRMF_PKIPUBLICATIONINFO *failInfo;
+	} CMP_CERTIFIEDKEYPAIR;
+DECLARE_ASN1_FUNCTIONS(CMP_CERTIFIEDKEYPAIR)
+
+/*
+	 PKIStatusInfo ::= SEQUENCE {
+		 status		   PKIStatus,
+		 statusString  PKIFreeText	   OPTIONAL,
+		 failInfo	   PKIFailureInfo  OPTIONAL
+	 }
+ */
+typedef struct cmp_pkistatusinfo_st
+	{
+	CMP_PKISTATUS	   *status;
+#if 0
+	CMP_PKIFREETEXT    *statusString;
+#endif
+	STACK_OF(ASN1_UTF8STRING)	 *statusString;
+	CMP_PKIFAILUREINFO *failInfo;
+	} CMP_PKISTATUSINFO;
+DECLARE_ASN1_FUNCTIONS(CMP_PKISTATUSINFO)
+DECLARE_STACK_OF(CMP_PKISTATUSINFO)
+
+/*
+	 RevReqContent ::= SEQUENCE OF RevDetails
+
+	 RevDetails ::= SEQUENCE {
+		 certDetails		 CertTemplate,
+		 -- allows requester to specify as much as they can about
+		 -- the cert. for which revocation is requested
+		 -- (e.g., for cases in which serialNumber is not available)
+		 crlEntryDetails	 Extensions		  OPTIONAL
+		 -- requested crlEntryExtensions
+	 }
+*/
+typedef struct cmp_revdetails_st
+	{
+	CRMF_CERTTEMPLATE		 *certDetails;
+	X509_EXTENSIONS			 *crlEntryDetails;
+	} CMP_REVDETAILS;
+DECLARE_ASN1_FUNCTIONS(CMP_REVDETAILS)
+DECLARE_STACK_OF(CMP_REVDETAILS)
+
+/*
+	 RevRepContent ::= SEQUENCE {
+		 status		  SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+		 -- in same order as was sent in RevReqContent
+		 revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId
+											 OPTIONAL,
+		 -- IDs for which revocation was requested
+		 -- (same order as status)
+		 crls	  [1] SEQUENCE SIZE (1..MAX) OF CertificateList
+											 OPTIONAL
+		 -- the resulting CRLs (there may be more than one)
+	 }
+ */
+typedef struct cmp_revrep_st
+	{
+	STACK_OF(CMP_PKISTATUSINFO) *status;
+	STACK_OF(CRMF_CERTID)		*certId;
+	STACK_OF(X509)				*crls;
+	} CMP_REVREPCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_REVREPCONTENT)
+
+/*
+	 KeyRecRepContent ::= SEQUENCE {
+		 status					 PKIStatusInfo,
+		 newSigCert			 [0] CMPCertificate OPTIONAL,
+		 caCerts			 [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate OPTIONAL,
+		 keyPairHist		 [2] SEQUENCE SIZE (1..MAX) OF CertifiedKeyPair OPTIONAL
+	 }
+*/
+typedef struct cmp_keyrecrepcontent_st
+	{
+	CMP_PKISTATUSINFO		*status;
+	/* the RFC explicitly allows substituting CMPCertificate with X509 */
+	X509					*newSigCert;
+	STACK_OF(X509)			*caCerts;
+	STACK_OF(CMP_CERTIFIEDKEYPAIR) *keyPairHist;
+	} CMP_KEYRECREPCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_KEYRECREPCONTENT)
+
+/*
+	 ErrorMsgContent ::= SEQUENCE {
+		 pKIStatusInfo			PKIStatusInfo,
+		 errorCode				INTEGER			  OPTIONAL,
+		 -- implementation-specific error codes
+		 errorDetails			PKIFreeText		  OPTIONAL
+		 -- implementation-specific error details
+	 }
+ */
+typedef struct cmp_errormsgcontent_st
+	{
+	CMP_PKISTATUSINFO *pKIStatusInfo;
+	ASN1_INTEGER	  *errorCode;
+	STACK_OF(ASN1_UTF8STRING)	*errorDetails;
+#if 0
+	CMP_PKIFREETEXT   *errorDetails;
+#endif
+	} CMP_ERRORMSGCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_ERRORMSGCONTENT)
+
+/*
+	 CertConfirmContent ::= SEQUENCE OF CertStatus
+
+	 CertStatus ::= SEQUENCE {
+		certHash	OCTET STRING,
+		-- the hash of the certificate, using the same hash algorithm
+		-- as is used to create and verify the certificate signature
+		certReqId	INTEGER,
+		-- to match this confirmation with the corresponding req/rep
+		statusInfo	PKIStatusInfo OPTIONAL
+	 }
+ */
+typedef struct cmp_certstatus_st
+	{
+	ASN1_OCTET_STRING	*certHash;
+	ASN1_INTEGER		*certReqId;
+	CMP_PKISTATUSINFO	*statusInfo;
+	} CMP_CERTSTATUS;
+DECLARE_STACK_OF(CMP_CERTSTATUS)
+DECLARE_ASN1_SET_OF(CMP_CERTSTATUS)
+DECLARE_ASN1_FUNCTIONS(CMP_CERTSTATUS)
+
+typedef STACK_OF(CMP_CERTSTATUS) CMP_CERTCONFIRMCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_CERTCONFIRMCONTENT)
+
+/*
+	 CertResponse ::= SEQUENCE {
+		 certReqId			 INTEGER,
+		 -- to match this response with corresponding request (a value
+		 -- of -1 is to be used if certReqId is not specified in the
+		 -- corresponding request)
+		 status				 PKIStatusInfo,
+		 certifiedKeyPair	 CertifiedKeyPair	 OPTIONAL,
+		 rspInfo			 OCTET STRING		 OPTIONAL
+		 -- analogous to the id-regInfo-utf8Pairs string defined
+		 -- for regInfo in CertReqMsg [CRMF]
+	 }
+ */
+typedef struct cmp_certresponse_st
+	{
+	ASN1_INTEGER		 *certReqId;
+	CMP_PKISTATUSINFO	 *status;
+	CMP_CERTIFIEDKEYPAIR *certifiedKeyPair;
+	ASN1_OCTET_STRING	 *rspInfo;
+	} CMP_CERTRESPONSE;
+DECLARE_ASN1_FUNCTIONS(CMP_CERTRESPONSE)
+DECLARE_STACK_OF(CMP_CERTRESPONSE)
+
+/*
+	 CertRepMessage ::= SEQUENCE {
+		 caPubs		  [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+						  OPTIONAL,
+		 response		  SEQUENCE OF CertResponse
+	 }
+ */
+typedef struct cmp_certrepmessage_st
+	{
+	/* the RFC explicitly allows substituting CMPCertificate with X509 */
+	STACK_OF(X509) *caPubs;
+	STACK_OF(CMP_CERTRESPONSE)	 *response;
+	} CMP_CERTREPMESSAGE;
+DECLARE_ASN1_FUNCTIONS(CMP_CERTREPMESSAGE)
+
+/* the following is from RFC 2986 - PKCS #10
+
+Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
+	type	ATTRIBUTE.&id({IOSet}),
+	values	SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
+}
+
+CertificationRequestInfo ::= SEQUENCE {
+	version		  INTEGER { v1(0) } (v1,...),
+	subject		  Name,
+	subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+	attributes	  [0] Attributes{{ CRIAttributes }}
+}
+
+CertificationRequest ::= SEQUENCE {
+	certificationRequestInfo CertificationRequestInfo,
+	signatureAlgorithm		 AlgorithmIdentifier{{ SignatureAlgorithms }},
+	signature				 BIT STRING
+}
+*/
+typedef struct pkcs10_attribute_st
+	{
+	ASN1_OBJECT			*id;
+	STACK_OF(ASN1_TYPE) *values;
+	} PKCS10_ATTRIBUTE;
+DECLARE_ASN1_FUNCTIONS(PKCS10_ATTRIBUTE)
+DECLARE_STACK_OF(PKCS10_ATTRIBUTE)
+
+typedef struct pkcs10_certificationrequestinfo_st
+	{
+	ASN1_INTEGER			   *version;
+	X509_NAME				   *subject;
+	X509_PUBKEY				   *subjectPKInfo;
+	STACK_OF(PKCS10_ATTRIBUTE) attributes;
+	} PKCS10_CERTIFICATIONREQUESTINFO;
+DECLARE_ASN1_FUNCTIONS(PKCS10_CERTIFICATIONREQUESTINFO)
+
+typedef struct pkcs10_certificationrequest_st
+	{
+	PKCS10_CERTIFICATIONREQUESTINFO *certificationRequestInfo;
+	X509_ALGOR						*signatureAlgorithm;
+	ASN1_BIT_STRING					*signature;
+	} PKCS10_CERTIFICATIONREQUEST;
+DECLARE_ASN1_FUNCTIONS(PKCS10_CERTIFICATIONREQUEST)
+
+/*
+	 PollReqContent ::= SEQUENCE OF SEQUENCE {
+		 certReqId				INTEGER
+	 }
+ */
+typedef struct cmp_pollreq_st
+	{
+	ASN1_INTEGER *certReqId;
+	} CMP_POLLREQ;
+DECLARE_ASN1_FUNCTIONS(CMP_POLLREQ)
+DECLARE_STACK_OF(CMP_POLLREQ)
+typedef STACK_OF(CMP_POLLREQ) CMP_POLLREQCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_POLLREQCONTENT)
+
+/*
+	 PollRepContent ::= SEQUENCE OF SEQUENCE {
+		 certReqId				INTEGER,
+		 checkAfter				INTEGER,  -- time in seconds
+		 reason					PKIFreeText OPTIONAL
+	 }
+ */
+typedef struct cmp_pollrep_st
+	{
+	ASN1_INTEGER *certReqId;
+	ASN1_INTEGER *checkAfter;
+	STACK_OF(ASN1_UTF8STRING) *reason;
+	} CMP_POLLREP;
+DECLARE_ASN1_FUNCTIONS(CMP_POLLREP)
+DECLARE_STACK_OF(CMP_POLLREP)
+typedef STACK_OF(CMP_POLLREP) CMP_POLLREPCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_POLLREPCONTENT)
+
+/*
+	 PKIHeader ::= SEQUENCE {
+		 pvno				 INTEGER	 { cmp1999(1), cmp2000(2) },
+		 sender				 GeneralName,
+		 -- identifies the sender
+		 recipient			 GeneralName,
+		 -- identifies the intended recipient
+		 messageTime	 [0] GeneralizedTime		 OPTIONAL,
+		 -- time of production of this message (used when sender
+		 -- believes that the transport will be "suitable"; i.e.,
+		 -- that the time will still be meaningful upon receipt)
+		 protectionAlg	 [1] AlgorithmIdentifier	 OPTIONAL,
+		 -- algorithm used for calculation of protection bits
+		 senderKID		 [2] KeyIdentifier			 OPTIONAL,
+		 recipKID		 [3] KeyIdentifier			 OPTIONAL,
+		 -- to identify specific keys used for protection
+		 transactionID	 [4] OCTET STRING			 OPTIONAL,
+		 -- identifies the transaction; i.e., this will be the same in
+		 -- corresponding request, response, certConf, and PKIConf
+		 -- messages
+		 senderNonce	 [5] OCTET STRING			 OPTIONAL,
+		 recipNonce		 [6] OCTET STRING			 OPTIONAL,
+		 -- nonces used to provide replay protection, senderNonce
+		 -- is inserted by the creator of this message; recipNonce
+		 -- is a nonce previously inserted in a related message by
+		 -- the intended recipient of this message
+		 freeText		 [7] PKIFreeText			 OPTIONAL,
+		 -- this may be used to indicate context-specific instructions
+		 -- (this field is intended for human consumption)
+		 generalInfo	 [8] SEQUENCE SIZE (1..MAX) OF
+								InfoTypeAndValue	 OPTIONAL
+		 -- this may be used to convey context-specific information
+		 -- (this field not primarily intended for human consumption)
+	 }
+*/
+typedef struct cmp_pkiheader_st
+	{
+	ASN1_INTEGER				  *pvno;
+	GENERAL_NAME				  *sender;
+	GENERAL_NAME				  *recipient;
+	ASN1_GENERALIZEDTIME		  *messageTime;    /* 0 */
+	X509_ALGOR					  *protectionAlg;  /* 1 */
+	ASN1_OCTET_STRING			  *senderKID;	   /* 2 */
+	ASN1_OCTET_STRING			  *recipKID;	   /* 3 */
+	ASN1_OCTET_STRING			  *transactionID;  /* 4 */
+	ASN1_OCTET_STRING			  *senderNonce;    /* 5 */
+	ASN1_OCTET_STRING			  *recipNonce;	   /* 6 */
+	STACK_OF(ASN1_UTF8STRING)	  *freeText;	   /* 7 */
+	STACK_OF(CMP_INFOTYPEANDVALUE) *generalInfo;	/* 8 */
+	} CMP_PKIHEADER;
+DECLARE_ASN1_FUNCTIONS(CMP_PKIHEADER)
+
+#define V_CMP_PKIBODY_IR	0
+#define V_CMP_PKIBODY_IP	1
+#define V_CMP_PKIBODY_CR	2
+#define V_CMP_PKIBODY_CP	3
+#define V_CMP_PKIBODY_P10CR	4
+#define V_CMP_PKIBODY_POPDECC	5
+#define V_CMP_PKIBODY_POPDECR	6
+#define V_CMP_PKIBODY_KUR	7
+#define V_CMP_PKIBODY_KUP	8
+#define V_CMP_PKIBODY_KRR	9
+#define V_CMP_PKIBODY_KRP	10
+#define V_CMP_PKIBODY_RR	11
+#define V_CMP_PKIBODY_RP	12
+#define V_CMP_PKIBODY_CCR	13
+#define V_CMP_PKIBODY_CCP	14
+#define V_CMP_PKIBODY_CKUANN	15
+#define V_CMP_PKIBODY_CANN	16
+#define V_CMP_PKIBODY_RANN	17
+#define V_CMP_PKIBODY_CRLANN	18
+#define V_CMP_PKIBODY_PKICONF	19
+#define V_CMP_PKIBODY_NESTED	20
+#define V_CMP_PKIBODY_GENM	21
+#define V_CMP_PKIBODY_GENP	22
+#define V_CMP_PKIBODY_ERROR	23
+#define V_CMP_PKIBODY_CERTCONF	24
+#define V_CMP_PKIBODY_POLLREQ	25
+#define V_CMP_PKIBODY_POLLREP	26
+
+typedef STACK_OF(CMP_CHALLENGE) CMP_POPODECKEYCHALLCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_POPODECKEYCHALLCONTENT)
+
+typedef STACK_OF(ASN1_INTEGER) CMP_POPODECKEYRESPCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_POPODECKEYRESPCONTENT)
+
+typedef STACK_OF(CMP_REVDETAILS) CMP_REVREQCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_REVREQCONTENT)
+
+typedef STACK_OF(X509_CRL) CMP_CRLANNCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_CRLANNCONTENT)
+
+typedef STACK_OF(CMP_INFOTYPEANDVALUE) CMP_GENMSGCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_GENMSGCONTENT)
+
+typedef STACK_OF(CMP_INFOTYPEANDVALUE) CMP_GENREPCONTENT;
+DECLARE_ASN1_FUNCTIONS(CMP_GENREPCONTENT)
+
+/*
+	 PKIBody ::= CHOICE {		-- message-specific body elements
+		 ir		  [0]  CertReqMessages,		   --Initialization Request
+		 ip		  [1]  CertRepMessage,		   --Initialization Response
+		 cr		  [2]  CertReqMessages,		   --Certification Request
+		 cp		  [3]  CertRepMessage,		   --Certification Response
+		 p10cr	  [4]  CertificationRequest,   --imported from [PKCS10]
+		 popdecc  [5]  POPODecKeyChallContent, --pop Challenge
+		 popdecr  [6]  POPODecKeyRespContent,  --pop Response
+		 kur	  [7]  CertReqMessages,		   --Key Update Request
+		 kup	  [8]  CertRepMessage,		   --Key Update Response
+		 krr	  [9]  CertReqMessages,		   --Key Recovery Request
+		 krp	  [10] KeyRecRepContent,	   --Key Recovery Response
+		 rr		  [11] RevReqContent,		   --Revocation Request
+		 rp		  [12] RevRepContent,		   --Revocation Response
+		 ccr	  [13] CertReqMessages,		   --Cross-Cert. Request
+		 ccp	  [14] CertRepMessage,		   --Cross-Cert. Response
+		 ckuann   [15] CAKeyUpdAnnContent,	   --CA Key Update Ann.
+		 cann	  [16] CertAnnContent,		   --Certificate Ann.
+		 rann	  [17] RevAnnContent,		   --Revocation Ann.
+		 crlann   [18] CRLAnnContent,		   --CRL Announcement
+		 pkiconf  [19] PKIConfirmContent,	   --Confirmation
+		 nested   [20] NestedMessageContent,   --Nested Message
+		 genm	  [21] GenMsgContent,		   --General Message
+		 genp	  [22] GenRepContent,		   --General Response
+		 error	  [23] ErrorMsgContent,		   --Error Message
+		 certConf [24] CertConfirmContent,	   --Certificate confirm
+		 pollReq  [25] PollReqContent,		   --Polling request
+		 pollRep  [26] PollRepContent		   --Polling response
+*/
+typedef struct cmp_pkibody_st
+	{
+	int type;
+	union
+		{
+		CRMF_CERTREQMESSAGES   *ir;   /* 0 */
+		CMP_CERTREPMESSAGE			*ip;   /* 1 */
+		CRMF_CERTREQMESSAGES   *cr;   /* 2 */
+		CMP_CERTREPMESSAGE			*cp;   /* 3 */
+		/* p10cr	[4]  CertificationRequest,	 --imported from [PKCS10] */
+		PKCS10_CERTIFICATIONREQUEST *p10cr;   /* 4 */
+		/* popdecc	[5]  POPODecKeyChallContent, --pop Challenge */
+		/* POPODecKeyChallContent ::= SEQUENCE OF Challenge */
+		CMP_POPODECKEYCHALLCONTENT *popdecc; /* 5 */
+		/* popdecr	[6]  POPODecKeyRespContent,  --pop Response */
+		/* POPODecKeyRespContent ::= SEQUENCE OF INTEGER */
+		CMP_POPODECKEYRESPCONTENT  *popdecr; /* 6 */
+		CRMF_CERTREQMESSAGES   *kur;   /* 7 */
+		CMP_CERTREPMESSAGE			*kup;	/* 8 */
+		CRMF_CERTREQMESSAGES   *krr;   /* 9 */
+
+		/* krp		[10] KeyRecRepContent,		 --Key Recovery Response */
+		CMP_KEYRECREPCONTENT		*krp;	/* 10 */
+		/* rr		[11] RevReqContent,			 --Revocation Request */
+		CMP_REVREQCONTENT	 *rr; /* 11 */
+		/* rp		[12] RevRepContent,			 --Revocation Response */
+		CMP_REVREPCONTENT	*rp; /* 12 */
+		/* ccr		[13] CertReqMessages,		 --Cross-Cert. Request */
+		CRMF_CERTREQMESSAGES   *ccr; /* 13 */
+		/* ccp		[14] CertRepMessage,		 --Cross-Cert. Response */
+		CMP_CERTREPMESSAGE			*ccp; /* 14 */
+		/* ckuann	[15] CAKeyUpdAnnContent,	 --CA Key Update Ann. */
+		CMP_CAKEYUPDANNCONTENT	 *ckuann; /* 15 */
+		/* cann		[16] CertAnnContent,		 --Certificate Ann. */
+		/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+		X509					   *cann; /* 16 */
+		/* rann		[17] RevAnnContent,			 --Revocation Ann. */
+		CMP_REVANNCONTENT		   *rann; /* 17 */
+		/* crlann	[18] CRLAnnContent,			 --CRL Announcement */
+		/* CRLAnnContent ::= SEQUENCE OF CertificateList */
+		CMP_CRLANNCONTENT		  *crlann;
+		/* PKIConfirmContent ::= NULL */
+		/* pkiconf	[19] PKIConfirmContent,		 --Confirmation */
+		/* CMP_PKICONFIRMCONTENT would be only a typedef of ASN1_NULL */
+		/* CMP_CONFIRMCONTENT *pkiconf; */
+		/* NOTE: this should ASN1_NULL according to the RFC but there might be a struct in it when sent from faulty servers... */
+		ASN1_TYPE						*pkiconf; /* 19 */
+		/* nested	[20] NestedMessageContent,	 --Nested Message */
+		/* NestedMessageContent ::= PKIMessages */
+		CMP_PKIMESSAGES				   *nested; /* 20 */
+		/* genm		[21] GenMsgContent,			 --General Message */
+		/* GenMsgContent ::= SEQUENCE OF InfoTypeAndValue */
+		CMP_GENMSGCONTENT *genm; /* 21 */
+		/* genp		[22] GenRepContent,			 --General Response */
+		/* GenRepContent ::= SEQUENCE OF InfoTypeAndValue */
+		CMP_GENREPCONTENT *genp; /* 22 */
+		/* error	[23] ErrorMsgContent,		 --Error Message */
+		CMP_ERRORMSGCONTENT			   *error;	  /* 23 */
+		/* certConf [24] CertConfirmContent,	 --Certificate confirm */
+		CMP_CERTCONFIRMCONTENT		   *certConf; /* 24 */
+		/* pollReq	[25] PollReqContent,		 --Polling request */
+		CMP_POLLREQCONTENT			*pollReq;
+		/* pollRep	[26] PollRepContent			 --Polling response */
+		CMP_POLLREPCONTENT			 *pollRep;
+		} value;
+	} CMP_PKIBODY;
+DECLARE_ASN1_FUNCTIONS(CMP_PKIBODY)
+
+/*
+	 PKIProtection ::= BIT STRING
+
+	 PKIMessages ::= SEQUENCE SIZE (1..MAX) OF PKIMessage
+
+	  PKIMessage ::= SEQUENCE {
+		 header			  PKIHeader,
+		 body			  PKIBody,
+		 protection   [0] PKIProtection OPTIONAL,
+		 extraCerts   [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+						  OPTIONAL
+	 }
+ */
+typedef struct cmp_pkimessage_st
+	{
+	CMP_PKIHEADER				 *header;
+	CMP_PKIBODY					 *body;
+	ASN1_BIT_STRING				 *protection; /* 0 */
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	STACK_OF(X509) *extraCerts; /* 1 */
+	} CMP_PKIMESSAGE;
+DECLARE_ASN1_FUNCTIONS(CMP_PKIMESSAGE)
+DECLARE_STACK_OF(CMP_PKIMESSAGE) /* PKIMessages */
+
+/*
+	 ProtectedPart ::= SEQUENCE {
+		 header    PKIHeader,
+		 body	   PKIBody
+	 }
+	 */
+typedef struct cmp_protectedpart_st
+	{
+	CMP_PKIHEADER				 *header;
+	CMP_PKIBODY					 *body;
+	} CMP_PROTECTEDPART;
+DECLARE_ASN1_FUNCTIONS(CMP_PROTECTEDPART)
+
+/* this is not defined here as it is already in CRMF:
+	 id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+	 PBMParameter ::= SEQUENCE {
+		 salt				 OCTET STRING,
+		 -- note:  implementations MAY wish to limit acceptable sizes
+		 -- of this string to values appropriate for their environment
+		 -- in order to reduce the risk of denial-of-service attacks
+		 owf				 AlgorithmIdentifier,
+		 -- AlgId for a One-Way Function (SHA-1 recommended)
+		 iterationCount		 INTEGER,
+		 -- number of times the OWF is applied
+		 -- note:  implementations MAY wish to limit acceptable sizes
+		 -- of this integer to values appropriate for their environment
+		 -- in order to reduce the risk of denial-of-service attacks
+		 mac				 AlgorithmIdentifier
+		 -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+	 }	 -- or HMAC [RFC2104, RFC2202])
+ */
+
+/*
+	TODO: this is not yet defined here - but DH is anyway not used yet
+
+	 id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+	 DHBMParameter ::= SEQUENCE {
+		 owf				 AlgorithmIdentifier,
+		 -- AlgId for a One-Way Function (SHA-1 recommended)
+		 mac				 AlgorithmIdentifier
+		 -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+	 }	 -- or HMAC [RFC2104, RFC2202])
+
+ */
+
+/* The following is not cared for, because it is described in section 5.2.5
+ * that this is beyond the scope of CMP
+	 OOBCert ::= CMPCertificate
+
+	 OOBCertHash ::= SEQUENCE {
+		 hashAlg	 [0] AlgorithmIdentifier	 OPTIONAL,
+		 certId		 [1] CertId					 OPTIONAL,
+		 hashVal		 BIT STRING
+		 -- hashVal is calculated over the DER encoding of the
+		 -- self-signed certificate with the identifier certID.
+	 }
+ */
+
+/* ########################################################################## *
+ * context DECLARATIONS
+ * ########################################################################## */
+
+typedef void (*cmp_logfn_t)(const char *msg);
+typedef int (*cmp_certConfFn_t)(int status, const X509 *cert);
+
+/* this structure is used to store the context for CMP sessions 
+ * partly using OpenSSL ASN.1 types in order to ease handling it */
+typedef struct cmp_ctx_st
+	{
+	/* "reference and secret" for MSG_MAC_ALG */
+	ASN1_OCTET_STRING	 *referenceValue;
+	ASN1_OCTET_STRING	 *secretValue;
+	/* for setting itav for EJBCA in CA mode */
+	ASN1_UTF8STRING		 *regToken;
+	/* certificate used to identify the server */
+	X509				 *srvCert;
+	/* current client certificate used to identify and sign for MSG_SIG_ALG */
+	X509				 *clCert;
+	X509				 *oldClCert;
+	/* subject name to be used in the cert template. NB: could also be taken
+	 * from clcert */
+	X509_NAME			 *subjectName;
+	/* to set in recipient in pkiheader */ 
+	X509_NAME			 *recipient;
+	/* names to be added to the cert template as the subjectAltName extension */
+	STACK_OF(GENERAL_NAME) *subjectAltNames;
+	/* whether or not the subjectAltName extension should be set critical */
+	int                   setSubjectAltNameCritical;
+	/* Stack of CA certificates sent by the CA in a IP message */ 
+	STACK_OF(X509)		 *caPubs;
+	/* stack of extraCerts to be included when sending a PKI message */
+	STACK_OF(X509)		 *extraCertsOut;
+	/* stack of extraCerts received from remote */ 
+	STACK_OF(X509)		 *extraCertsIn;
+	/* EVP_PKEY holding the *current* key pair
+	 * Note: this is not an ASN.1 type */
+	EVP_PKEY			 *pkey;
+	/* *new* CLIENT certificate received from the CA
+	 * TODO: this should be a stack since there could be more than one */
+	X509				 *newClCert;
+	/* EVP_PKEY holding the *new* key pair
+	 * Note: this is not an ASN.1 type */
+	EVP_PKEY			 *newPkey;
+	/* the current transaction ID */
+	ASN1_OCTET_STRING	 *transactionID;
+	/* last nonce received */
+	ASN1_OCTET_STRING	 *recipNonce;
+	/* to set implicitConfirm in IR/KUR/CR messges false=0 true!=0 */
+	int	implicitConfirm;
+	/* Proof-of-posession mechanism used. Defaults to signature (POPOsignkingKey) */ 
+	int	popoMethod;
+	/* maximum time in secods to wait for an http transfer to complete
+	 * Note: only usable with libcurl! */
+	int	HttpTimeOut;
+	/* maximum time to poll the server for a response if a 'waiting' PKIStatus is received */
+	int maxPollTime;
+	/* PKIStatus of last received IP/CP/KUP */
+	/* TODO: this should be a stack since there could be more than one */
+	int lastPKIStatus;
+	/* failInfoCode of last received IP/CP/KUP */
+	/* TODO: this should be a stack since there could be more than one */
+	unsigned long failInfoCode;
+	STACK_OF(ASN1_UTF8STRING) *lastStatusString;
+
+	/* log callback functions for error and debug messages */
+	cmp_logfn_t error_cb, debug_cb;
+
+	/* callback for letting the user check the received certificate and 
+	 * reject if necessary */
+	cmp_certConfFn_t certConf_cb;
+
+	/* stores for trusted and untrusted (intermediate) certificates */
+	X509_STORE *trusted_store;
+	X509_STORE *untrusted_store;
+
+	/* include root certs from extracerts when validating? Used for 3GPP-style E.7 */
+	int permitTAInExtraCertsForIR;
+	/* stores the server Cert as soon as it's trust chain has been validated */
+	X509 *validatedSrvCert;
+
+	/* HTTP transfer related settings */
+	char	  *serverName;
+	int		  serverPort;
+	char	  *serverPath;
+	char	  *proxyName;
+	int		  proxyPort;
+	int       lastHTTPCode;
+	int       useTLS;
+	char	  *sourceAddress;
+
+	CERTIFICATEPOLICIES *policies;
+
+	} CMP_CTX;
+
+DECLARE_ASN1_FUNCTIONS(CMP_CTX)
+
+/* ########################################################################## *
+ * function DECLARATIONS
+ * ########################################################################## */
+
+/* cmp_msg.c */
+CMP_PKIMESSAGE *CMP_ir_new( CMP_CTX *ctx);
+CMP_PKIMESSAGE *CMP_cr_new( CMP_CTX *ctx);
+CMP_PKIMESSAGE *CMP_rr_new( CMP_CTX *ctx);
+CMP_PKIMESSAGE *CMP_certConf_new( CMP_CTX *ctx);
+CMP_PKIMESSAGE *CMP_kur_new( CMP_CTX *ctx);
+CMP_PKIMESSAGE *CMP_genm_new( CMP_CTX *ctx);
+CMP_PKIMESSAGE *CMP_pollReq_new( CMP_CTX *ctx, int reqId);
+
+/* cmp_lib.c */
+long CMP_REVREPCONTENT_PKIStatus_get(CMP_REVREPCONTENT *revRep, long reqId);
+int CMP_PKIHEADER_set_version(CMP_PKIHEADER *hdr, int version);
+int CMP_PKIHEADER_set1_recipient(CMP_PKIHEADER *hdr, const X509_NAME *nm);
+int CMP_PKIHEADER_set1_sender(CMP_PKIHEADER *hdr, const X509_NAME *nm);
+int CMP_PKIHEADER_set1_transactionID(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *transactionID);
+int CMP_PKIHEADER_set1_recipNonce(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *recipNonce);
+int CMP_PKIHEADER_set1_senderKID(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *senderKID);
+int CMP_PKIHEADER_set_messageTime(CMP_PKIHEADER *hdr);
+int CMP_PKIMESSAGE_set_implicitConfirm(CMP_PKIMESSAGE *msg);
+int CMP_PKIMESSAGE_check_implicitConfirm(CMP_PKIMESSAGE *msg);
+int CMP_PKIHEADER_push0_freeText( CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
+int CMP_PKIHEADER_push1_freeText( CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
+int CMP_PKIHEADER_init(CMP_CTX *ctx, CMP_PKIHEADER *hdr);
+ASN1_BIT_STRING *CMP_calc_protection_pbmac(CMP_PKIMESSAGE *pkimessage, const ASN1_OCTET_STRING *secret);
+int CMP_PKIMESSAGE_protect(CMP_CTX *ctx, CMP_PKIMESSAGE *msg);
+int CMP_CERTSTATUS_set_certHash( CMP_CERTSTATUS *certStatus, const X509 *cert);
+int CMP_PKIHEADER_generalInfo_item_push0(CMP_PKIHEADER *hdr, const CMP_INFOTYPEANDVALUE *itav);
+int CMP_PKIMESSAGE_genm_item_push0(CMP_PKIMESSAGE *msg, const CMP_INFOTYPEANDVALUE *itav);
+int CMP_ITAV_stack_item_push0(STACK_OF(CMP_INFOTYPEANDVALUE) **itav_sk_p, const CMP_INFOTYPEANDVALUE *itav);
+long CMP_PKISTATUSINFO_PKIstatus_get( CMP_PKISTATUSINFO *statusInfo);
+long CMP_CERTREPMESSAGE_PKIStatus_get( CMP_CERTREPMESSAGE *certRep, long certReqId);
+char *CMP_CERTREPMESSAGE_PKIFailureInfoString_get0(CMP_CERTREPMESSAGE *certRep, long certReqId);
+STACK_OF(ASN1_UTF8STRING)* CMP_CERTREPMESSAGE_PKIStatusString_get0( CMP_CERTREPMESSAGE *certRep, long certReqId);
+CMP_PKIFAILUREINFO *CMP_CERTREPMESSAGE_PKIFailureInfo_get0(CMP_CERTREPMESSAGE *certRep, long certReqId);
+X509 *CMP_CERTREPMESSAGE_get_certificate(CMP_CTX *ctx, CMP_CERTREPMESSAGE *certrep);
+int CMP_PKIFAILUREINFO_check( ASN1_BIT_STRING *failInfo, int codeBit);
+CMP_CERTRESPONSE *CMP_CERTREPMESSAGE_certResponse_get0( CMP_CERTREPMESSAGE *certRep, long certReqId);
+int CMP_CERTREPMESSAGE_certType_get( CMP_CERTREPMESSAGE *certRep, long certReqId);
+int CMP_PKIMESSAGE_set_bodytype( CMP_PKIMESSAGE *msg, int type);
+int CMP_PKIMESSAGE_get_bodytype( CMP_PKIMESSAGE *msg);
+char *CMP_PKIMESSAGE_parse_error_msg( CMP_PKIMESSAGE *msg, char *errormsg, int bufsize);
+ASN1_OCTET_STRING *CMP_get_cert_subject_key_id(const X509 *cert);
+STACK_OF(X509) *CMP_build_cert_chain(X509_STORE *store, X509 *cert);
+
+/* cmp_vfy.c */
+int CMP_validate_msg(CMP_CTX *ctx, CMP_PKIMESSAGE *msg);
+
+/* from cmp_http.c */
+int CMP_PKIMESSAGE_http_perform(const CMP_CTX *ctx, const CMP_PKIMESSAGE *msg, CMP_PKIMESSAGE **out);
+long CMP_get_http_response_code(const CMP_CTX *ctx);
+	
+
+/* from cmp_ses.c */
+X509 *CMP_doInitialRequestSeq(CMP_CTX *ctx);
+X509 *CMP_doCertificateRequestSeq(CMP_CTX *ctx);
+int CMP_doRevocationRequestSeq(CMP_CTX *ctx);
+X509 *CMP_doKeyUpdateRequestSeq(CMP_CTX *ctx);
+STACK_OF(CMP_INFOTYPEANDVALUE) *CMP_doGeneralMessageSeq(CMP_CTX *ctx, int nid, char *value);
+
+/* from cmp_ctx.c */
+CMP_CTX *CMP_CTX_create(void);
+int CMP_CTX_init( CMP_CTX *ctx);
+int CMP_CTX_set0_trustedStore( CMP_CTX *ctx, X509_STORE *store);
+int CMP_CTX_set0_untrustedStore( CMP_CTX *ctx, X509_STORE *store);
+void CMP_CTX_delete(CMP_CTX *ctx);
+int CMP_CTX_set_error_callback( CMP_CTX *ctx, cmp_logfn_t cb);
+int CMP_CTX_set_debug_callback( CMP_CTX *ctx, cmp_logfn_t cb);
+int CMP_CTX_set_certConf_callback( CMP_CTX *ctx, cmp_certConfFn_t cb);
+int CMP_CTX_set1_referenceValue( CMP_CTX *ctx, const unsigned char *ref, size_t len);
+int CMP_CTX_set1_secretValue( CMP_CTX *ctx, const unsigned char *sec, const size_t len);
+int CMP_CTX_set1_regToken( CMP_CTX *ctx, const char *regtoken, const size_t len);
+/* for backwards compatibility, TODO: remove asap */
+#define CMP_CTX_set1_caCert CMP_CTX_set1_srvCert
+int CMP_CTX_set1_srvCert( CMP_CTX *ctx, const X509 *cert);
+int CMP_CTX_set1_clCert( CMP_CTX *ctx, const X509 *cert);
+int CMP_CTX_set1_oldClCert( CMP_CTX *ctx, const X509 *cert);
+int CMP_CTX_set1_subjectName( CMP_CTX *ctx, const X509_NAME *name);
+int CMP_CTX_set1_recipient( CMP_CTX *ctx, const X509_NAME *name);
+int CMP_CTX_subjectAltName_push1( CMP_CTX *ctx, const GENERAL_NAME *name);
+int CMP_CTX_set1_sender( CMP_CTX *ctx, const X509_NAME *name);
+X509_NAME* CMP_CTX_sender_get( CMP_CTX *ctx);
+STACK_OF(X509)* CMP_CTX_caPubs_get1( CMP_CTX *ctx);
+X509 *CMP_CTX_caPubs_pop( CMP_CTX *ctx);
+int CMP_CTX_caPubs_num( CMP_CTX *ctx);
+int CMP_CTX_set1_caPubs( CMP_CTX *ctx, const STACK_OF(X509) *caPubs);
+int CMP_CTX_policyOID_push1( CMP_CTX *ctx, const char *policyOID);
+
+int CMP_CTX_set1_extraCertsOut( CMP_CTX *ctx, const STACK_OF(X509) *extraCertsOut);
+int CMP_CTX_extraCertsOut_push1( CMP_CTX *ctx, const X509 *val);
+int CMP_CTX_extraCertsOut_num( CMP_CTX *ctx);
+STACK_OF(X509)* CMP_CTX_extraCertsIn_get1( CMP_CTX *ctx);
+int CMP_CTX_set1_extraCertsIn( CMP_CTX *ctx, const STACK_OF(X509) *extraCertsIn);
+X509 *CMP_CTX_extraCertsIn_pop( CMP_CTX *ctx);
+int CMP_CTX_extraCertsIn_num( CMP_CTX *ctx);
+int CMP_CTX_loadUntrustedStack(CMP_CTX *ctx, STACK_OF(X509) *stack);
+
+int CMP_CTX_set1_newClCert( CMP_CTX *ctx, const X509 *cert);
+int CMP_CTX_set0_pkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+int CMP_CTX_set1_pkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+int CMP_CTX_set0_newPkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+int CMP_CTX_set1_newPkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+int CMP_CTX_set1_transactionID( CMP_CTX *ctx, const ASN1_OCTET_STRING *id);
+int CMP_CTX_set1_senderNonce( CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce);
+int CMP_CTX_set1_recipNonce( CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce);
+int CMP_CTX_set1_serverName( CMP_CTX *ctx, const char *name);
+int CMP_CTX_set1_serverPort( CMP_CTX *ctx, int port);
+int CMP_CTX_set1_proxyName( CMP_CTX *ctx, const char *name);
+int CMP_CTX_set1_proxyPort( CMP_CTX *ctx, int port);
+int CMP_CTX_set1_sourceAddress( CMP_CTX *ctx, const char *ip);
+/* for backwards compatibility, TODO: remove asap */
+#define CMP_CTX_set1_timeOut CMP_CTX_set_HttpTimeOut 
+int CMP_CTX_set1_timeOut( CMP_CTX *ctx, int time);
+int CMP_CTX_set1_popoMethod( CMP_CTX *ctx, int method);
+int CMP_CTX_set1_serverPath( CMP_CTX *ctx, const char *path);
+int CMP_CTX_set_failInfoCode(CMP_CTX *ctx, CMP_PKIFAILUREINFO *failInfo);
+unsigned long CMP_CTX_failInfoCode_get(CMP_CTX *ctx);
+STACK_OF(ASN1_UTF8STRING) *CMP_CTX_statusString_get( CMP_CTX *ctx);
+#define CMP_CTX_OPT_UNSET                      0
+#define CMP_CTX_OPT_SET                        1
+#define CMP_CTX_OPT_IMPLICITCONFIRM            2
+#define CMP_CTX_OPT_POPMETHOD                  3
+#define CMP_CTX_OPT_MAXPOLLTIME                4
+#define CMP_CTX_PERMIT_TA_IN_EXTRACERTS_FOR_IR 5
+#define CMP_CTX_SET_SUBJECTALTNAME_CRITICAL    6
+#define CMP_CTX_USE_TLS                        7
+int CMP_CTX_set_option( CMP_CTX *ctx, const int opt, const int val);
+#if 0
+int CMP_CTX_push_freeText( CMP_CTX *ctx, const char *text);
+#endif
+
+int CMP_CTX_error_callback(const char *str, size_t len, void *u);
+void CMP_printf(const CMP_CTX *ctx, const char *fmt, ...);
+
+/* BIO definitions */
+#define d2i_CMP_PKIMESSAGE_bio(bp,p) ASN1_d2i_bio_of(CMP_PKIMESSAGE,CMP_PKIMESSAGE_new,d2i_CMP_PKIMESSAGE,bp,p)
+#define i2d_CMP_PKIMESSAGE_bio(bp,o) ASN1_i2d_bio_of(CMP_PKIMESSAGE,i2d_CMP_PKIMESSAGE,bp,o)
+#define d2i_CMP_PROTECTEDPART_bio(bp,p) ASN1_d2i_bio_of(CMP_PROTECTEDPART,CMP_PROTECTEDPART_new,d2i_CMP_PROTECTEDPART,bp,p)
+#define i2d_CMP_PROTECTEDPART_bio(bp,o) ASN1_i2d_bio_of(CMP_PROTECTEDPART,i2d_CMP_PROTECTEDPART,bp,o)
+
+/* 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.
+ */
+void ERR_load_CMP_strings(void);
+
+/* Error codes for the CMP functions. */
+
+/* Function codes. */
+#define CMP_F_CMP_CALC_PROTECTION_PBMAC			 100
+#define CMP_F_CMP_CALC_PROTECTION_SIG			 101
+#define CMP_F_CMP_CERTCONF_NEW				 102
+#define CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1		 103
+#define CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE	 104
+#define CMP_F_CMP_CERTREPMESSAGE_PKIFAILUREINFOSTRING_GET0 105
+#define CMP_F_CMP_CERTREPMESSAGE_PKIFAILUREINFO_GET0	 106
+#define CMP_F_CMP_CERTREPMESSAGE_PKISTATUSSTRING_GET0	 107
+#define CMP_F_CMP_CERTREPMESSAGE_PKISTATUS_GET		 108
+#define CMP_F_CMP_CERTSTATUS_SET_CERTHASH		 109
+#define CMP_F_CMP_CR_NEW				 110
+#define CMP_F_CMP_CTX_CAPUBS_GET1			 111
+#define CMP_F_CMP_CTX_CAPUBS_NUM			 112
+#define CMP_F_CMP_CTX_CAPUBS_POP			 113
+#define CMP_F_CMP_CTX_CREATE				 114
+#define CMP_F_CMP_CTX_EXTRACERTSIN_GET1			 115
+#define CMP_F_CMP_CTX_EXTRACERTSIN_NUM			 116
+#define CMP_F_CMP_CTX_EXTRACERTSIN_POP			 117
+#define CMP_F_CMP_CTX_EXTRACERTSOUT_NUM			 118
+#define CMP_F_CMP_CTX_EXTRACERTSOUT_PUSH1		 119
+#define CMP_F_CMP_CTX_INIT				 120
+#define CMP_F_CMP_CTX_SET0_NEWPKEY			 121
+#define CMP_F_CMP_CTX_SET0_PKEY				 122
+#define CMP_F_CMP_CTX_SET1_CAPUBS			 123
+#define CMP_F_CMP_CTX_SET1_CLCERT			 124
+#define CMP_F_CMP_CTX_SET1_EXTRACERTSIN			 125
+#define CMP_F_CMP_CTX_SET1_EXTRACERTSOUT		 126
+#define CMP_F_CMP_CTX_SET1_NEWCLCERT			 127
+#define CMP_F_CMP_CTX_SET1_NEWPKEY			 128
+#define CMP_F_CMP_CTX_SET1_OLDCLCERT			 129
+#define CMP_F_CMP_CTX_SET1_PKEY				 130
+#define CMP_F_CMP_CTX_SET1_POPOMETHOD			 131
+#define CMP_F_CMP_CTX_SET1_PROXYNAME			 132
+#define CMP_F_CMP_CTX_SET1_PROXYPORT			 133
+#define CMP_F_CMP_CTX_SET1_RECIPIENT			 134
+#define CMP_F_CMP_CTX_SET1_RECIPNONCE			 135
+#define CMP_F_CMP_CTX_SET1_REFERENCEVALUE		 136
+#define CMP_F_CMP_CTX_SET1_REGTOKEN			 137
+#define CMP_F_CMP_CTX_SET1_SECRETVALUE			 138
+#define CMP_F_CMP_CTX_SET1_SERVERNAME			 139
+#define CMP_F_CMP_CTX_SET1_SERVERPATH			 140
+#define CMP_F_CMP_CTX_SET1_SERVERPORT			 141
+#define CMP_F_CMP_CTX_SET1_SOURCEADDRESS		 142
+#define CMP_F_CMP_CTX_SET1_SRVCERT			 143
+#define CMP_F_CMP_CTX_SET1_SUBJECTNAME			 144
+#define CMP_F_CMP_CTX_SET1_TRANSACTIONID		 145
+#define CMP_F_CMP_CTX_SET_HTTPTIMEOUT			 146
+#define CMP_F_CMP_CTX_SUBJECTALTNAME_PUSH1		 147
+#define CMP_F_CMP_DOCERTIFICATEREQUESTSEQ		 148
+#define CMP_F_CMP_DOGENERALMESSAGESEQ			 149
+#define CMP_F_CMP_DOINITIALREQUESTSEQ			 150
+#define CMP_F_CMP_DOKEYUPDATEREQUESTSEQ			 151
+#define CMP_F_CMP_DOREVOCATIONREQUESTSEQ		 152
+#define CMP_F_CMP_GENM_NEW				 153
+#define CMP_F_CMP_IR_NEW				 154
+#define CMP_F_CMP_KUR_NEW				 155
+#define CMP_F_CMP_NEW_HTTP_BIO				 156
+#define CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM		 157
+#define CMP_F_CMP_PKIMESSAGE_PARSE_ERROR_MSG		 158
+#define CMP_F_CMP_PKIMESSAGE_PROTECT			 159
+#define CMP_F_CMP_PKISTATUSINFO_PKISTATUS_GET_STRING	 160
+#define CMP_F_CMP_POLLREQ_NEW				 161
+#define CMP_F_CMP_REVREPCONTENT_PKISTATUS_GET		 162
+#define CMP_F_CMP_RR_NEW				 163
+#define CMP_F_CMP_VALIDATE_CERT_PATH			 164
+#define CMP_F_CMP_VALIDATE_MSG				 165
+#define CMP_F_CMP_VERIFY_SIGNATURE			 166
+#define CMP_F_PARSE_HTTP_LINE1				 167
+#define CMP_F_PKEY_DUP					 168
+#define CMP_F_POLLFORRESPONSE				 169
+#define CMP_F_SENDCERTCONF				 170
+
+/* Reason codes. */
+#define CMP_R_ALGORITHM_NOT_SUPPORTED			 100
+#define CMP_R_CERTIFICATE_NOT_FOUND			 101
+#define CMP_R_CP_NOT_RECEIVED				 102
+#define CMP_R_CURL_ERROR				 103
+#define CMP_R_ERROR_CALCULATING_PROTECTION		 104
+#define CMP_R_ERROR_CREATING_CERTCONF			 105
+#define CMP_R_ERROR_CREATING_CR				 106
+#define CMP_R_ERROR_CREATING_GENM			 107
+#define CMP_R_ERROR_CREATING_IR				 108
+#define CMP_R_ERROR_CREATING_KUR			 109
+#define CMP_R_ERROR_CREATING_POLLREQ			 110
+#define CMP_R_ERROR_CREATING_RR				 111
+#define CMP_R_ERROR_DECODING_CERTIFICATE		 112
+#define CMP_R_ERROR_DECRYPTING_CERTIFICATE		 113
+#define CMP_R_ERROR_DECRYPTING_ENCCERT			 114
+#define CMP_R_ERROR_DECRYPTING_KEY			 115
+#define CMP_R_ERROR_DECRYPTING_SYMMETRIC_KEY		 116
+#define CMP_R_ERROR_NONCES_DO_NOT_MATCH			 117
+#define CMP_R_ERROR_PARSING_ERROR_MESSAGE		 118
+#define CMP_R_ERROR_PARSING_PKISTATUS			 119
+#define CMP_R_ERROR_PROTECTING_MESSAGE			 120
+#define CMP_R_ERROR_REQID_NOT_FOUND			 121
+#define CMP_R_ERROR_SETTING_CERTHASH			 122
+#define CMP_R_ERROR_VALIDATING_PROTECTION		 123
+#define CMP_R_FAILED_TO_DECODE_PKIMESSAGE		 124
+#define CMP_R_GENP_NOT_RECEIVED				 125
+#define CMP_R_INVALID_ARGS				 126
+#define CMP_R_INVALID_CONTENT_TYPE			 127
+#define CMP_R_INVALID_CONTEXT				 128
+#define CMP_R_INVALID_KEY				 129
+#define CMP_R_INVALID_PARAMETERS			 130
+#define CMP_R_IP_NOT_RECEIVED				 131
+#define CMP_R_KUP_NOT_RECEIVED				 132
+#define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION	 133
+#define CMP_R_NO_CERTIFICATE_RECEIVED			 134
+#define CMP_R_NO_SECRET_VALUE_GIVEN_FOR_PBMAC		 135
+#define CMP_R_NO_TRUSTED_CERTIFICATES_SET		 136
+#define CMP_R_NO_VALID_SRVCERT_FOUND			 137
+#define CMP_R_NULL_ARGUMENT				 138
+#define CMP_R_PKIBODY_ERROR				 139
+#define CMP_R_PKICONF_NOT_RECEIVED			 140
+#define CMP_R_POLLREP_NOT_RECEIVED			 141
+#define CMP_R_REQUEST_REJECTED_BY_CA			 142
+#define CMP_R_RP_NOT_RECEIVED				 143
+#define CMP_R_SERVER_NOT_REACHABLE			 144
+#define CMP_R_SERVER_RESPONSE_ERROR			 145
+#define CMP_R_SERVER_RESPONSE_PARSE_ERROR		 146
+#define CMP_R_UNABLE_TO_CREATE_CONTEXT			 147
+#define CMP_R_UNEXPECTED_PKISTATUS			 148
+#define CMP_R_UNKNOWN_ALGORITHM_ID			 149
+#define CMP_R_UNKNOWN_CERTTYPE				 150
+#define CMP_R_UNKNOWN_PKISTATUS				 151
+#define CMP_R_UNSUPPORTED_ALGORITHM			 152
+#define CMP_R_UNSUPPORTED_CIPHER			 153
+#define CMP_R_UNSUPPORTED_KEY_TYPE			 154
+#define CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC	 155
+#define CMP_R_WRONG_ALGORITHM_OID			 156
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_asn.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_asn.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_asn.c	(revision 764)
@@ -0,0 +1,361 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* cmp_asn.c
+ * OpenSSL ASN.1 definitions for CMP (RFC 4210)
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/cmp.h>
+
+ASN1_SEQUENCE(CMP_REVANNCONTENT) = {
+	/* CMP_PKISTATUS is effectively ASN1_INTEGER so it is used directly */
+	ASN1_SIMPLE(CMP_REVANNCONTENT, status, ASN1_INTEGER),
+	ASN1_SIMPLE(CMP_REVANNCONTENT, certId, CRMF_CERTID),
+	ASN1_SIMPLE(CMP_REVANNCONTENT, willBeRevokedAt, ASN1_GENERALIZEDTIME),
+	ASN1_SIMPLE(CMP_REVANNCONTENT, badSinceDate, ASN1_GENERALIZEDTIME),
+	ASN1_OPT(CMP_REVANNCONTENT,    crlDetails, X509_EXTENSIONS)
+} ASN1_SEQUENCE_END(CMP_REVANNCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_REVANNCONTENT)
+
+
+ASN1_SEQUENCE(CMP_CHALLENGE) = {
+	ASN1_OPT(CMP_CHALLENGE, owf, X509_ALGOR),
+	ASN1_SIMPLE(CMP_CHALLENGE, whitness, ASN1_OCTET_STRING),
+	ASN1_SIMPLE(CMP_CHALLENGE, challenge, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMP_CHALLENGE)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CHALLENGE)
+
+
+ASN1_ITEM_TEMPLATE(CMP_POPODECKEYCHALLCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_POPODECKEYCHALLCONTENT, CMP_CHALLENGE)
+ASN1_ITEM_TEMPLATE_END(CMP_POPODECKEYCHALLCONTENT)
+
+
+ASN1_ITEM_TEMPLATE(CMP_POPODECKEYRESPCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_POPODECKEYRESPCONTENT, ASN1_INTEGER)
+ASN1_ITEM_TEMPLATE_END(CMP_POPODECKEYRESPCONTENT)
+
+
+ASN1_SEQUENCE(CMP_CAKEYUPDANNCONTENT) = {
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ASN1_SIMPLE(CMP_CAKEYUPDANNCONTENT, oldWithNew, X509),
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ASN1_SIMPLE(CMP_CAKEYUPDANNCONTENT, newWithOld, X509),
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ASN1_SIMPLE(CMP_CAKEYUPDANNCONTENT, newWithNew, X509)
+} ASN1_SEQUENCE_END(CMP_CAKEYUPDANNCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CAKEYUPDANNCONTENT)
+
+
+ASN1_SEQUENCE(CMP_ERRORMSGCONTENT) = {
+	ASN1_SIMPLE(CMP_ERRORMSGCONTENT, pKIStatusInfo, CMP_PKISTATUSINFO),
+	ASN1_OPT(CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER),
+	/* CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING so it is used directly */
+	ASN1_SEQUENCE_OF_OPT(CMP_ERRORMSGCONTENT, errorDetails, ASN1_UTF8STRING)
+} ASN1_SEQUENCE_END(CMP_ERRORMSGCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_ERRORMSGCONTENT)
+
+ASN1_ADB_TEMPLATE(infotypeandvalue_default) = ASN1_OPT(CMP_INFOTYPEANDVALUE, infoValue.other, ASN1_ANY);
+ASN1_ADB(CMP_INFOTYPEANDVALUE) = {
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ADB_ENTRY(NID_id_it_caProtEncCert,	 ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.caProtEncCert,	 X509)),
+	ADB_ENTRY(NID_id_it_signKeyPairTypes,ASN1_SEQUENCE_OF_OPT(CMP_INFOTYPEANDVALUE, infoValue.signKeyPairTypes,  X509_ALGOR)),
+	ADB_ENTRY(NID_id_it_encKeyPairTypes, ASN1_SEQUENCE_OF_OPT(CMP_INFOTYPEANDVALUE, infoValue.encKeyPairTypes,	 X509_ALGOR)),
+	ADB_ENTRY(NID_id_it_preferredSymmAlg,ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.preferredSymmAlg,  X509_ALGOR)),
+	ADB_ENTRY(NID_id_it_caKeyUpdateInfo, ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.caKeyUpdateInfo,	 CMP_CAKEYUPDANNCONTENT)),
+	ADB_ENTRY(NID_id_it_currentCRL,		 ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.currentCRL,		 X509_CRL)),
+	ADB_ENTRY(NID_id_it_unsupportedOIDs, ASN1_SEQUENCE_OF_OPT(CMP_INFOTYPEANDVALUE, infoValue.unsupportedOIDs,	 ASN1_OBJECT)),
+	ADB_ENTRY(NID_id_it_keyPairParamReq, ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.keyPairParamReq,	 ASN1_OBJECT)),
+	ADB_ENTRY(NID_id_it_keyPairParamRep, ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.keyPairParamRep,	 X509_ALGOR)),
+	ADB_ENTRY(NID_id_it_revPassphrase,	 ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.revPassphrase,	 CRMF_ENCRYPTEDVALUE)),
+	ADB_ENTRY(NID_id_it_implicitConfirm, ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.implicitConfirm,	 ASN1_NULL)),
+	ADB_ENTRY(NID_id_it_confirmWaitTime, ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.confirmWaitTime,	 ASN1_GENERALIZEDTIME)),
+	ADB_ENTRY(NID_id_it_origPKIMessage,  ASN1_OPT(CMP_INFOTYPEANDVALUE,				infoValue.origPKIMessage,	 CMP_PKIMESSAGES)),
+	ADB_ENTRY(NID_id_it_suppLangTags,	 ASN1_SEQUENCE_OF_OPT(CMP_INFOTYPEANDVALUE, infoValue.suppLangTagsValue, ASN1_UTF8STRING)),
+#if 0
+	/* this is what CL likes for KUR - not in the RFC */
+	ADB_ENTRY(NID_id_smime_aa_signingCertificate, ASN1_SET_OF(CMP_INFOTYPEANDVALUE, infoValue.signingCertificate, ESS_SIGNING_CERT))
+	/* this is how signingCertificate should probably be actually used */
+	/* ADB_ENTRY(NID_id_smime_aa_signingCertificate, ASN1_SIMPLE(CMP_INFOTYPEANDVALUE, infoValue.signingCertificate, ESS_SIGNING_CERT)) */
+#endif 
+} ASN1_ADB_END(CMP_INFOTYPEANDVALUE, 0, infoType, 0, &infotypeandvalue_default_tt, NULL);
+
+
+ASN1_SEQUENCE(CMP_INFOTYPEANDVALUE) = {
+	ASN1_SIMPLE(CMP_INFOTYPEANDVALUE, infoType, ASN1_OBJECT),
+	ASN1_ADB_OBJECT(CMP_INFOTYPEANDVALUE)
+} ASN1_SEQUENCE_END(CMP_INFOTYPEANDVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_INFOTYPEANDVALUE)
+
+
+ASN1_CHOICE(CMP_CERTORENCCERT) = {
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ASN1_EXP(CMP_CERTORENCCERT, value.certificate, X509, 0),
+	ASN1_EXP(CMP_CERTORENCCERT, value.encryptedCert, CRMF_ENCRYPTEDVALUE, 1),
+} ASN1_CHOICE_END(CMP_CERTORENCCERT)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CERTORENCCERT)
+
+
+ASN1_SEQUENCE(CMP_CERTIFIEDKEYPAIR) = {
+	ASN1_SIMPLE(CMP_CERTIFIEDKEYPAIR, certOrEncCert, CMP_CERTORENCCERT),
+	ASN1_EXP_OPT(CMP_CERTIFIEDKEYPAIR, privateKey, CRMF_ENCRYPTEDVALUE,0),
+	ASN1_EXP_OPT(CMP_CERTIFIEDKEYPAIR, failInfo, CRMF_PKIPUBLICATIONINFO,1)
+} ASN1_SEQUENCE_END(CMP_CERTIFIEDKEYPAIR)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CERTIFIEDKEYPAIR)
+
+
+ASN1_SEQUENCE(CMP_REVDETAILS) = {
+	ASN1_SIMPLE(CMP_REVDETAILS, certDetails, CRMF_CERTTEMPLATE),
+	ASN1_OPT(CMP_REVDETAILS, crlEntryDetails, X509_EXTENSIONS)
+} ASN1_SEQUENCE_END(CMP_REVDETAILS)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_REVDETAILS)
+
+
+ASN1_ITEM_TEMPLATE(CMP_REVREQCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_REVREQCONTENT, CMP_REVDETAILS)
+ASN1_ITEM_TEMPLATE_END(CMP_REVREQCONTENT)
+
+
+ASN1_SEQUENCE(CMP_REVREPCONTENT) = {
+	ASN1_SEQUENCE_OF(CMP_REVREPCONTENT, status, CMP_PKISTATUSINFO),
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_REVREPCONTENT, certId, CRMF_CERTID, 0),
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_REVREPCONTENT, crls,	X509, 1)
+} ASN1_SEQUENCE_END(CMP_REVREPCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_REVREPCONTENT)
+
+
+ASN1_SEQUENCE(CMP_KEYRECREPCONTENT) = {
+	ASN1_SIMPLE(CMP_KEYRECREPCONTENT, status, CMP_PKISTATUSINFO),
+	ASN1_EXP_OPT(CMP_KEYRECREPCONTENT, newSigCert, X509, 0),
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_KEYRECREPCONTENT, caCerts, X509, 1),
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_KEYRECREPCONTENT, keyPairHist, X509, 2)
+} ASN1_SEQUENCE_END(CMP_KEYRECREPCONTENT)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_KEYRECREPCONTENT)
+
+
+ASN1_ITEM_TEMPLATE(CMP_PKISTATUS) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_UNIVERSAL, 0, status, ASN1_INTEGER)
+ASN1_ITEM_TEMPLATE_END(CMP_PKISTATUS)
+
+ASN1_SEQUENCE(CMP_PKISTATUSINFO) = {
+	ASN1_SIMPLE(CMP_PKISTATUSINFO, status, CMP_PKISTATUS),
+	/* CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING so it is used directly */
+	ASN1_SEQUENCE_OF_OPT(CMP_PKISTATUSINFO, statusString, ASN1_UTF8STRING),
+	/* CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so it is used directly */
+	ASN1_OPT(CMP_PKISTATUSINFO, failInfo, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(CMP_PKISTATUSINFO)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_PKISTATUSINFO)
+
+
+ASN1_SEQUENCE(CMP_CERTSTATUS) = {
+	ASN1_SIMPLE(CMP_CERTSTATUS, certHash, ASN1_OCTET_STRING),
+	ASN1_SIMPLE(CMP_CERTSTATUS, certReqId, ASN1_INTEGER),
+	ASN1_OPT(CMP_CERTSTATUS, statusInfo, CMP_PKISTATUSINFO)
+} ASN1_SEQUENCE_END(CMP_CERTSTATUS)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CERTSTATUS)
+
+/* the PKCS10 structures are untested */
+ASN1_SEQUENCE(PKCS10_ATTRIBUTE) = {
+	ASN1_SIMPLE(PKCS10_ATTRIBUTE, id, ASN1_OBJECT),
+	ASN1_SEQUENCE_OF(PKCS10_ATTRIBUTE, values, ASN1_ANY),
+} ASN1_SEQUENCE_END(PKCS10_ATTRIBUTE)
+IMPLEMENT_ASN1_FUNCTIONS(PKCS10_ATTRIBUTE)
+
+ASN1_SEQUENCE(PKCS10_CERTIFICATIONREQUESTINFO) = {
+	ASN1_SIMPLE(PKCS10_CERTIFICATIONREQUESTINFO, version, ASN1_INTEGER),
+	ASN1_SIMPLE(PKCS10_CERTIFICATIONREQUESTINFO, subject, X509_NAME),
+	ASN1_SIMPLE(PKCS10_CERTIFICATIONREQUESTINFO, subjectPKInfo, X509_PUBKEY),
+	ASN1_IMP_SET_OF(PKCS10_CERTIFICATIONREQUESTINFO, attributes, PKCS10_ATTRIBUTE, 0),
+} ASN1_SEQUENCE_END(PKCS10_CERTIFICATIONREQUESTINFO)
+IMPLEMENT_ASN1_FUNCTIONS(PKCS10_CERTIFICATIONREQUESTINFO)
+
+ASN1_SEQUENCE(PKCS10_CERTIFICATIONREQUEST) = {
+	ASN1_SIMPLE(PKCS10_CERTIFICATIONREQUEST, certificationRequestInfo, PKCS10_CERTIFICATIONREQUESTINFO),
+	ASN1_SIMPLE(PKCS10_CERTIFICATIONREQUEST, signatureAlgorithm, X509_ALGOR),
+	ASN1_SIMPLE(PKCS10_CERTIFICATIONREQUEST, signature, ASN1_BIT_STRING),
+} ASN1_SEQUENCE_END(PKCS10_CERTIFICATIONREQUEST)
+IMPLEMENT_ASN1_FUNCTIONS(PKCS10_CERTIFICATIONREQUEST)
+
+ASN1_ITEM_TEMPLATE(CMP_CERTCONFIRMCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_CERTCONFIRMCONTENT, CMP_CERTSTATUS)
+ASN1_ITEM_TEMPLATE_END(CMP_CERTCONFIRMCONTENT)
+
+ASN1_SEQUENCE(CMP_CERTRESPONSE) = {
+	ASN1_SIMPLE(CMP_CERTRESPONSE, certReqId, ASN1_INTEGER),
+	ASN1_SIMPLE(CMP_CERTRESPONSE, status, CMP_PKISTATUSINFO),
+	ASN1_OPT(CMP_CERTRESPONSE, certifiedKeyPair, CMP_CERTIFIEDKEYPAIR),
+	ASN1_OPT(CMP_CERTRESPONSE, rspInfo, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMP_CERTRESPONSE)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CERTRESPONSE)
+
+ASN1_SEQUENCE(CMP_POLLREQ) = {
+	ASN1_SIMPLE(CMP_POLLREQ, certReqId, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(CMP_POLLREQ)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_POLLREQ)
+
+ASN1_ITEM_TEMPLATE(CMP_POLLREQCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_POLLREQCONTENT, CMP_POLLREQ)
+ASN1_ITEM_TEMPLATE_END(CMP_POLLREQCONTENT)
+
+ASN1_SEQUENCE(CMP_POLLREP) = {
+	ASN1_SIMPLE(CMP_POLLREP, certReqId, ASN1_INTEGER),
+	ASN1_SIMPLE(CMP_POLLREP, checkAfter, ASN1_INTEGER),
+	ASN1_SEQUENCE_OF_OPT(CMP_POLLREP, reason, ASN1_UTF8STRING),
+} ASN1_SEQUENCE_END(CMP_POLLREP)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_POLLREP)
+
+ASN1_ITEM_TEMPLATE(CMP_POLLREPCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_POLLREPCONTENT, CMP_POLLREP)
+ASN1_ITEM_TEMPLATE_END(CMP_POLLREPCONTENT)
+
+ASN1_SEQUENCE(CMP_CERTREPMESSAGE) = {
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_CERTREPMESSAGE, caPubs, X509,1),
+	ASN1_SEQUENCE_OF(CMP_CERTREPMESSAGE, response, CMP_CERTRESPONSE)
+} ASN1_SEQUENCE_END(CMP_CERTREPMESSAGE)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CERTREPMESSAGE)
+
+ASN1_ITEM_TEMPLATE(CMP_GENMSGCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_GENMSGCONTENT, CMP_INFOTYPEANDVALUE)
+ASN1_ITEM_TEMPLATE_END(CMP_GENMSGCONTENT)
+
+ASN1_ITEM_TEMPLATE(CMP_GENREPCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_GENREPCONTENT, CMP_INFOTYPEANDVALUE)
+ASN1_ITEM_TEMPLATE_END(CMP_GENREPCONTENT)
+
+ASN1_ITEM_TEMPLATE(CMP_CRLANNCONTENT) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_CRLANNCONTENT, X509_CRL)
+ASN1_ITEM_TEMPLATE_END(CMP_CRLANNCONTENT)
+
+ASN1_CHOICE(CMP_PKIBODY) = {
+	ASN1_EXP(CMP_PKIBODY, value.ir, CRMF_CERTREQMESSAGES, 0),
+	ASN1_EXP(CMP_PKIBODY, value.ip, CMP_CERTREPMESSAGE, 1),
+	ASN1_EXP(CMP_PKIBODY, value.cr, CRMF_CERTREQMESSAGES, 2),
+	ASN1_EXP(CMP_PKIBODY, value.cp, CMP_CERTREPMESSAGE, 3),
+	ASN1_EXP(CMP_PKIBODY, value.p10cr, PKCS10_CERTIFICATIONREQUEST, 4),
+	ASN1_EXP(CMP_PKIBODY, value.popdecc, CMP_POPODECKEYCHALLCONTENT, 5),
+	ASN1_EXP(CMP_PKIBODY, value.popdecr, CMP_POPODECKEYRESPCONTENT, 6),
+	ASN1_EXP(CMP_PKIBODY, value.kur, CRMF_CERTREQMESSAGES, 7),
+	ASN1_EXP(CMP_PKIBODY, value.kup, CMP_CERTREPMESSAGE, 8),
+	ASN1_EXP(CMP_PKIBODY, value.krr, CRMF_CERTREQMESSAGES, 9),
+	ASN1_EXP(CMP_PKIBODY, value.krp, CMP_KEYRECREPCONTENT, 10),
+	ASN1_EXP(CMP_PKIBODY, value.rr, CMP_REVREQCONTENT, 11),
+	ASN1_EXP(CMP_PKIBODY, value.rp, CMP_REVREPCONTENT, 12),
+	ASN1_EXP(CMP_PKIBODY, value.ccr, CRMF_CERTREQMESSAGES, 13),
+	ASN1_EXP(CMP_PKIBODY, value.ccp, CMP_CERTREPMESSAGE, 14),
+	ASN1_EXP(CMP_PKIBODY, value.ckuann, CMP_CAKEYUPDANNCONTENT, 15),
+	ASN1_EXP(CMP_PKIBODY, value.cann, X509, 16),
+	ASN1_EXP(CMP_PKIBODY, value.rann, CMP_REVANNCONTENT, 17),
+	ASN1_EXP(CMP_PKIBODY, value.crlann, CMP_CRLANNCONTENT, 18),
+	ASN1_EXP(CMP_PKIBODY, value.pkiconf, ASN1_ANY, 19),
+	ASN1_EXP(CMP_PKIBODY, value.nested, CMP_PKIMESSAGES, 20),
+	ASN1_EXP(CMP_PKIBODY, value.genm, CMP_GENMSGCONTENT, 21),
+	ASN1_EXP(CMP_PKIBODY, value.genp, CMP_GENREPCONTENT, 22),
+	ASN1_EXP(CMP_PKIBODY, value.error, CMP_ERRORMSGCONTENT, 23),
+	ASN1_EXP(CMP_PKIBODY, value.certConf, CMP_CERTCONFIRMCONTENT, 24),
+	ASN1_EXP(CMP_PKIBODY, value.pollReq, CMP_POLLREQCONTENT, 25),
+	ASN1_EXP(CMP_PKIBODY, value.pollRep, CMP_POLLREPCONTENT, 26),
+} ASN1_CHOICE_END(CMP_PKIBODY)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_PKIBODY)
+
+ASN1_SEQUENCE(CMP_PKIHEADER) = {
+	ASN1_SIMPLE(CMP_PKIHEADER, pvno, ASN1_INTEGER),
+	ASN1_SIMPLE(CMP_PKIHEADER, sender, GENERAL_NAME),
+	ASN1_SIMPLE(CMP_PKIHEADER, recipient, GENERAL_NAME),
+	ASN1_EXP_OPT(CMP_PKIHEADER, messageTime, ASN1_GENERALIZEDTIME,0),
+	ASN1_EXP_OPT(CMP_PKIHEADER, protectionAlg, X509_ALGOR,1),
+	ASN1_EXP_OPT(CMP_PKIHEADER, senderKID, ASN1_OCTET_STRING,2),
+	ASN1_EXP_OPT(CMP_PKIHEADER, recipKID, ASN1_OCTET_STRING,3),
+	ASN1_EXP_OPT(CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING,4),
+	ASN1_EXP_OPT(CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING,5),
+	ASN1_EXP_OPT(CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING,6),
+	/* CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING so it is used directly */
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_PKIHEADER, freeText, ASN1_UTF8STRING,7),
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_PKIHEADER, generalInfo, CMP_INFOTYPEANDVALUE,8)
+} ASN1_SEQUENCE_END(CMP_PKIHEADER)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_PKIHEADER)
+
+ASN1_SEQUENCE(CMP_PROTECTEDPART) = {
+	ASN1_SIMPLE(CMP_PKIMESSAGE, header, CMP_PKIHEADER),
+	ASN1_SIMPLE(CMP_PKIMESSAGE, body, CMP_PKIBODY)
+} ASN1_SEQUENCE_END(CMP_PROTECTEDPART)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_PROTECTEDPART);
+
+ASN1_SEQUENCE(CMP_PKIMESSAGE) = {
+	ASN1_SIMPLE(CMP_PKIMESSAGE, header, CMP_PKIHEADER),
+	ASN1_SIMPLE(CMP_PKIMESSAGE, body, CMP_PKIBODY),
+	ASN1_EXP_OPT(CMP_PKIMESSAGE, protection, ASN1_BIT_STRING,0),
+	/* CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+	ASN1_EXP_SEQUENCE_OF_OPT(CMP_PKIMESSAGE, extraCerts, X509,1)
+} ASN1_SEQUENCE_END(CMP_PKIMESSAGE)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_PKIMESSAGE)
+
+ASN1_ITEM_TEMPLATE(CMP_PKIMESSAGES) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CMP_PKIMESSAGES, CMP_PKIMESSAGE)
+ASN1_ITEM_TEMPLATE_END(CMP_PKIMESSAGES)
+
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_ctx.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_ctx.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_ctx.c	(revision 764)
@@ -0,0 +1,1240 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* crypto/cmp/cmp_ctx.c
+ * CMP (RFC 4210) context functions for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <string.h>
+#include <dirent.h>
+
+/* NAMING
+ * The 0 version uses the supplied structure pointer directly in the parent and
+ * it will be freed up when the parent is freed. In the above example crl would
+ * be freed but rev would not.
+ *
+ * The 1 function uses a copy of the supplied structure pointer (or in some
+ * cases increases its link count) in the parent and so both (x and obj above)
+ * should be freed up.
+ */
+
+/* OpenSSL ASN.1 macros in CTX struct */
+ASN1_SEQUENCE(CMP_CTX) = {
+	ASN1_OPT(CMP_CTX, referenceValue, ASN1_OCTET_STRING),
+	ASN1_OPT(CMP_CTX, secretValue, ASN1_OCTET_STRING),
+	ASN1_OPT(CMP_CTX, regToken, ASN1_UTF8STRING),
+	ASN1_OPT(CMP_CTX, srvCert, X509),
+	ASN1_OPT(CMP_CTX, clCert, X509),
+	ASN1_OPT(CMP_CTX, oldClCert, X509),
+	ASN1_OPT(CMP_CTX, subjectName, X509_NAME),
+	ASN1_SEQUENCE_OF_OPT(CMP_CTX, subjectAltNames, GENERAL_NAME),
+	ASN1_OPT(CMP_CTX, recipient, X509_NAME),
+	ASN1_SEQUENCE_OF_OPT(CMP_CTX, caPubs, X509),
+	ASN1_SEQUENCE_OF_OPT(CMP_CTX, extraCertsOut, X509),
+	ASN1_SEQUENCE_OF_OPT(CMP_CTX, extraCertsIn, X509),
+	ASN1_OPT(CMP_CTX, newClCert, X509),
+	ASN1_OPT(CMP_CTX, transactionID, ASN1_OCTET_STRING),
+	ASN1_OPT(CMP_CTX, recipNonce, ASN1_OCTET_STRING),
+	ASN1_OPT(CMP_CTX, validatedSrvCert, X509),
+	ASN1_SEQUENCE_OF_OPT(CMP_CTX, lastStatusString, ASN1_UTF8STRING),
+	ASN1_SEQUENCE_OF_OPT(CMP_CTX, policies, POLICYINFO),
+} ASN1_SEQUENCE_END(CMP_CTX)
+IMPLEMENT_ASN1_FUNCTIONS(CMP_CTX)
+
+/* ############################################################################ *
+ * Returns a duplicate of the given stack of X509 certificates.
+ * ############################################################################ */
+static STACK_OF(X509)* X509_stack_dup(const STACK_OF(X509)* stack)
+	{
+	STACK_OF(X509) *newsk = NULL;
+	int i;
+
+	if (!stack) goto err;
+	if (!(newsk = sk_X509_new_null())) goto err;
+
+	for (i = 0; i < sk_X509_num(stack); i++)
+		sk_X509_push(newsk, X509_dup(sk_X509_value(stack, i)));
+
+	return newsk;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * Creates a copy of the given EVP_PKEY.
+ * TODO: is there really no other already existing way to do that?
+ * returns ptr to duplicated EVP_PKEY on success, NULL on error
+ * ############################################################################ */
+static EVP_PKEY *pkey_dup(const EVP_PKEY *pkey)
+	{
+	EVP_PKEY *pkeyDup = EVP_PKEY_new();
+	if (!pkeyDup) goto err;
+	
+	switch (pkey->type)
+		{
+#ifndef OPENSSL_NO_RSA
+		case EVP_PKEY_RSA:
+			EVP_PKEY_set1_RSA(pkeyDup, pkey->pkey.rsa);
+			break;
+#endif
+#ifndef OPENSSL_NO_DSA
+		case EVP_PKEY_DSA: 
+			EVP_PKEY_set1_DSA(pkeyDup, pkey->pkey.dsa);
+			break;
+#endif
+#ifndef OPENSSL_NO_DH
+		case EVP_PKEY_DH:
+			EVP_PKEY_set1_DH(pkeyDup, pkey->pkey.dh);
+			break;
+#endif
+#ifndef OPENSSL_NO_EC
+		case EVP_PKEY_EC:
+			EVP_PKEY_set1_EC_KEY(pkeyDup, pkey->pkey.ec);
+			break;
+#endif
+		default: 
+			CMPerr(CMP_F_PKEY_DUP, CMP_R_UNSUPPORTED_KEY_TYPE);
+			goto err;
+		}
+	return pkeyDup;
+
+err:
+	if (pkeyDup) EVP_PKEY_free(pkeyDup);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Set certificate store containing root CA certs.
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_CTX_set0_trustedStore( CMP_CTX *ctx, X509_STORE *store)
+	{
+	if (!store) return 0;
+	if (ctx->trusted_store)
+		X509_STORE_free(ctx->trusted_store);
+	ctx->trusted_store = store;
+	return 1;
+	}
+
+/* ############################################################################ *
+ * Set certificate store containing intermediate certificates (for building
+ * our own cert chain to send in extraCerts).
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_CTX_set0_untrustedStore( CMP_CTX *ctx, X509_STORE *store)
+	{
+	if (!store) return 0;
+	if (ctx->untrusted_store)
+		X509_STORE_free(ctx->untrusted_store);
+	ctx->untrusted_store = store;
+	return 1;
+	}
+
+/* ################################################################ *
+ * Allocates and initializes a CMP_CTX context structure with some 
+ * default values.
+ * OpenSSL ASN.1 types are initialized to NULL by the call to CMP_CTX_new()
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_init( CMP_CTX *ctx)
+	{
+	if (!ctx)
+		{
+		CMPerr(CMP_F_CMP_CTX_INIT, CMP_R_INVALID_CONTEXT);
+		goto err;
+		}
+
+	/* all other elements are initialized through ASN1 macros */
+	ctx->pkey			 = NULL;
+	ctx->newPkey		 = NULL;
+	ctx->serverName		 = NULL;
+	/* serverPath has to be an empty sting if not set since it is not mandatory */
+	/* this will be freed by CMP_CTX_delete() */
+	ctx->serverPath		 = OPENSSL_malloc(1);
+	ctx->serverPath[0]	 = 0;
+	ctx->serverPort		 = 0;
+	ctx->proxyName		 = NULL;
+	ctx->proxyPort		 = 0;
+	ctx->implicitConfirm = 0;
+	ctx->popoMethod		 = CRMF_POPO_SIGNATURE;
+	ctx->HttpTimeOut	 = 2*60;
+	ctx->setSubjectAltNameCritical = 0;
+	ctx->sourceAddress   = NULL;
+	ctx->lastHTTPCode    = 0;
+	ctx->useTLS    = 0;
+
+	ctx->error_cb = NULL;
+	ctx->debug_cb = (cmp_logfn_t) puts;
+	ctx->certConf_cb = NULL;
+
+	ctx->trusted_store	 = X509_STORE_new();
+	ctx->untrusted_store = X509_STORE_new();
+
+	ctx->maxPollTime = 0;
+
+	ctx->lastPKIStatus = 0;
+	ctx->failInfoCode = 0;
+
+	ctx->permitTAInExtraCertsForIR = 0;
+	ctx->validatedSrvCert = NULL;
+
+	/* initialize OpenSSL */
+	OpenSSL_add_all_ciphers();
+	OpenSSL_add_all_digests();
+	ERR_load_crypto_strings();
+
+	return 1;
+
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * frees CMP_CTX variables allocated in CMP_CTX_init and calls CMP_CTX_free
+ * ################################################################ */
+void CMP_CTX_delete(CMP_CTX *ctx)
+	{
+	if (!ctx) return;
+	if (ctx->pkey) EVP_PKEY_free(ctx->pkey);
+	if (ctx->newPkey) EVP_PKEY_free(ctx->newPkey);
+
+	if (ctx->serverName) OPENSSL_free(ctx->serverName);
+	if (ctx->serverPath) OPENSSL_free(ctx->serverPath);
+	if (ctx->proxyName) OPENSSL_free(ctx->proxyName);
+	if (ctx->trusted_store) X509_STORE_free(ctx->trusted_store);
+	if (ctx->untrusted_store) X509_STORE_free(ctx->untrusted_store);
+
+	CMP_CTX_free(ctx);
+	}
+
+/* ################################################################ *
+ * creates and initializes a CMP_CTX structure
+ * returns pointer to created CMP_CTX on success, NULL on error
+ * ################################################################ */
+CMP_CTX *CMP_CTX_create(void)
+	{
+	CMP_CTX *ctx=NULL;
+
+	if( !(ctx = CMP_CTX_new())) goto err;
+	if( !(CMP_CTX_init(ctx))) goto err;
+
+	return ctx;
+err:
+	CMPerr(CMP_F_CMP_CTX_CREATE, CMP_R_UNABLE_TO_CREATE_CONTEXT);
+	if (ctx) CMP_CTX_free(ctx);
+	return NULL;
+	}
+
+/* ################################################################ *
+ * returns latest failInfoCode, -1 on error
+ * ################################################################ */
+unsigned long CMP_CTX_get_failInfoCode( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	return ctx->failInfoCode;
+err:
+	return -1;
+	}
+
+/* ################################################################ *
+ * returns the statusString from the last CertRepMessage, NULL on error
+ * ################################################################ */
+STACK_OF(ASN1_UTF8STRING) *CMP_CTX_statusString_get( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	return ctx->lastStatusString;
+err:
+	return NULL;
+	}
+
+/* ################################################################ *
+ * Set callback function for checking if the cert is ok or should
+ * it be rejected.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set_certConf_callback( CMP_CTX *ctx, cmp_certConfFn_t cb)
+	{
+	if (!ctx) goto err;
+	ctx->certConf_cb = cb;
+	return 1;
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set a callback function which will receive debug messages.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set_error_callback( CMP_CTX *ctx, cmp_logfn_t cb)
+	{
+	if (!ctx) goto err;
+	ctx->error_cb = cb;
+	return 1;
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set a callback function which will receive error messages.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set_debug_callback( CMP_CTX *ctx, cmp_logfn_t cb)
+	{
+	if (!ctx) goto err;
+	ctx->debug_cb = cb;
+	return 1; 
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the reference value to be used for identification (i.e. the 
+ * username) when using PBMAC.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_referenceValue( CMP_CTX *ctx, const unsigned char *ref, size_t len)
+	{
+	if (!ctx || !ref)
+		{
+		CMPerr(CMP_F_CMP_CTX_SET1_REFERENCEVALUE, CMP_R_INVALID_PARAMETERS);
+		goto err;
+		}
+
+	if (!ctx->referenceValue)
+		ctx->referenceValue = ASN1_OCTET_STRING_new();
+
+	return (ASN1_OCTET_STRING_set(ctx->referenceValue, ref, len));
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the password to be used for protecting messages with PBMAC
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_secretValue( CMP_CTX *ctx, const unsigned char *sec, const size_t len)
+	{
+	if (!ctx) goto err;
+	if (!sec) goto err;
+
+	if (!ctx->secretValue)
+		ctx->secretValue = ASN1_OCTET_STRING_new();
+
+	return (ASN1_OCTET_STRING_set(ctx->secretValue, sec, len));
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SECRETVALUE, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the registration token value (the password for EJBCA for example)
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_regToken( CMP_CTX *ctx, const char *regtoken, const size_t len)
+	{
+	if (!ctx) goto err;
+	if (!regtoken) goto err;
+
+	if (!ctx->regToken)
+		ctx->regToken = ASN1_UTF8STRING_new();
+
+	return (ASN1_STRING_set(ctx->regToken, regtoken, len));
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_REGTOKEN, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Returns the stack of certificates received in a response message.
+ * The stack is duplicated so the caller must handle freeing it!
+ * returns pointer to created stack on success, NULL on error
+ * ################################################################ */
+STACK_OF(X509)* CMP_CTX_extraCertsIn_get1( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->extraCertsIn) return 0;
+	return X509_stack_dup(ctx->extraCertsIn);
+err:
+	CMPerr(CMP_F_CMP_CTX_EXTRACERTSIN_GET1, CMP_R_NULL_ARGUMENT);
+	return NULL;
+	}
+
+/* ################################################################ *
+ * Pops and returns one certificate from the received extraCerts field
+ * returns pointer certificate on success, NULL on error
+ * ################################################################ */
+X509 *CMP_CTX_extraCertsIn_pop( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->extraCertsIn) return NULL;
+	return sk_X509_pop(ctx->extraCertsIn);
+err:
+	CMPerr(CMP_F_CMP_CTX_EXTRACERTSIN_POP, CMP_R_NULL_ARGUMENT);
+	return NULL;
+	}
+
+/* ################################################################ *
+ * Returns the number of extraCerts received in a response, 0 on error
+ * TODO: should that return something else on error?
+ * ################################################################ */
+int CMP_CTX_extraCertsIn_num( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->extraCertsIn) return 0;
+	return sk_X509_num(ctx->extraCertsIn);
+err:
+	CMPerr(CMP_F_CMP_CTX_EXTRACERTSIN_NUM, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Copies the given stack of inbound X509 certificates to extraCertsIn of
+ * the CMP_CTX structure so that they may be retrieved later.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_extraCertsIn( CMP_CTX *ctx, const STACK_OF(X509) *extraCertsIn)
+	{
+	if (!ctx) goto err;
+	if (!extraCertsIn) goto err;
+
+	/* if there are already inbound extraCerts on the stack delete them */
+	if (ctx->extraCertsIn)
+		{
+		sk_X509_pop_free(ctx->extraCertsIn, X509_free);
+		ctx->extraCertsIn = NULL;
+		}
+
+	if (!(ctx->extraCertsIn = X509_stack_dup(extraCertsIn))) goto err;
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_EXTRACERTSIN, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Duplicate and push the given X509 certificate to the stack of 
+ * outbound certificates to send in the extraCerts field.
+ * returns number of pushed certificates on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_extraCertsOut_push1( CMP_CTX *ctx, const X509 *val)
+	{
+	if (!ctx) goto err;
+	if (!ctx->extraCertsOut && !(ctx->extraCertsOut = sk_X509_new_null())) return 0;
+	return sk_X509_push(ctx->extraCertsOut, X509_dup((X509*)val));
+err:
+	CMPerr(CMP_F_CMP_CTX_EXTRACERTSOUT_PUSH1, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * load all the intermediate certificates from the given stack into untrusted_store
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_CTX_loadUntrustedStack(CMP_CTX *ctx, STACK_OF(X509) *stack)
+	{
+	int i;
+	EVP_PKEY *pubkey;
+	X509 *cert;
+	
+	if (!stack) goto err;
+	if (!ctx->untrusted_store && !( ctx->untrusted_store = X509_STORE_new() ))
+		goto err;
+
+	for (i = 0; i < sk_X509_num(stack); i++)
+		{
+		if(!(cert = sk_X509_value(stack, i))) goto err;
+		if(!(pubkey = X509_get_pubkey(cert))) continue;
+
+		/* don't add self-signed certs here */
+		if (!X509_verify(cert, pubkey))
+			X509_STORE_add_cert(ctx->untrusted_store, cert);  /* don't fail as adding existing certificate to store would cause error */
+		EVP_PKEY_free(pubkey);
+		}
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * Return the number of certificates we have in the outbound 
+ * extraCerts stack, 0 on error
+ * TODO: should that return something else on error?
+ * ################################################################ */
+int CMP_CTX_extraCertsOut_num( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->extraCertsOut) return 0;
+	return sk_X509_num(ctx->extraCertsOut);
+err:
+	CMPerr(CMP_F_CMP_CTX_EXTRACERTSOUT_NUM, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Duplicate and set the given stack as the new stack of X509 
+ * certificates to send out in the extraCerts field.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_extraCertsOut( CMP_CTX *ctx, const STACK_OF(X509) *extraCertsOut)
+	{
+	if (!ctx) goto err;
+	if (!extraCertsOut) goto err;
+
+	if (ctx->extraCertsOut)
+		{
+		sk_X509_pop_free(ctx->extraCertsOut, X509_free);
+		ctx->extraCertsOut = NULL;
+		}
+
+	if (!(ctx->extraCertsOut = X509_stack_dup(extraCertsOut))) goto err;
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_EXTRACERTSOUT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * CMP_CTX_policyOID_push1() adds the certificate policy OID given by the
+ * string to the X509_EXTENSIONS of the certificate template we are
+ * requesting.
+ * ################################################################ */
+int CMP_CTX_policyOID_push1( CMP_CTX *ctx, const char *policyOID)
+{
+	if (!ctx || !policyOID) goto err;
+
+	if (!ctx->policies)
+		ctx->policies = CERTIFICATEPOLICIES_new();
+	if (!ctx->policies) goto err;
+
+	POLICYINFO *pol = POLICYINFO_new();
+	if (!pol) goto err;
+
+	pol->policyid = OBJ_txt2obj(policyOID, 1);
+	sk_POLICYINFO_push(ctx->policies, pol);
+
+	return 1;
+
+err:
+	return 0;
+}
+
+
+/* ################################################################ *
+ * Returns a duplicate of the stack received X509 certificates that
+ * were received in the caPubs field of the last response message.
+ * returns NULL on error
+ * ################################################################ */
+STACK_OF(X509)* CMP_CTX_caPubs_get1( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->caPubs) return NULL;
+	return X509_stack_dup(ctx->caPubs);
+err:
+	CMPerr(CMP_F_CMP_CTX_CAPUBS_GET1, CMP_R_NULL_ARGUMENT);
+	return NULL;
+	}
+
+/* ################################################################ *
+ * Pop one certificate out of the list of certificates received in
+ * the caPubs field, returns NULL on errror or when the stack is empty
+ * ################################################################ */
+X509 *CMP_CTX_caPubs_pop( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->caPubs) return NULL;
+	return sk_X509_pop(ctx->caPubs);
+err:
+	CMPerr(CMP_F_CMP_CTX_CAPUBS_POP, CMP_R_NULL_ARGUMENT);
+	return NULL;
+	}
+
+/* ################################################################ *
+ * Return the number of certificates received in the caPubs field
+ * of the last response message, 0 on error
+ * TODO: should that return something else on error?
+ * ################################################################ */
+int CMP_CTX_caPubs_num( CMP_CTX *ctx)
+	{
+	if (!ctx) goto err;
+	if (!ctx->caPubs) return 0;
+	return sk_X509_num(ctx->caPubs);
+err:
+	CMPerr(CMP_F_CMP_CTX_CAPUBS_NUM, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Duplciate and copy the given stack of certificates to the given 
+ * CMP_CTX structure so that they may be retrieved later.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_caPubs( CMP_CTX *ctx, const STACK_OF(X509) *caPubs)
+	{
+	if (!ctx) goto err;
+	if (!caPubs) goto err;
+
+	if (ctx->caPubs)
+		{
+		sk_X509_pop_free(ctx->caPubs, X509_free);
+		ctx->caPubs = NULL;
+		}
+
+	if (!(ctx->caPubs = X509_stack_dup(caPubs))) goto err;
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_CAPUBS, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Sets the CA certificate that is to be used for verifying response
+ * messages. Pointer is not consumed.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_srvCert( CMP_CTX *ctx, const X509 *cert)
+	{
+	if (!ctx) goto err;
+	if (!cert) goto err;
+
+	if (ctx->srvCert)
+		{
+		X509_free(ctx->srvCert);
+		ctx->srvCert = NULL;
+		}
+
+	if (!(ctx->srvCert = X509_dup( (X509*)cert))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SRVCERT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the X509 name of the recipient. Set in the PKIHeader.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_recipient( CMP_CTX *ctx, const X509_NAME *name)
+	{
+	if (!ctx) goto err;
+	if (!name) goto err;
+
+	if (ctx->recipient)
+		{
+		X509_NAME_free(ctx->recipient);
+		ctx->recipient = NULL;
+		}
+
+	if (!(ctx->recipient = X509_NAME_dup( (X509_NAME*)name))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_RECIPIENT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the subject name that will be placed in the certificate 
+ * request. This will be the subject name on the received certificate.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_subjectName( CMP_CTX *ctx, const X509_NAME *name)
+	{
+	if (!ctx) goto err;
+	if (!name) goto err;
+
+	if (ctx->subjectName)
+		{
+		X509_NAME_free(ctx->subjectName);
+		ctx->subjectName = NULL;
+		}
+
+	if (!(ctx->subjectName = X509_NAME_dup( (X509_NAME*)name))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SUBJECTNAME, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Push a GENERAL_NAME structure that will be added to the CRMF
+ * request's extensions field to request subject alternative names.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_subjectAltName_push1( CMP_CTX *ctx, const GENERAL_NAME *name)
+	{
+	if (!ctx) goto err;
+	if (!name) goto err;
+
+	if (!ctx->subjectAltNames && !(ctx->subjectAltNames = sk_GENERAL_NAME_new_null()))
+		goto err;
+
+	if (!sk_GENERAL_NAME_push(ctx->subjectAltNames, GENERAL_NAME_dup( (GENERAL_NAME*)name))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SUBJECTALTNAME_PUSH1, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set our own client certificate, used for example in KUR and when
+ * doing the IR with existing certificate.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_clCert( CMP_CTX *ctx, const X509 *cert)
+	{
+	if (!ctx) goto err;
+	if (!cert) goto err;
+
+	if (ctx->clCert)
+		{
+		X509_free(ctx->clCert);
+		ctx->clCert = NULL;
+		}
+
+	if (!(ctx->clCert = X509_dup( (X509*)cert))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_CLCERT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the old certificate that we are updating in KUR
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_oldClCert( CMP_CTX *ctx, const X509 *cert)
+	{
+	if (!ctx) goto err;
+	if (!cert) goto err;
+
+	if (ctx->oldClCert)
+		{
+		X509_free(ctx->oldClCert);
+		ctx->oldClCert = NULL;
+		}
+
+	if (!(ctx->oldClCert = X509_dup( (X509*)cert))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_OLDCLCERT, CMP_R_NULL_ARGUMENT);
+ 	return 0;
+ 	}
+
+/* ################################################################ *
+ * sets the (newly received in IP/KUP/CP) client Certificate to the context
+ * returns 1 on success, 0 on error
+ * TODO: this only permits for one client cert to be received...
+ * ################################################################ */
+int CMP_CTX_set1_newClCert( CMP_CTX *ctx, const X509 *cert)
+	{
+	if (!ctx) goto err;
+	if (!cert) goto err;
+
+	if (ctx->newClCert)
+		{
+		X509_free(ctx->newClCert);
+		ctx->newClCert = NULL;
+		}
+
+	if (!(ctx->newClCert = X509_dup( (X509*)cert))) goto err;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_NEWCLCERT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the client's private key. This creates a duplicate of the key
+ * so the given pointer is not used directly.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_pkey( CMP_CTX *ctx, const EVP_PKEY *pkey)
+	{
+	EVP_PKEY *pkeyDup = NULL;
+	if (!ctx) goto err;
+	if (!pkey) goto err;
+
+	pkeyDup = pkey_dup(pkey);;
+	return CMP_CTX_set0_pkey(ctx, pkeyDup);
+
+err:
+	if (pkeyDup) EVP_PKEY_free(pkeyDup);
+	CMPerr(CMP_F_CMP_CTX_SET1_PKEY, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the client's current private key. NOTE: this version uses
+ * the given pointer directly!
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set0_pkey( CMP_CTX *ctx, const EVP_PKEY *pkey)
+	{
+	if (!ctx) goto err;
+	if (!pkey) goto err;
+
+	if (ctx->pkey)
+		{
+		EVP_PKEY_free(ctx->pkey);
+		ctx->pkey = NULL;
+		}
+
+	ctx->pkey = (EVP_PKEY*) pkey;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET0_PKEY, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set new key pa8r. Used for example when doing Key Update.
+ * The key is duplicated so the original pointer is not directly used.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_newPkey( CMP_CTX *ctx, const EVP_PKEY *pkey)
+	{
+	EVP_PKEY *pkeyDup = NULL;
+	if (!ctx) goto err;
+	if (!pkey) goto err;
+
+	pkeyDup = pkey_dup(pkey);
+	return CMP_CTX_set0_newPkey(ctx, pkeyDup);
+
+err:
+	if (pkeyDup) EVP_PKEY_free(pkeyDup);
+	CMPerr(CMP_F_CMP_CTX_SET1_NEWPKEY, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set new key pair. Used e.g. when doing Key Update.
+ * NOTE: uses the pointer directly!
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set0_newPkey( CMP_CTX *ctx, const EVP_PKEY *pkey)
+	{
+	if (!ctx) goto err;
+	if (!pkey) goto err;
+
+	if (ctx->newPkey)
+		{
+		EVP_PKEY_free(ctx->newPkey);
+		ctx->newPkey = NULL;
+		}
+
+	ctx->newPkey = (EVP_PKEY*) pkey;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET0_NEWPKEY, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * sets the given transactionID to the context
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_transactionID( CMP_CTX *ctx, const ASN1_OCTET_STRING *id)
+	{
+	if (!ctx) goto err;
+	if (!id) goto err;
+
+	if (ctx->transactionID)
+		{
+		ASN1_OCTET_STRING_free(ctx->transactionID);
+		ctx->transactionID = NULL;
+		}
+
+	if (!(ctx->transactionID = ASN1_OCTET_STRING_dup((ASN1_OCTET_STRING *)id)))
+		return 0;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_TRANSACTIONID, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+
+/* ################################################################ *
+ * sets the given nonce to be used for the recipNonce in the next message to be
+ * created.
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_recipNonce( CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce)
+	{
+	if (!ctx) goto err;
+	if (!nonce) goto err;
+
+	if (ctx->recipNonce)
+		{
+		ASN1_OCTET_STRING_free(ctx->recipNonce);
+		ctx->recipNonce = NULL;
+		}
+
+	if (!(ctx->recipNonce = ASN1_OCTET_STRING_dup((ASN1_OCTET_STRING *)nonce))) 
+		return 0;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_RECIPNONCE, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the hostname of the (HTTP) proxy server to use for all connections
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_proxyName( CMP_CTX *ctx, const char *name)
+	{
+	if (!ctx) goto err;
+	if (!name) goto err;
+
+	if (ctx->proxyName)
+		{
+		OPENSSL_free( ctx->proxyName);
+		ctx->proxyName = NULL;
+		}
+
+	ctx->proxyName = OPENSSL_malloc( strlen(name)+1);
+	strcpy( ctx->proxyName, name);
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_PROXYNAME, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the (HTTP) hostname of the CA server
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_serverName( CMP_CTX *ctx, const char *name)
+	{
+	if (!ctx) goto err;
+	if (!name) goto err;
+
+	if (ctx->serverName)
+		{
+		OPENSSL_free( ctx->serverName);
+		ctx->serverName = NULL;
+		}
+
+	ctx->serverName = OPENSSL_malloc( strlen(name)+1);
+	strcpy( ctx->serverName, name);
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SERVERNAME, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Sets the proof of possession method to be used when creating a certTemplate
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_popoMethod( CMP_CTX *ctx, int method)
+	{
+	if (!ctx) goto err;
+
+	ctx->popoMethod = method;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_POPOMETHOD, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * sets the timeout for the (HTTP) transport mechanism
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set_HttpTimeOut( CMP_CTX *ctx, int time)
+	{
+	if (!ctx) goto err;
+
+	ctx->HttpTimeOut = time;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET_HTTPTIMEOUT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * sets the (HTTP) proxy port to be used
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_proxyPort( CMP_CTX *ctx, int port)
+	{
+	if (!ctx) goto err;
+
+	ctx->proxyPort = port;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_PROXYPORT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * sets the (HTTP) server port to be used
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_sourceAddress( CMP_CTX *ctx, const char *ip)
+	{
+	if (!ctx) goto err;
+	if (!ip) goto err;
+
+	if (ctx->sourceAddress)
+		{
+		OPENSSL_free( ctx->sourceAddress);
+		ctx->sourceAddress = NULL;
+		}
+
+	ctx->sourceAddress = OPENSSL_malloc( strlen(ip)+1);
+	strcpy( ctx->sourceAddress, ip);
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SOURCEADDRESS, CMP_R_NULL_ARGUMENT);
+	return 0;	
+	}
+
+/* ################################################################ *
+ * sets the (HTTP) server port to be used
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_serverPort( CMP_CTX *ctx, int port)
+	{
+	if (!ctx) goto err;
+
+	ctx->serverPort = port;
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SERVERPORT, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Sets the HTTP path to be used on the server (e.g "pkix/")
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set1_serverPath( CMP_CTX *ctx, const char *path)
+	{
+	if (!ctx) goto err;
+
+	if (ctx->serverPath)
+		{
+		/* clear the old value */
+		OPENSSL_free( ctx->serverPath);
+		ctx->serverPath = 0;
+		}
+
+	if (!path)
+		{
+		/* clear the serverPath */
+		ctx->serverPath = OPENSSL_malloc(1);
+		ctx->serverPath[0] = 0;
+		return 1;
+		}
+
+	ctx->serverPath = OPENSSL_malloc( strlen(path)+1);
+	strcpy( ctx->serverPath, path);
+
+	return 1;
+err:
+	CMPerr(CMP_F_CMP_CTX_SET1_SERVERPATH, CMP_R_NULL_ARGUMENT);
+	return 0;
+	}
+
+/* ################################################################ *
+ * Set the failinfo error code bits in CMP_CTX based on the given
+ * CMP_PKIFAILUREINFO structure
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set_failInfoCode(CMP_CTX *ctx, CMP_PKIFAILUREINFO *failInfo)
+	{
+	int i;
+
+	if (!ctx || !failInfo) return 0;
+
+	ctx->failInfoCode = 0;
+	for ( i=0; i <= CMP_PKIFAILUREINFO_MAX; i++)
+		if( ASN1_BIT_STRING_get_bit(failInfo, i))
+			ctx->failInfoCode |= 1 << i;
+
+	return 1;
+	}
+
+/* ################################################################ *
+ * Get the failinfo error code bits in CMP_CTX
+ * returns bitstring in ulong on success, -1 on error
+ * ################################################################ */
+unsigned long CMP_CTX_failInfoCode_get(CMP_CTX *ctx)
+	{
+	if (!ctx) return -1;
+	return ctx->failInfoCode;
+	}
+
+#if 0
+/* ################################################################ *
+ * pushes a given 0-terminated character string to ctx->freeText
+ * this is inteded for human consumption
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_push_freeText( CMP_CTX *ctx, const char *text)
+	{
+	ASN1_UTF8STRING *utf8string=NULL;
+
+	if (!ctx) goto err;
+	if (!text) goto err;
+
+	if (!ctx->freeText)
+		if( !(ctx->freeText = sk_ASN1_UTF8STRING_new())) goto err;
+
+	if( !(utf8string = ASN1_UTF8STRING_new())) goto err;
+	ASN1_UTF8STRING_set(utf8string, text, strlen(text));
+	if( !(sk_ASN1_UTF8STRING_push(ctx->freeText, utf8string) goto err;
+	return 1;/
+err:
+	CMP_printf( "ERROR in FILE: %s, LINE: %d\n", __FILE__, __LINE__);
+	if (utf8string) ASN1_UTF8STRING_free(utf8string);
+	return 0;
+	}
+#endif
+
+/* ################################################################ * 
+ * sets a BOOLEAN option of the context to the "val" arg
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+int CMP_CTX_set_option( CMP_CTX *ctx, const int opt, const int val)
+	{
+	if (!ctx) goto err;
+
+	switch (opt)
+		{
+		case CMP_CTX_OPT_IMPLICITCONFIRM:
+			ctx->implicitConfirm = val;
+			break;
+		case CMP_CTX_OPT_POPMETHOD:
+			ctx->popoMethod = val;
+			break;
+		case CMP_CTX_OPT_MAXPOLLTIME:
+			ctx->maxPollTime = val;
+			break;
+		case CMP_CTX_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
+			ctx->permitTAInExtraCertsForIR = val;
+			break;
+		case CMP_CTX_SET_SUBJECTALTNAME_CRITICAL:
+			ctx->setSubjectAltNameCritical = val;
+			break;
+		case CMP_CTX_USE_TLS:
+			ctx->useTLS = val;
+			break;
+		default:
+			goto err;
+		}
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ################################################################ *
+ * Function used for printing debug messages if debug_cb is set
+ * (CMP_CTX_INIT defaults to puts)
+ * ################################################################ */
+void CMP_printf(const CMP_CTX *ctx, const char *fmt, ...)
+	{
+#ifdef CMP_DEBUG
+	va_list arg_ptr;
+	char buf[1024];
+
+	if (!ctx || !ctx->debug_cb) return;
+
+	va_start(arg_ptr, fmt);
+
+	vsnprintf(buf, sizeof(buf), fmt, arg_ptr);
+	ctx->debug_cb(buf);
+
+	va_end(arg_ptr);
+#endif
+	}
+
+/* ############################################################################ *
+ * This callback is used to print out the OpenSSL error queue via'
+ * ERR_print_errors_cb() to the ctx->error_cb() function set by the user
+ * returns always 1
+ * ############################################################################ */
+int CMP_CTX_error_callback(const char *str, size_t len, void *u)
+	{
+	CMP_CTX *ctx = (CMP_CTX*) u;
+	if (ctx && ctx->error_cb) 
+		ctx->error_cb(str);
+	return 1;
+	}
+
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_err.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_err.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_err.c	(revision 764)
@@ -0,0 +1,221 @@
+/* crypto/cmp/cmp_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2011 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at 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 <openssl/cmp.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_CMP,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_CMP,0,reason)
+
+static ERR_STRING_DATA CMP_str_functs[]=
+	{
+{ERR_FUNC(CMP_F_CMP_CALC_PROTECTION_PBMAC),	"CMP_calc_protection_pbmac"},
+{ERR_FUNC(CMP_F_CMP_CALC_PROTECTION_SIG),	"CMP_CALC_PROTECTION_SIG"},
+{ERR_FUNC(CMP_F_CMP_CERTCONF_NEW),	"CMP_certConf_new"},
+{ERR_FUNC(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1),	"CMP_CERTREPMESSAGE_ENCCERT_GET1"},
+{ERR_FUNC(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE),	"CMP_CERTREPMESSAGE_get_certificate"},
+{ERR_FUNC(CMP_F_CMP_CERTREPMESSAGE_PKIFAILUREINFOSTRING_GET0),	"CMP_CERTREPMESSAGE_PKIFailureInfoString_get0"},
+{ERR_FUNC(CMP_F_CMP_CERTREPMESSAGE_PKIFAILUREINFO_GET0),	"CMP_CERTREPMESSAGE_PKIFailureInfo_get0"},
+{ERR_FUNC(CMP_F_CMP_CERTREPMESSAGE_PKISTATUSSTRING_GET0),	"CMP_CERTREPMESSAGE_PKIStatusString_get0"},
+{ERR_FUNC(CMP_F_CMP_CERTREPMESSAGE_PKISTATUS_GET),	"CMP_CERTREPMESSAGE_PKIStatus_get"},
+{ERR_FUNC(CMP_F_CMP_CERTSTATUS_SET_CERTHASH),	"CMP_CERTSTATUS_set_certHash"},
+{ERR_FUNC(CMP_F_CMP_CR_NEW),	"CMP_cr_new"},
+{ERR_FUNC(CMP_F_CMP_CTX_CAPUBS_GET1),	"CMP_CTX_caPubs_get1"},
+{ERR_FUNC(CMP_F_CMP_CTX_CAPUBS_NUM),	"CMP_CTX_caPubs_num"},
+{ERR_FUNC(CMP_F_CMP_CTX_CAPUBS_POP),	"CMP_CTX_caPubs_pop"},
+{ERR_FUNC(CMP_F_CMP_CTX_CREATE),	"CMP_CTX_create"},
+{ERR_FUNC(CMP_F_CMP_CTX_EXTRACERTSIN_GET1),	"CMP_CTX_extraCertsIn_get1"},
+{ERR_FUNC(CMP_F_CMP_CTX_EXTRACERTSIN_NUM),	"CMP_CTX_extraCertsIn_num"},
+{ERR_FUNC(CMP_F_CMP_CTX_EXTRACERTSIN_POP),	"CMP_CTX_extraCertsIn_pop"},
+{ERR_FUNC(CMP_F_CMP_CTX_EXTRACERTSOUT_NUM),	"CMP_CTX_extraCertsOut_num"},
+{ERR_FUNC(CMP_F_CMP_CTX_EXTRACERTSOUT_PUSH1),	"CMP_CTX_extraCertsOut_push1"},
+{ERR_FUNC(CMP_F_CMP_CTX_INIT),	"CMP_CTX_init"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET0_NEWPKEY),	"CMP_CTX_set0_newPkey"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET0_PKEY),	"CMP_CTX_set0_pkey"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_CAPUBS),	"CMP_CTX_set1_caPubs"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_CLCERT),	"CMP_CTX_set1_clCert"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_EXTRACERTSIN),	"CMP_CTX_set1_extraCertsIn"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_EXTRACERTSOUT),	"CMP_CTX_set1_extraCertsOut"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_NEWCLCERT),	"CMP_CTX_set1_newClCert"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_NEWPKEY),	"CMP_CTX_set1_newPkey"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_OLDCLCERT),	"CMP_CTX_SET1_OLDCLCERT"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_PKEY),	"CMP_CTX_set1_pkey"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_POPOMETHOD),	"CMP_CTX_set1_popoMethod"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_PROXYNAME),	"CMP_CTX_set1_proxyName"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_PROXYPORT),	"CMP_CTX_set1_proxyPort"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_RECIPIENT),	"CMP_CTX_set1_recipient"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_RECIPNONCE),	"CMP_CTX_set1_recipNonce"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_REFERENCEVALUE),	"CMP_CTX_set1_referenceValue"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_REGTOKEN),	"CMP_CTX_set1_regToken"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SECRETVALUE),	"CMP_CTX_set1_secretValue"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SERVERNAME),	"CMP_CTX_set1_serverName"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SERVERPATH),	"CMP_CTX_set1_serverPath"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SERVERPORT),	"CMP_CTX_set1_serverPort"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SOURCEADDRESS),	"CMP_CTX_set1_sourceAddress"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SRVCERT),	"CMP_CTX_set1_srvCert"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_SUBJECTNAME),	"CMP_CTX_set1_subjectName"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET1_TRANSACTIONID),	"CMP_CTX_set1_transactionID"},
+{ERR_FUNC(CMP_F_CMP_CTX_SET_HTTPTIMEOUT),	"CMP_CTX_SET_HTTPTIMEOUT"},
+{ERR_FUNC(CMP_F_CMP_CTX_SUBJECTALTNAME_PUSH1),	"CMP_CTX_subjectAltName_push1"},
+{ERR_FUNC(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ),	"CMP_doCertificateRequestSeq"},
+{ERR_FUNC(CMP_F_CMP_DOGENERALMESSAGESEQ),	"CMP_doGeneralMessageSeq"},
+{ERR_FUNC(CMP_F_CMP_DOINITIALREQUESTSEQ),	"CMP_doInitialRequestSeq"},
+{ERR_FUNC(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ),	"CMP_doKeyUpdateRequestSeq"},
+{ERR_FUNC(CMP_F_CMP_DOREVOCATIONREQUESTSEQ),	"CMP_doRevocationRequestSeq"},
+{ERR_FUNC(CMP_F_CMP_GENM_NEW),	"CMP_genm_new"},
+{ERR_FUNC(CMP_F_CMP_IR_NEW),	"CMP_ir_new"},
+{ERR_FUNC(CMP_F_CMP_KUR_NEW),	"CMP_kur_new"},
+{ERR_FUNC(CMP_F_CMP_NEW_HTTP_BIO),	"CMP_NEW_HTTP_BIO"},
+{ERR_FUNC(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM),	"CMP_PKIMESSAGE_http_perform"},
+{ERR_FUNC(CMP_F_CMP_PKIMESSAGE_PARSE_ERROR_MSG),	"CMP_PKIMESSAGE_parse_error_msg"},
+{ERR_FUNC(CMP_F_CMP_PKIMESSAGE_PROTECT),	"CMP_PKIMESSAGE_protect"},
+{ERR_FUNC(CMP_F_CMP_PKISTATUSINFO_PKISTATUS_GET_STRING),	"CMP_PKISTATUSINFO_PKISTATUS_GET_STRING"},
+{ERR_FUNC(CMP_F_CMP_POLLREQ_NEW),	"CMP_pollReq_new"},
+{ERR_FUNC(CMP_F_CMP_REVREPCONTENT_PKISTATUS_GET),	"CMP_REVREPCONTENT_PKIStatus_get"},
+{ERR_FUNC(CMP_F_CMP_RR_NEW),	"CMP_rr_new"},
+{ERR_FUNC(CMP_F_CMP_VALIDATE_CERT_PATH),	"CMP_VALIDATE_CERT_PATH"},
+{ERR_FUNC(CMP_F_CMP_VALIDATE_MSG),	"CMP_validate_msg"},
+{ERR_FUNC(CMP_F_CMP_VERIFY_SIGNATURE),	"CMP_VERIFY_SIGNATURE"},
+{ERR_FUNC(CMP_F_PARSE_HTTP_LINE1),	"PARSE_HTTP_LINE1"},
+{ERR_FUNC(CMP_F_PKEY_DUP),	"PKEY_DUP"},
+{ERR_FUNC(CMP_F_POLLFORRESPONSE),	"POLLFORRESPONSE"},
+{ERR_FUNC(CMP_F_SENDCERTCONF),	"SENDCERTCONF"},
+{0,NULL}
+	};
+
+static ERR_STRING_DATA CMP_str_reasons[]=
+	{
+{ERR_REASON(CMP_R_ALGORITHM_NOT_SUPPORTED),"algorithm not supported"},
+{ERR_REASON(CMP_R_CERTIFICATE_NOT_FOUND) ,"certificate not found"},
+{ERR_REASON(CMP_R_CP_NOT_RECEIVED)       ,"cp not received"},
+{ERR_REASON(CMP_R_CURL_ERROR)            ,"curl error"},
+{ERR_REASON(CMP_R_ERROR_CALCULATING_PROTECTION),"error calculating protection"},
+{ERR_REASON(CMP_R_ERROR_CREATING_CERTCONF),"error creating certconf"},
+{ERR_REASON(CMP_R_ERROR_CREATING_CR)     ,"error creating cr"},
+{ERR_REASON(CMP_R_ERROR_CREATING_GENM)   ,"error creating genm"},
+{ERR_REASON(CMP_R_ERROR_CREATING_IR)     ,"error creating ir"},
+{ERR_REASON(CMP_R_ERROR_CREATING_KUR)    ,"error creating kur"},
+{ERR_REASON(CMP_R_ERROR_CREATING_POLLREQ),"error creating pollreq"},
+{ERR_REASON(CMP_R_ERROR_CREATING_RR)     ,"error creating rr"},
+{ERR_REASON(CMP_R_ERROR_DECODING_CERTIFICATE),"error decoding certificate"},
+{ERR_REASON(CMP_R_ERROR_DECRYPTING_CERTIFICATE),"error decrypting certificate"},
+{ERR_REASON(CMP_R_ERROR_DECRYPTING_ENCCERT),"error decrypting enccert"},
+{ERR_REASON(CMP_R_ERROR_DECRYPTING_KEY)  ,"error decrypting key"},
+{ERR_REASON(CMP_R_ERROR_DECRYPTING_SYMMETRIC_KEY),"error decrypting symmetric key"},
+{ERR_REASON(CMP_R_ERROR_NONCES_DO_NOT_MATCH),"error nonces do not match"},
+{ERR_REASON(CMP_R_ERROR_PARSING_ERROR_MESSAGE),"error parsing error message"},
+{ERR_REASON(CMP_R_ERROR_PARSING_PKISTATUS),"error parsing pkistatus"},
+{ERR_REASON(CMP_R_ERROR_PROTECTING_MESSAGE),"error protecting message"},
+{ERR_REASON(CMP_R_ERROR_REQID_NOT_FOUND) ,"error reqid not found"},
+{ERR_REASON(CMP_R_ERROR_SETTING_CERTHASH),"error setting certhash"},
+{ERR_REASON(CMP_R_ERROR_VALIDATING_PROTECTION),"error validating protection"},
+{ERR_REASON(CMP_R_FAILED_TO_DECODE_PKIMESSAGE),"failed to decode pkimessage"},
+{ERR_REASON(CMP_R_GENP_NOT_RECEIVED)     ,"genp not received"},
+{ERR_REASON(CMP_R_INVALID_ARGS)          ,"invalid args"},
+{ERR_REASON(CMP_R_INVALID_CONTENT_TYPE)  ,"invalid content type"},
+{ERR_REASON(CMP_R_INVALID_CONTEXT)       ,"invalid context"},
+{ERR_REASON(CMP_R_INVALID_KEY)           ,"invalid key"},
+{ERR_REASON(CMP_R_INVALID_PARAMETERS)    ,"invalid parameters"},
+{ERR_REASON(CMP_R_IP_NOT_RECEIVED)       ,"ip not received"},
+{ERR_REASON(CMP_R_KUP_NOT_RECEIVED)      ,"kup not received"},
+{ERR_REASON(CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),"missing key input for creating protection"},
+{ERR_REASON(CMP_R_NO_CERTIFICATE_RECEIVED),"no certificate received"},
+{ERR_REASON(CMP_R_NO_SECRET_VALUE_GIVEN_FOR_PBMAC),"no secret value given for pbmac"},
+{ERR_REASON(CMP_R_NO_TRUSTED_CERTIFICATES_SET),"no trusted certificates set"},
+{ERR_REASON(CMP_R_NO_VALID_SRVCERT_FOUND),"no valid srvcert found"},
+{ERR_REASON(CMP_R_NULL_ARGUMENT)         ,"null argument"},
+{ERR_REASON(CMP_R_PKIBODY_ERROR)         ,"pkibody error"},
+{ERR_REASON(CMP_R_PKICONF_NOT_RECEIVED)  ,"pkiconf not received"},
+{ERR_REASON(CMP_R_POLLREP_NOT_RECEIVED)  ,"pollrep not received"},
+{ERR_REASON(CMP_R_REQUEST_REJECTED_BY_CA),"request rejected by ca"},
+{ERR_REASON(CMP_R_RP_NOT_RECEIVED)       ,"rp not received"},
+{ERR_REASON(CMP_R_SERVER_NOT_REACHABLE)  ,"server not reachable"},
+{ERR_REASON(CMP_R_SERVER_RESPONSE_ERROR) ,"server response error"},
+{ERR_REASON(CMP_R_SERVER_RESPONSE_PARSE_ERROR),"server response parse error"},
+{ERR_REASON(CMP_R_UNABLE_TO_CREATE_CONTEXT),"unable to create context"},
+{ERR_REASON(CMP_R_UNEXPECTED_PKISTATUS)  ,"unexpected pkistatus"},
+{ERR_REASON(CMP_R_UNKNOWN_ALGORITHM_ID)  ,"unknown algorithm id"},
+{ERR_REASON(CMP_R_UNKNOWN_CERTTYPE)      ,"unknown certtype"},
+{ERR_REASON(CMP_R_UNKNOWN_PKISTATUS)     ,"unknown pkistatus"},
+{ERR_REASON(CMP_R_UNSUPPORTED_ALGORITHM) ,"unsupported algorithm"},
+{ERR_REASON(CMP_R_UNSUPPORTED_CIPHER)    ,"unsupported cipher"},
+{ERR_REASON(CMP_R_UNSUPPORTED_KEY_TYPE)  ,"unsupported key type"},
+{ERR_REASON(CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),"unsupported protection alg dhbasedmac"},
+{ERR_REASON(CMP_R_WRONG_ALGORITHM_OID)   ,"wrong algorithm oid"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_CMP_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(CMP_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,CMP_str_functs);
+		ERR_load_strings(0,CMP_str_reasons);
+		}
+#endif
+	}
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_http.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_http.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_http.c	(revision 764)
@@ -0,0 +1,945 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* crypto/cmp/cmp_http.c
+ * HTTP functions for CMP (RFC 4210) for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2013 Miikka Viljanen <mviljane at users.sourceforge.net>
+ * 
+ * HTTP code taken from crypto/ocsp/ocsp_ht.c, written by 
+ * Dr Stephen N Henson (steve at openssl.org)
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "e_os.h"
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+#include <openssl/ssl.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef OPENSSL_SYS_SUNOS
+#define strtoul (unsigned long)strtol
+#endif /* OPENSSL_SYS_SUNOS */
+
+
+#ifndef HAVE_CURL /* NO curl support, so we use HTTP code from OCSP */
+
+typedef BIO CMPBIO;
+
+/* This code for HTTP was adapted from crypto/ocsp/ocsp_ht.c, OpenSSL version
+ * 1.0.1e, originally written by Dr Stephen N Henson (steve at openssl.org) for
+ * the OpenSSL project 2006.
+ */
+
+/* Stateful CMP request code, supporting non-blocking I/O */
+
+/* Opaque CMP request status structure */
+
+typedef struct cmp_req_ctx_st CMP_REQ_CTX;
+struct cmp_req_ctx_st {
+	int state;		/* Current I/O state */
+	unsigned char *iobuf;	/* Line buffer */
+	int iobuflen;		/* Line buffer length */
+	BIO *io;		/* BIO to perform I/O with */
+	BIO *mem;		/* Memory BIO response is built into */
+	unsigned long asn1_len;	/* ASN1 length of response */
+	};
+
+#define CMP_MAX_REQUEST_LENGTH	(100 * 1024)
+#define CMP_MAX_LINE_LEN	4096;
+
+/* CMP states */
+
+/* If set no reading should be performed */
+#define OHS_NOREAD		0x1000
+/* Error condition */
+#define OHS_ERROR		(0 | OHS_NOREAD)
+/* First line being read */
+#define OHS_FIRSTLINE		1
+/* MIME headers being read */
+#define OHS_HEADERS		2
+/* CMP initial header (tag + length) being read */
+#define OHS_ASN1_HEADER		3
+/* CMP content octets being read */
+#define OHS_ASN1_CONTENT	4
+/* Request being sent */
+#define OHS_ASN1_WRITE		(6 | OHS_NOREAD)
+/* Request being flushed */
+#define OHS_ASN1_FLUSH		(7 | OHS_NOREAD)
+/* Completed */
+#define OHS_DONE		(8 | OHS_NOREAD)
+
+/* from apps.h */
+#ifndef openssl_fdset
+#ifdef OPENSSL_SYSNAME_WIN32
+#  define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
+#else
+#  define openssl_fdset(a,b) FD_SET(a, b)
+#endif
+#endif
+
+
+static int parse_http_line1(char *line);
+
+void CMP_REQ_CTX_free(CMP_REQ_CTX *rctx)
+	{
+	if (rctx->mem)
+		BIO_free(rctx->mem);
+	if (rctx->iobuf)
+		OPENSSL_free(rctx->iobuf);
+	OPENSSL_free(rctx);
+	}
+
+int CMP_REQ_CTX_set1_req(CMP_REQ_CTX *rctx, CMP_PKIMESSAGE *req)
+	{
+	static const char req_hdr[] =
+	"Content-Type: application/pkixcmp\r\n"
+	"Cache-control: no-cache\r\n"
+	"Content-Length: %d\r\n\r\n";
+        if (BIO_printf(rctx->mem, req_hdr, i2d_CMP_PKIMESSAGE(req, NULL)) <= 0)
+		return 0;
+        if (i2d_CMP_PKIMESSAGE_bio(rctx->mem, req) <= 0)
+		return 0;
+	rctx->state = OHS_ASN1_WRITE;
+	rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
+	return 1;
+	}
+
+int CMP_REQ_CTX_add1_header(CMP_REQ_CTX *rctx,
+		const char *name, const char *value)
+	{
+	if (!name)
+		return 0;
+	if (BIO_puts(rctx->mem, name) <= 0)
+		return 0;
+	if (value)
+		{
+		if (BIO_write(rctx->mem, ": ", 2) != 2)
+			return 0;
+		if (BIO_puts(rctx->mem, value) <= 0)
+			return 0;
+		}
+	if (BIO_write(rctx->mem, "\r\n", 2) != 2)
+		return 0;
+	return 1;
+	}
+
+CMP_REQ_CTX *CMP_sendreq_new(BIO *io, char *path, CMP_PKIMESSAGE *req,
+								int maxline)
+	{
+	static const char post_hdr[] = "POST %s HTTP/1.0\r\n";
+
+	CMP_REQ_CTX *rctx;
+	rctx = OPENSSL_malloc(sizeof(CMP_REQ_CTX));
+	rctx->state = OHS_ERROR;
+	rctx->mem = BIO_new(BIO_s_mem());
+	rctx->io = io;
+	rctx->asn1_len = 0;
+	if (maxline > 0)
+		rctx->iobuflen = maxline;
+	else
+		rctx->iobuflen = CMP_MAX_LINE_LEN;
+	rctx->iobuf = OPENSSL_malloc(rctx->iobuflen);
+	if (!rctx->iobuf)
+		return 0;
+	if (!path)
+		path = "/";
+
+        if (BIO_printf(rctx->mem, post_hdr, path) <= 0)
+		return 0;
+
+	if (req && !CMP_REQ_CTX_set1_req(rctx, req))
+		return 0;
+
+	return rctx;
+	}
+
+/* Parse the HTTP response. This will look like this:
+ * "HTTP/1.0 200 OK". We need to obtain the numeric code and
+ * (optional) informational message.
+ */
+
+static int parse_http_line1(char *line)
+	{
+	int retcode;
+	char *p, *q, *r;
+	/* Skip to first white space (passed protocol info) */
+
+	for(p = line; *p && !isspace((unsigned char)*p); p++)
+		continue;
+	if(!*p)
+		{
+		CMPerr(CMP_F_PARSE_HTTP_LINE1,
+					CMP_R_SERVER_RESPONSE_PARSE_ERROR);
+		return 0;
+		}
+
+	/* Skip past white space to start of response code */
+	while(*p && isspace((unsigned char)*p))
+		p++;
+
+	if(!*p)
+		{
+		CMPerr(CMP_F_PARSE_HTTP_LINE1,
+					CMP_R_SERVER_RESPONSE_PARSE_ERROR);
+		return 0;
+		}
+
+	/* Find end of response code: first whitespace after start of code */
+	for(q = p; *q && !isspace((unsigned char)*q); q++)
+		continue;
+
+	if(!*q)
+		{
+		CMPerr(CMP_F_PARSE_HTTP_LINE1,
+					CMP_R_SERVER_RESPONSE_PARSE_ERROR);
+		return 0;
+		}
+
+	/* Set end of response code and start of message */ 
+	*q++ = 0;
+
+	/* Attempt to parse numeric code */
+	retcode = strtoul(p, &r, 10);
+
+	if(*r)
+		return 0;
+
+	/* Skip over any leading white space in message */
+	while(*q && isspace((unsigned char)*q))
+		q++;
+
+	if(*q)
+		{
+		/* Finally zap any trailing white space in message (include
+		 * CRLF) */
+
+		/* We know q has a non white space character so this is OK */
+		for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--)
+			*r = 0;
+		}
+	if(retcode != 200)
+		{
+		CMPerr(CMP_F_PARSE_HTTP_LINE1, CMP_R_SERVER_RESPONSE_ERROR);
+		if(!*q)
+			ERR_add_error_data(2, "Code=", p);
+		else
+			ERR_add_error_data(4, "Code=", p, ",Reason=", q);
+		return 0;
+		}
+
+
+	return 1;
+
+	}
+
+int CMP_sendreq_nbio(CMP_PKIMESSAGE **presp, CMP_REQ_CTX *rctx)
+	{
+	int i, n;
+	const unsigned char *p;
+	next_io:
+	if (!(rctx->state & OHS_NOREAD))
+		{
+		n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen);
+
+		if (n <= 0)
+			{
+			if (BIO_should_retry(rctx->io))
+				return -1;
+			return 0;
+			}
+
+		/* Write data to memory BIO */
+
+		if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
+			return 0;
+		}
+
+	switch(rctx->state)
+		{
+
+		case OHS_ASN1_WRITE:
+		n = BIO_get_mem_data(rctx->mem, &p);
+
+		i = BIO_write(rctx->io,
+			p + (n - rctx->asn1_len), rctx->asn1_len);
+
+		if (i <= 0)
+			{
+			if (BIO_should_retry(rctx->io))
+				return -1;
+			rctx->state = OHS_ERROR;
+			return 0;
+			}
+
+		rctx->asn1_len -= i;
+
+		if (rctx->asn1_len > 0)
+			goto next_io;
+
+		rctx->state = OHS_ASN1_FLUSH;
+
+		(void)BIO_reset(rctx->mem);
+
+		case OHS_ASN1_FLUSH:
+
+		i = BIO_flush(rctx->io);
+
+		if (i > 0)
+			{
+			rctx->state = OHS_FIRSTLINE;
+			goto next_io;
+			}
+
+		if (BIO_should_retry(rctx->io))
+			return -1;
+
+		rctx->state = OHS_ERROR;
+		return 0;
+
+		case OHS_ERROR:
+		return 0;
+
+		case OHS_FIRSTLINE:
+		case OHS_HEADERS:
+
+		/* Attempt to read a line in */
+
+		next_line:
+		/* Due to &%^*$" memory BIO behaviour with BIO_gets we
+		 * have to check there's a complete line in there before
+		 * calling BIO_gets or we'll just get a partial read.
+		 */
+		n = BIO_get_mem_data(rctx->mem, &p);
+		if ((n <= 0) || !memchr(p, '\n', n))
+			{
+			if (n >= rctx->iobuflen)
+				{
+				rctx->state = OHS_ERROR;
+				return 0;
+				}
+			goto next_io;
+			}
+		n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
+
+		if (n <= 0)
+			{
+			if (BIO_should_retry(rctx->mem))
+				goto next_io;
+			rctx->state = OHS_ERROR;
+			return 0;
+			}
+
+		/* Don't allow excessive lines */
+		if (n == rctx->iobuflen)
+			{
+			rctx->state = OHS_ERROR;
+			return 0;
+			}
+
+		/* First line */
+		if (rctx->state == OHS_FIRSTLINE)
+			{
+			if (parse_http_line1((char *)rctx->iobuf))
+				{
+				rctx->state = OHS_HEADERS;
+				goto next_line;
+				}
+			else
+				{
+				rctx->state = OHS_ERROR;
+				return 0;
+				}
+			}
+		else
+			{
+			/* Look for blank line: end of headers */
+			for (p = rctx->iobuf; *p; p++)
+				{
+				if ((*p != '\r') && (*p != '\n'))
+					break;
+				}
+			if (*p)
+				goto next_line;
+
+			rctx->state = OHS_ASN1_HEADER;
+
+			}
+ 
+		/* Fall thru */
+
+
+		case OHS_ASN1_HEADER:
+		/* Now reading ASN1 header: can read at least 2 bytes which
+		 * is enough for ASN1 SEQUENCE header and either length field
+		 * or at least the length of the length field.
+		 */
+		n = BIO_get_mem_data(rctx->mem, &p);
+		if (n < 2)
+			goto next_io;
+
+		/* Check it is an ASN1 SEQUENCE */
+		if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
+			{
+			rctx->state = OHS_ERROR;
+			return 0;
+			}
+
+		/* Check out length field */
+		if (*p & 0x80)
+			{
+			/* If MSB set on initial length octet we can now
+			 * always read 6 octets: make sure we have them.
+			 */
+			if (n < 6)
+				goto next_io;
+			n = *p & 0x7F;
+			/* Not NDEF or excessive length */
+			if (!n || (n > 4))
+				{
+				rctx->state = OHS_ERROR;
+				return 0;
+				}
+			p++;
+			rctx->asn1_len = 0;
+			for (i = 0; i < n; i++)
+				{
+				rctx->asn1_len <<= 8;
+				rctx->asn1_len |= *p++;
+				}
+
+			if (rctx->asn1_len > CMP_MAX_REQUEST_LENGTH)
+				{
+				rctx->state = OHS_ERROR;
+				return 0;
+				}
+
+			rctx->asn1_len += n + 2;
+			}
+		else
+			rctx->asn1_len = *p + 2;
+
+		rctx->state = OHS_ASN1_CONTENT;
+
+		/* Fall thru */
+		
+		case OHS_ASN1_CONTENT:
+		n = BIO_get_mem_data(rctx->mem, &p);
+		if (n < (int)rctx->asn1_len)
+			goto next_io;
+
+
+		*presp = d2i_CMP_PKIMESSAGE(NULL, &p, rctx->asn1_len);
+		if (*presp)
+			{
+			rctx->state = OHS_DONE;
+			return 1;
+			}
+
+		rctx->state = OHS_ERROR;
+		return 0;
+
+		break;
+
+		case OHS_DONE:
+		return 1;
+
+		}
+
+	return 0;
+	}
+
+/* Blocking CMP request handler: now a special case of non-blocking I/O */
+
+CMP_PKIMESSAGE *CMP_sendreq_bio(BIO *b, char *path, CMP_PKIMESSAGE *req)
+	{
+	CMP_PKIMESSAGE *resp = NULL;
+	CMP_REQ_CTX *ctx;
+	int rv;
+
+	ctx = CMP_sendreq_new(b, path, req, -1);
+	if (!ctx) return NULL;
+
+	do
+		{
+		rv = CMP_sendreq_nbio(&resp, ctx);
+		} while ((rv == -1) && BIO_should_retry(b));
+
+	CMP_REQ_CTX_free(ctx);
+
+	if (rv)
+		return resp;
+
+	return NULL;
+	}
+
+
+#else /* HAVE_CURL */
+
+typedef CURL CMPBIO;
+
+/* If libcurl is available, we use this code. */
+
+typedef struct rdata_s
+	{
+	char *memory;
+	size_t size;
+	} rdata_t;
+
+/* ############################################################################ *
+ * internal function
+ *
+ * realloc which doesn't fail when trying to reallocate NULL pointers
+ *
+ * returns pointer to (re-)allocate space or NULL on error
+ * ############################################################################ */
+static void *myrealloc(void *ptr, size_t size)
+	{
+	if(ptr)
+		return realloc(ptr, size);
+	else
+		return calloc(1,size);
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * used for CURLOPT_WRITEFUNCTION
+ *
+ * returns size of written data in bytes
+ * ############################################################################ */
+static size_t write_data(void *ptr, size_t size, size_t nmemb, void *data)
+	{
+	size_t realsize = size * nmemb;
+	struct rdata_s *mem = (struct rdata_s *) data;
+
+	mem->memory = myrealloc(mem->memory, mem->size + realsize + 1);
+	if (mem->memory)
+		{
+		memcpy(&(mem->memory[mem->size]), ptr, realsize);
+		mem->size += realsize;
+		mem->memory[mem->size] = 0;
+		}
+	return realsize;
+	}
+
+/* ################################################################ *
+ * internal function
+ *
+ * In CMP_CTX we have separate variables for server address and path,
+ * but libcurl doesn't have a separate function for just setting the
+ * path. This function simply checks the end of the effective url to
+ * make sure that the correct path is there, and if it's not set yet
+ * it will be added.
+ *
+ * returns 1 on success, 0 on error
+ * ################################################################ */
+static int set_http_path(CURL *curl, const CMP_CTX *ctx)
+	{
+	char *url = NULL;
+	int bufsize = 0;
+
+	bufsize = strlen(ctx->serverName) + strlen(ctx->serverPath) + 2;
+	url = malloc(bufsize);
+	if (!url) return 0;
+
+	BIO_snprintf(url, bufsize, "%s/%s", ctx->serverName, ctx->serverPath);
+	curl_easy_setopt(curl, CURLOPT_URL, url);
+	free(url);
+
+	return 1;
+	}
+
+
+#endif
+
+
+/*
+static uint32_t gethostiplong(const char *host)
+	{
+	unsigned char ip[4];
+
+	BIO_get_host_ip(host, ip);
+
+	return htonl( (unsigned long)
+			((unsigned long)ip[0]<<24L)|
+			((unsigned long)ip[1]<<16L)|
+			((unsigned long)ip[2]<< 8L)|
+			((unsigned long)ip[3]) );
+	}
+*/
+
+/* ########################################################################## *
+ * internal function
+ * Create a new http connection, with a specified source ip/interface
+ * returns 1 on success, 0 on error, returns the created bio inside the *bio
+ * argument
+ * ########################################################################## */
+static int CMP_new_http_bio( CMPBIO **bio, const CMP_CTX *ctx)
+	{
+#ifndef HAVE_CURL
+	BIO *cbio = NULL;
+
+	if (!ctx) goto err;
+	
+	if (!ctx->proxyName || !ctx->proxyPort)
+		{
+		cbio = BIO_new_connect(ctx->serverName);
+		if (!cbio) goto err;
+		BIO_set_conn_int_port(cbio, &ctx->serverPort);
+		}
+	else
+		{
+		cbio = BIO_new_connect(ctx->proxyName);
+		if (!cbio) goto err;
+		BIO_set_conn_int_port(cbio, &ctx->proxyPort);
+		}
+
+	if (ctx->useTLS)
+		{
+		OpenSSL_add_ssl_algorithms();
+		/* TODO support all versions of SSL / TLS properly */
+		SSL_CTX *ctx = SSL_CTX_new(TLSv1_client_method());
+		SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+		BIO *sbio = BIO_new_ssl(ctx, 1);
+		cbio = BIO_push(sbio, cbio);
+		}
+
+	*bio = cbio;
+	return 1;
+
+	err:
+	return 0;
+#else
+	struct curl_slist *slist=NULL;
+	CURL *curl;
+	
+	static int curl_initialized = 0;
+
+	if (!ctx) goto err;
+
+	if (curl_initialized == 0)
+		{
+		curl_initialized =	1;
+		curl_global_init(CURL_GLOBAL_ALL);
+		}
+
+	if (!(curl=curl_easy_init())) goto err;
+
+	slist = curl_slist_append(slist, "Content-Type: application/pkixcmp");
+	slist = curl_slist_append(slist, "Cache-control: no-cache");
+	slist = curl_slist_append(slist, "Expect:"); 
+	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
+	if (ctx->sourceAddress != NULL)
+		curl_easy_setopt(curl, CURLOPT_INTERFACE, ctx->sourceAddress);
+
+	curl_easy_setopt(curl, CURLOPT_URL, ctx->serverName);
+	curl_easy_setopt(curl, CURLOPT_PORT, ctx->serverPort);
+
+	curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+
+	if (ctx->proxyName && ctx->proxyPort)
+		{
+		curl_easy_setopt(curl, CURLOPT_PROXY, ctx->proxyName);
+		curl_easy_setopt(curl, CURLOPT_PROXYPORT, ctx->proxyPort);
+		curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+		}
+	else
+		{
+		/* curl will automatically try to get proxy from environment if we don't set this.
+		 * if proxy use is enabled, it will be set in CMP_PKIMESSAGE_http_perform. */
+		curl_easy_setopt(curl, CURLOPT_PROXY, ""); /* TODO: that needs to be explicitly documented */
+		}
+
+	*bio = curl;
+	return 1;
+
+	err:
+	CMPerr(CMP_F_CMP_NEW_HTTP_BIO, CMP_R_CURL_ERROR);
+	return 0;
+#endif
+	}
+
+static int CMP_delete_http_bio( CMPBIO *cbio)
+	{
+#ifndef HAVE_CURL
+	if (cbio) BIO_free_all(cbio);
+#else
+	if (cbio) curl_easy_cleanup(cbio);
+#endif
+	return 1;
+	}
+
+/* ################################################################ *
+ * Send the given PKIMessage msg and place the response in *out.
+ * returns 1 on success, 0 on error
+ * on success, returns pointer to received PKIMessage in *out
+ * ################################################################ */
+#ifndef HAVE_CURL
+
+int CMP_PKIMESSAGE_http_perform(const CMP_CTX *ctx, const CMP_PKIMESSAGE *msg, CMP_PKIMESSAGE **out)
+	{
+	int rv, fd;
+	fd_set confds;
+	struct timeval tv;
+	char *path=0;
+	size_t pos=0, pathlen=0;
+	CMPBIO *cbio = 0;
+
+	CMP_new_http_bio(&cbio, ctx);
+
+	if (!cbio || !ctx || !msg || !out)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_NULL_ARGUMENT);
+		goto err;
+		}
+
+	if (!ctx->serverName || !ctx->serverPath || !ctx->serverPort)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_NULL_ARGUMENT);
+		goto err;
+		}
+
+	if (ctx->HttpTimeOut != 0)
+		BIO_set_nbio(cbio, 1);
+	
+	rv = BIO_do_connect(cbio);
+	if (rv <= 0 && (ctx->HttpTimeOut == -1 || !BIO_should_retry(cbio)))
+		{
+		/* Error connecting */
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_SERVER_NOT_REACHABLE);
+		goto err;
+		}
+
+	if (BIO_get_fd(cbio, &fd) <= 0)
+		{
+		/* XXX Can't get fd, is this the right error to return? */
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_SERVER_NOT_REACHABLE);
+		goto err;
+		}
+
+	if (ctx->HttpTimeOut != -1 && rv <= 0)
+		{
+		FD_ZERO(&confds);
+		openssl_fdset(fd, &confds);
+		tv.tv_usec = 0;
+		tv.tv_sec = ctx->HttpTimeOut;
+		rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+		if (rv == 0)
+			{
+			// Timed out
+			CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_SERVER_NOT_REACHABLE);
+			goto err;
+			}
+		}
+
+	pathlen = strlen(ctx->serverName) + strlen(ctx->serverPath) + 32;
+	path = (char*) OPENSSL_malloc(pathlen);
+	if (!path) goto err;
+
+	/* Section 5.1.2 of RFC 1945 states that the absoluteURI form is only allowed when using a proxy */
+	if (ctx->proxyName && ctx->proxyPort)
+		pos = BIO_snprintf(path, pathlen-1, "http://%s:%d", ctx->serverName, ctx->serverPort);
+	
+	/* make sure path includes a forward slash */
+	if (ctx->serverPath[0] != '/') path[pos++] = '/';
+
+	BIO_snprintf(path+pos, pathlen-pos-1, "%s", ctx->serverPath);
+
+	*out = CMP_sendreq_bio(cbio, path, (CMP_PKIMESSAGE*) msg);
+
+	OPENSSL_free(path);
+	// BIO_reset(cbio);
+	CMP_delete_http_bio(cbio);
+	
+	if (!*out) {
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_FAILED_TO_DECODE_PKIMESSAGE);
+		goto err;
+	}
+	
+	return 1;
+
+	err:
+	return 0;
+	}
+
+#else  /* HAVE_CURL */
+
+int CMP_PKIMESSAGE_http_perform(const CMP_CTX *ctx, const CMP_PKIMESSAGE *msg, CMP_PKIMESSAGE **out)
+	{
+	unsigned char *derMsg = NULL, *pder = NULL;
+	char *content_type = NULL;
+	int derLen = 0;
+	CURLcode res;
+	rdata_t rdata = {0,0};
+	CMPBIO *curl = NULL;
+
+	CMP_new_http_bio(&curl, ctx);
+
+	if (!curl || !ctx || !msg || !out)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_NULL_ARGUMENT);
+		goto err;
+		}
+
+	if (!ctx->serverName || !ctx->serverPath || !ctx->serverPort)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_NULL_ARGUMENT);
+		goto err;
+		}
+
+	derLen = i2d_CMP_PKIMESSAGE( (CMP_PKIMESSAGE*) msg, &derMsg);
+
+	set_http_path(curl, ctx);
+
+	/* curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); */
+
+	/* rdata will contain the data received from the server */
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&rdata);
+
+	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*) derMsg);
+	curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, derLen);
+
+	/* set timeout for the entire HTTP operation */
+	if (ctx->HttpTimeOut != 0)
+		curl_easy_setopt(curl, CURLOPT_TIMEOUT, ctx->HttpTimeOut);
+
+	res = curl_easy_perform(curl);
+
+	/* free up sent DER message from memory */
+	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void*) 0);
+	free(derMsg);
+
+	if (res != CURLE_OK)
+		{
+		char num[64];
+
+		if (res == CURLE_COULDNT_CONNECT
+			|| res == CURLE_COULDNT_RESOLVE_PROXY
+			|| res == CURLE_COULDNT_RESOLVE_HOST
+			|| res == CURLE_SEND_ERROR
+			|| res == CURLE_RECV_ERROR
+			|| res == CURLE_OPERATION_TIMEDOUT
+			|| res == CURLE_INTERFACE_FAILED)
+			CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_SERVER_NOT_REACHABLE);
+		else if (res != CURLE_OK)
+			CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_CURL_ERROR);
+
+		BIO_snprintf(num, sizeof(num)-1, "%d:", res);
+		ERR_add_error_data(2, num, curl_easy_strerror(res));
+		goto err;
+		}
+	
+	/* verify that Content-type is application/pkixcmp */
+	curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
+	if (content_type == NULL || strcmp(content_type, "application/pkixcmp") != 0)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_INVALID_CONTENT_TYPE);
+		goto err;
+		}
+
+	pder = (unsigned char*) rdata.memory;
+	*out = d2i_CMP_PKIMESSAGE( NULL, (const unsigned char**) &pder, rdata.size);
+	if (*out == 0)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_HTTP_PERFORM, CMP_R_FAILED_TO_DECODE_PKIMESSAGE);
+		goto err;
+		}
+
+	if (CURLE_OK != curl_easy_getinfo((CMPBIO*)curl, CURLINFO_RESPONSE_CODE, &ctx->lastHTTPCode)) goto err;
+
+	CMP_delete_http_bio(curl);
+
+	free(rdata.memory);
+	return 1;
+
+	err:
+	if (rdata.memory)
+		free(rdata.memory);
+
+	if (curl)
+		CMP_delete_http_bio(curl);
+	return 0;
+	}
+#endif	/* HAVE_CURL */
+
+
+/* ################################################################ *
+ * Returns the HTTP response code of the last response we got from
+ * the server.
+ * returns 0 on error
+ * ################################################################ */
+long CMP_get_http_response_code(const CMP_CTX *ctx)
+	{
+	if (!ctx) return 0;
+	return ctx->lastHTTPCode;
+	}
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_lib.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_lib.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_lib.c	(revision 764)
@@ -0,0 +1,1534 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* crypto/cmp/cmp_lib.c
+ * CMP (RFC 4210) library functions for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+ /* NAMING
+  * The 0 version uses the supplied structure pointer directly in the parent and
+  * it will be freed up when the parent is freed. In the above example crl would
+  * be freed but rev would not.
+  *
+  * The 1 function uses a copy of the supplied structure pointer (or in some
+  * cases increases its link count) in the parent and so both (x and obj above)
+  * should be freed up.
+ */
+
+/* ############################################################################ *
+ * In this file are the functions which set the individual items inside			*
+ * the CMP structures															*
+ * ############################################################################ */
+
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/cmp.h>
+#include <openssl/x509.h>
+#include <openssl/rand.h>
+#include <openssl/safestack.h>
+#include <openssl/crypto.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+/* for bio_err */
+#include <openssl/err.h>
+
+#include <time.h>
+#include <string.h>
+
+/* ############################################################################ *
+ * Sets the protocol version number in PKIHeader.
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set_version(CMP_PKIHEADER *hdr, int version)
+	{
+	if( !hdr) goto err;
+
+	if(! ASN1_INTEGER_set(hdr->pvno, version)) goto err;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * Set the recipient name of PKIHeader.
+ * when nm is NULL, recipient is set to an empty string
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set1_recipient(CMP_PKIHEADER *hdr, const X509_NAME *nm)
+	{
+	GENERAL_NAME *gen=NULL;
+	if( !hdr) goto err;
+
+	gen = GENERAL_NAME_new();
+	if( !gen) goto err;
+
+	gen->type = GEN_DIRNAME;
+
+	/* if nm is not set an empty dirname will be set */
+	if (nm == NULL)
+		{
+		gen->d.directoryName = X509_NAME_new();
+		}
+	else
+		{
+		if (!X509_NAME_set(&gen->d.directoryName, (X509_NAME*) nm))
+			{
+			GENERAL_NAME_free(gen);
+			goto err;
+			}
+		}
+
+	if (hdr->recipient)
+		GENERAL_NAME_free(hdr->recipient);
+	hdr->recipient = gen;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * Set the sender name in PKIHeader.
+ * when nm is NULL, sender is set to an empty string
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set1_sender(CMP_PKIHEADER *hdr, const X509_NAME *nm)
+	{
+	GENERAL_NAME *gen=NULL;
+	if( !hdr) goto err;
+
+	gen = GENERAL_NAME_new();
+	if( !gen) goto err;
+
+	gen->type = GEN_DIRNAME;
+
+	/* if nm is not set an empty dirname will be set */
+	if (nm == NULL)
+		{
+		gen->d.directoryName = X509_NAME_new();
+		}
+	else {
+		if (!X509_NAME_set(&gen->d.directoryName, (X509_NAME*) nm))
+			{
+			GENERAL_NAME_free(gen);
+			goto err;
+			}
+		}
+	if (hdr->sender)
+		GENERAL_NAME_free(hdr->sender);
+	hdr->sender = gen;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * (re-)set given transaction ID in CMP header
+ * if given *transactionID is NULL, a random one is created with 128 bit
+ * according to section 5.1.1:
+ *
+ * It is RECOMMENDED that the clients fill the transactionID field with
+ * 128 bits of (pseudo-) random data for the start of a transaction to
+ * reduce the probability of having the transactionID in use at the
+ * server.
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set1_transactionID(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *transactionID)
+	{
+#define TRANSACTIONID_LENGTH 16
+	unsigned char *transactionIDuchar=NULL;
+
+	if(!hdr) goto err;
+
+	if(transactionID)
+		{
+		if (!(hdr->transactionID = ASN1_OCTET_STRING_dup((ASN1_OCTET_STRING *)transactionID))) goto err;
+		}
+	else {
+		/* generate a random value if none was given */
+		if(!(transactionIDuchar = (unsigned char*)OPENSSL_malloc(TRANSACTIONID_LENGTH))) goto err;
+		RAND_pseudo_bytes(transactionIDuchar, TRANSACTIONID_LENGTH);
+
+		if(hdr->transactionID == NULL)
+			{
+			hdr->transactionID = ASN1_OCTET_STRING_new();
+			}
+		if(!(ASN1_OCTET_STRING_set(hdr->transactionID, transactionIDuchar, TRANSACTIONID_LENGTH))) goto err;
+
+		OPENSSL_free(transactionIDuchar);
+		}
+
+	return 1;
+err:
+	if(transactionIDuchar)
+		OPENSSL_free(transactionIDuchar);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * (re-)set random senderNonce to given header
+ * as in 5.1.1:
+ *
+ * senderNonce			present
+ *	   -- 128 (pseudo-)random bits
+ * The senderNonce and recipNonce fields protect the PKIMessage against
+ * replay attacks.	The senderNonce will typically be 128 bits of
+ * (pseudo-) random data generated by the sender, whereas the recipNonce
+ * is copied from the senderNonce of the previous message in the
+ * transaction.
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_new_senderNonce(CMP_PKIHEADER *hdr)
+	{
+#define SENDERNONCE_LENGTH 16
+	unsigned char senderNonce[SENDERNONCE_LENGTH];
+
+	if( !hdr) goto err;
+
+	RAND_pseudo_bytes(senderNonce, SENDERNONCE_LENGTH);
+
+	if (hdr->senderNonce == NULL)
+		{
+		hdr->senderNonce = ASN1_OCTET_STRING_new();
+		}
+
+	if (!(ASN1_OCTET_STRING_set(hdr->senderNonce, senderNonce, SENDERNONCE_LENGTH))) goto err;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * (re-)sets given recipient nonce to given header
+ * as per 5.1.1 used to mirror the nonce back to the other side
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set1_recipNonce(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *recipNonce)
+	{
+	if (!hdr) goto err;
+	if (!recipNonce) goto err;
+
+	if (hdr->recipNonce)
+		ASN1_OCTET_STRING_free(hdr->recipNonce);
+
+	if (!(hdr->recipNonce = ASN1_OCTET_STRING_dup((ASN1_OCTET_STRING *)recipNonce))) goto err;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ * 
+ * (re-)set given senderKID to given header
+ *
+ * senderKID			referenceNum
+ *	 -- the reference number which the CA has previously issued
+ *	 -- to the end entity (together with the MACing key)
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set1_senderKID(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *senderKID)
+	{
+	if (!hdr) goto err;
+	if (!senderKID) goto err;
+
+	if (hdr->senderKID)
+		 ASN1_OCTET_STRING_free(hdr->senderKID);
+
+	if (!(hdr->senderKID = ASN1_OCTET_STRING_dup((ASN1_OCTET_STRING *)senderKID))) goto err;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################
+ * (re-)set the messageTime to the current system time
+ *
+ * as in 5.1.1:
+ *
+ * The messageTime field contains the time at which the sender created
+ * the message.  This may be useful to allow end entities to
+ * correct/check their local time for consistency with the time on a
+ * central system.
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_set_messageTime(CMP_PKIHEADER *hdr)
+	{
+	if (!hdr) goto err;
+
+	if (!hdr->messageTime)
+		 hdr->messageTime = ASN1_GENERALIZEDTIME_new();
+
+	if (! ASN1_GENERALIZEDTIME_set( hdr->messageTime, time(NULL))) goto err;
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * push given ASN1_UTF8STRING to hdr->freeText and consume the given pointer
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_push0_freeText( CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
+	{
+	if (!hdr) goto err;
+	if (!text) goto err;
+
+	if (!hdr->freeText)
+		if (!(hdr->freeText = sk_ASN1_UTF8STRING_new_null())) goto err;
+
+	if (!(sk_ASN1_UTF8STRING_push(hdr->freeText, text))) goto err;
+
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * push an ASN1_UTF8STRING to hdr->freeText and don't consume the given pointer
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_push1_freeText( CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
+	{
+	ASN1_UTF8STRING *textDup=NULL;
+
+	if (!hdr) goto err;
+	if (!text) goto err;
+
+	if( !(textDup = ASN1_UTF8STRING_new())) goto err;
+	if( !ASN1_STRING_set( textDup, text->data, text->length)) goto err;
+
+	return CMP_PKIHEADER_push0_freeText( hdr, textDup);
+err:
+	if (textDup) ASN1_UTF8STRING_free(textDup);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * Initialize the given PkiHeader structure with values set in the CMP_CTX structure.
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_init(CMP_CTX *ctx, CMP_PKIHEADER *hdr)
+	{
+	if( !hdr) goto err;
+	if( !ctx) goto err;
+
+	/* set the CMP version */
+	CMP_PKIHEADER_set_version( hdr, CMP_VERSION);
+
+	/* in case there is no OLD client cert the sender name is not set (e.g. for IR) */
+	if( ctx->clCert)
+		{
+		if( !CMP_PKIHEADER_set1_sender( hdr, X509_get_subject_name( (X509*) ctx->clCert))) goto err;
+		}
+	else {
+		if( !CMP_PKIHEADER_set1_sender( hdr, NULL)) goto err;
+		}
+
+	/* set recipient name either from known server certificate or recipient name in ctx, leave empty if not set in ctx */
+	if( ctx->srvCert)
+		{
+		if( !CMP_PKIHEADER_set1_recipient( hdr, X509_get_subject_name( (X509*) ctx->srvCert))) goto err;
+		}
+	else if( ctx->recipient)
+		{
+		if( !CMP_PKIHEADER_set1_recipient( hdr, ctx->recipient)) goto err;
+		}
+	else
+		{
+		if( !CMP_PKIHEADER_set1_recipient( hdr, NULL)) goto err;
+		}
+
+	/* set current time as message time */
+	if( !CMP_PKIHEADER_set_messageTime(hdr)) goto err;
+
+	if (ctx->recipNonce) 
+		if( !CMP_PKIHEADER_set1_recipNonce(hdr, ctx->recipNonce)) goto err;
+
+	if (ctx->transactionID)
+		{
+		if (!CMP_PKIHEADER_set1_transactionID(hdr, ctx->transactionID)) goto err;
+		}
+	else {
+		/* create new transaction ID */
+		if (!CMP_PKIHEADER_set1_transactionID(hdr, NULL)) goto err; 
+		CMP_CTX_set1_transactionID(ctx, hdr->transactionID);
+		}
+
+	if (!CMP_PKIHEADER_new_senderNonce(hdr)) goto err; 
+
+#if 0
+	/*
+		 freeText		 [7] PKIFreeText			 OPTIONAL,
+		 -- this may be used to indicate context-specific instructions
+		 -- (this field is intended for human consumption)
+	 */
+	if( ctx->freeText)
+		if( !CMP_PKIHEADER_push1_freeText(hdr, ctx->freeText)) goto err;
+#endif
+
+	return 1;
+err:
+	return 0;
+}
+
+
+/* ############################################################################ * 
+ * also used for verification from cmp_vfy
+ *
+ * calculate PBM protection for given PKImessage utilizing the given secret and the
+ * pbm-parameters set inside the message header's protectionAlg
+ *
+ * returns pointer to ASN1_BIT_STRING containing protection on success, NULL on
+ * error
+ * ############################################################################ */
+ASN1_BIT_STRING *CMP_calc_protection_pbmac(CMP_PKIMESSAGE *pkimessage, const ASN1_OCTET_STRING *secret)
+	{
+	ASN1_BIT_STRING *prot=NULL;
+	CMP_PROTECTEDPART protPart;
+	ASN1_STRING *pbmStr=NULL;
+	ASN1_OBJECT *algorOID=NULL;
+
+	CRMF_PBMPARAMETER *pbm=NULL;
+
+	size_t protPartDerLen;
+	unsigned int macLen;
+	unsigned char *protPartDer=NULL;
+	unsigned char *mac=NULL;
+	const unsigned char *pbmStrUchar=NULL;
+
+	void *ppval=NULL;
+	int pptype=0;
+
+	if (!secret)
+		{
+		CMPerr(CMP_F_CMP_CALC_PROTECTION_PBMAC, CMP_R_NO_SECRET_VALUE_GIVEN_FOR_PBMAC);
+		goto err;
+		}
+
+	protPart.header = pkimessage->header;
+	protPart.body	= pkimessage->body;
+	protPartDerLen	= i2d_CMP_PROTECTEDPART(&protPart, &protPartDer);
+
+	X509_ALGOR_get0( &algorOID, &pptype, &ppval, pkimessage->header->protectionAlg);
+
+	if (NID_id_PasswordBasedMAC == OBJ_obj2nid(algorOID))
+		{
+		/* there is no pmb set in this message */
+		if (!ppval) goto err;
+
+		pbmStr = (ASN1_STRING *)ppval;
+		pbmStrUchar = (unsigned char *)pbmStr->data;
+		pbm = d2i_CRMF_PBMPARAMETER( NULL, &pbmStrUchar, pbmStr->length);
+
+		if(!(CRMF_passwordBasedMac_new(pbm, protPartDer, protPartDerLen, secret->data, secret->length, &mac, &macLen))) goto err;
+		}
+	else {
+		CMPerr(CMP_F_CMP_CALC_PROTECTION_PBMAC, CMP_R_WRONG_ALGORITHM_OID);
+		goto err;
+		}
+	OPENSSL_free(protPartDer);
+
+	if(!(prot = ASN1_BIT_STRING_new())) goto err;
+	ASN1_BIT_STRING_set(prot, mac, macLen);
+
+	/* Actually this should not be needed but OpenSSL defaults all bitstrings to be a NamedBitList */
+	prot->flags &= ~0x07;
+	prot->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+	/* cleanup */
+	if (mac) OPENSSL_free(mac);
+	return prot;
+
+err:
+	if (mac) OPENSSL_free(mac);
+
+	CMPerr(CMP_F_CMP_CALC_PROTECTION_PBMAC, CMP_R_ERROR_CALCULATING_PROTECTION);
+	if(prot) ASN1_BIT_STRING_free(prot);
+	if(protPartDer) OPENSSL_free(protPartDer);
+	return NULL;
+}
+
+/* ############################################################################ * 
+ * only used internally
+ *
+ * calculate signature protection for given PKImessage utilizing the given secret key 
+ * and the algorithm parameters set inside the message header's protectionAlg
+ *
+ * returns pointer to ASN1_BIT_STRING containing protection on success, NULL on
+ * error
+ * ############################################################################ */
+ASN1_BIT_STRING *CMP_calc_protection_sig(CMP_PKIMESSAGE *pkimessage, EVP_PKEY *pkey)
+	{
+	ASN1_BIT_STRING *prot=NULL;
+	CMP_PROTECTEDPART protPart;
+	ASN1_OBJECT *algorOID=NULL;
+
+	size_t protPartDerLen;
+	unsigned int macLen;
+	size_t maxMacLen;
+	unsigned char *protPartDer=NULL;
+	unsigned char *mac=NULL;
+
+	void *ppval=NULL;
+	int pptype=0;
+
+	EVP_MD_CTX	 *evp_ctx=NULL;
+	const EVP_MD *md=NULL;
+
+	if (!pkey)
+		{ /* EVP_SignFinal() will check that pkey type is correct for the algorithm */
+		CMPerr(CMP_F_CMP_CALC_PROTECTION_SIG, CMP_R_INVALID_KEY);
+		ERR_add_error_data(1, "pkey was NULL although it is supposed to be used for generating protection");
+		goto err;
+		}
+
+	/* construct data to be signed */
+	protPart.header = pkimessage->header;
+	protPart.body	= pkimessage->body;
+	protPartDerLen	= i2d_CMP_PROTECTEDPART(&protPart, &protPartDer);
+
+	X509_ALGOR_get0( &algorOID, &pptype, &ppval, pkimessage->header->protectionAlg);
+
+	if ((md = EVP_get_digestbynid(OBJ_obj2nid(algorOID))))
+		{
+		maxMacLen = EVP_PKEY_size(pkey);
+		mac = OPENSSL_malloc(maxMacLen);
+
+		/* calculate signature */
+		evp_ctx = EVP_MD_CTX_create();
+		if (!evp_ctx) goto err;
+		if (!(EVP_SignInit_ex(evp_ctx, md, NULL))) goto err;
+		if (!(EVP_SignUpdate(evp_ctx, protPartDer, protPartDerLen))) goto err;
+		if (!(EVP_SignFinal(evp_ctx, mac, &macLen, pkey))) goto err;
+		}
+	else {
+		CMPerr(CMP_F_CMP_CALC_PROTECTION_SIG, CMP_R_UNKNOWN_ALGORITHM_ID);
+		goto err;
+		}
+
+	if(!(prot = ASN1_BIT_STRING_new())) goto err;
+	ASN1_BIT_STRING_set(prot, mac, macLen);
+
+	/* Actually this should not be needed but OpenSSL defaults all bitstrings to be a NamedBitList */
+	prot->flags &= ~0x07;
+	prot->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+	/* cleanup */
+	if (evp_ctx) EVP_MD_CTX_destroy(evp_ctx);
+	if (mac) OPENSSL_free(mac);
+	if (protPartDer) OPENSSL_free(protPartDer);
+	return prot;
+
+err:
+	if (evp_ctx) EVP_MD_CTX_destroy(evp_ctx);
+	if (mac) OPENSSL_free(mac);
+	if (protPartDer) OPENSSL_free(protPartDer);
+
+	CMPerr(CMP_F_CMP_CALC_PROTECTION_SIG, CMP_R_ERROR_CALCULATING_PROTECTION);
+	if(prot) ASN1_BIT_STRING_free(prot);
+	return NULL;
+}
+
+/* ############################################################################ *
+ * internal function
+ * Create an X509_ALGOR structure for PasswordBasedMAC protection
+ * returns pointer to X509_ALGOR on success, NULL on error
+ * TODO: this could take options to configure the pbmac
+ * ############################################################################ */
+X509_ALGOR *CMP_create_pbmac_algor(void)
+	{
+	X509_ALGOR *alg=NULL;
+	CRMF_PBMPARAMETER *pbm=NULL;
+	unsigned char *pbmDer=NULL;
+	int pbmDerLen;
+	ASN1_STRING *pbmStr=NULL;
+
+	if (!(alg = X509_ALGOR_new())) goto err;
+	if (!(pbm = CRMF_pbm_new())) goto err;
+	if (!(pbmStr = ASN1_STRING_new())) goto err;
+
+	pbmDerLen = i2d_CRMF_PBMPARAMETER( pbm, &pbmDer);
+
+	ASN1_STRING_set( pbmStr, pbmDer, pbmDerLen);
+	OPENSSL_free( pbmDer);
+	pbmDer = NULL; /* to avoid double free in case there would be a "goto err" inserted behind this point later in development */
+
+	X509_ALGOR_set0( alg, OBJ_nid2obj(NID_id_PasswordBasedMAC), V_ASN1_SEQUENCE, pbmStr);
+	pbmStr = NULL; /* pbmStr is not freed explicityly because the pointer was consumed by X509_ALGOR_set0() */
+
+	CRMF_PBMPARAMETER_free( pbm);
+	return alg;
+err:
+	if (alg) X509_ALGOR_free(alg);
+	if (pbm) CRMF_PBMPARAMETER_free( pbm);
+	if (pbmDer) OPENSSL_free( pbmDer);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * determines which kind of protection should be created based on the ctx
+ * sets this into the protectionAlg field in the message header
+ * calculates the protection and sets it in the protections filed
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIMESSAGE_protect(CMP_CTX *ctx, CMP_PKIMESSAGE *msg)
+	{
+	if(!ctx) goto err;
+	if(!msg) goto err;
+
+	/* use PasswordBasedMac according to 5.1.3.1 if secretValue is given */
+	if (ctx->secretValue)
+		{
+		if(!(msg->header->protectionAlg = CMP_create_pbmac_algor())) goto err;
+		CMP_PKIHEADER_set1_senderKID(msg->header, ctx->referenceValue);
+		if(!(msg->protection = CMP_calc_protection_pbmac( msg, ctx->secretValue))) 
+			goto err;
+		}
+	else {
+		/* use MSG_SIG_ALG according to 5.1.3.3 if client Certificate and private key is given */
+		if (ctx->clCert && ctx->pkey)
+			{
+			ASN1_OCTET_STRING *subjKeyIDStr = NULL;
+			int algNID = 0;
+			
+			if (!msg->header->protectionAlg)
+				msg->header->protectionAlg = X509_ALGOR_new();
+			
+			/* DSA/SHA1 is mandatory for MSG_SIG_ALG (appendix D.2) so SHA-1 is hardcoded here for now */
+			/* This could be made configurable via ctx to include SHA-256 etc */
+			switch (EVP_PKEY_type(ctx->pkey->type))
+				{
+				case EVP_PKEY_DSA: 
+					algNID = NID_dsaWithSHA1;
+					break;
+				case EVP_PKEY_RSA:
+					algNID = NID_sha1WithRSAEncryption;
+					break;
+				default:
+					CMPerr(CMP_F_CMP_PKIMESSAGE_PROTECT, CMP_R_UNSUPPORTED_KEY_TYPE);
+					goto err;
+				}
+			X509_ALGOR_set0(msg->header->protectionAlg, OBJ_nid2obj(algNID), V_ASN1_NULL, NULL);
+
+			/* set senderKID to  keyIdentifier of the used certificate according
+			 * to section 5.1.1 */
+			subjKeyIDStr = CMP_get_cert_subject_key_id(ctx->clCert);
+			if (subjKeyIDStr)
+				{
+				CMP_PKIHEADER_set1_senderKID(msg->header, subjKeyIDStr);
+				ASN1_OCTET_STRING_free(subjKeyIDStr);
+				}
+			
+			if (!(msg->protection = CMP_calc_protection_sig( msg, ctx->pkey))) 
+				goto err;
+			}
+		else
+			{
+			CMPerr(CMP_F_CMP_PKIMESSAGE_PROTECT, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
+			goto err;
+			}
+		}
+
+	return 1;
+	err:
+	CMPerr(CMP_F_CMP_PKIMESSAGE_PROTECT, CMP_R_ERROR_PROTECTING_MESSAGE);
+	return 0;
+	}
+
+/* ############################################################################ * 
+ * set certificate Hash in certStatus of certConf messages according to 5.3.18.
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_CERTSTATUS_set_certHash( CMP_CERTSTATUS *certStatus, const X509 *cert)
+	{
+	unsigned int hashLen;
+	unsigned char hash[EVP_MAX_MD_SIZE];
+	int sigAlgID;
+	const EVP_MD *md = NULL;
+
+	if (!certStatus) goto err;
+	if (!cert) goto err;
+
+	/*  select hash algorithm, as stated in Appendix F.  Compilable ASN.1 Definitions:
+	 *  -- the hash of the certificate, using the same hash algorithm
+	 *  -- as is used to create and verify the certificate signature */
+	sigAlgID = OBJ_obj2nid(cert->sig_alg->algorithm);
+	if ((md = EVP_get_digestbynid(sigAlgID)))
+		{
+		if (!X509_digest(cert, md, hash, &hashLen)) goto err;
+		if (!certStatus->certHash)
+			if (!(certStatus->certHash = ASN1_OCTET_STRING_new())) goto err;
+		if (!ASN1_OCTET_STRING_set(certStatus->certHash, hash, hashLen)) goto err;
+		}
+	else
+		{
+		CMPerr(CMP_F_CMP_CERTSTATUS_SET_CERTHASH, CMP_R_UNSUPPORTED_ALGORITHM);
+		goto err;
+		}
+
+	return 1;
+	err:
+	CMPerr(CMP_F_CMP_CERTSTATUS_SET_CERTHASH, CMP_R_ERROR_SETTING_CERTHASH);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets implicitConfirm in the generalInfo field of the PKIMessage header
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIMESSAGE_set_implicitConfirm(CMP_PKIMESSAGE *msg)
+	{
+	CMP_INFOTYPEANDVALUE *itav=NULL;
+
+	if (!msg) goto err;
+
+	if (!(itav = CMP_INFOTYPEANDVALUE_new())) goto err;
+	itav->infoType = OBJ_nid2obj(NID_id_it_implicitConfirm);
+	itav->infoValue.implicitConfirm = ASN1_NULL_new();
+	if (!CMP_PKIHEADER_generalInfo_item_push0( msg->header, itav)) goto err;
+	return 1;
+err:
+	if (itav) CMP_INFOTYPEANDVALUE_free(itav);
+	return 0;
+	}
+
+/* ############################################################################
+ * checks if implicitConfirm in the generalInfo field of the header is set
+ *
+ * returns 1 if it is set, 0 if not
+ * ############################################################################ */
+int CMP_PKIMESSAGE_check_implicitConfirm(CMP_PKIMESSAGE *msg)
+	{
+	int itavCount;
+	int i;
+	CMP_INFOTYPEANDVALUE *itav=NULL;
+
+	if (!msg) return 0;
+
+	itavCount = sk_CMP_INFOTYPEANDVALUE_num(msg->header->generalInfo);
+
+	for( i=0; i < itavCount; i++)
+		{
+		itav = sk_CMP_INFOTYPEANDVALUE_value(msg->header->generalInfo,i);
+		if (OBJ_obj2nid(itav->infoType) == NID_id_it_implicitConfirm)
+			return 1;
+		}
+
+	return 0;
+	}
+
+/* ############################################################################ * 
+ * push given itav to message header
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIHEADER_generalInfo_item_push0(CMP_PKIHEADER *hdr, const CMP_INFOTYPEANDVALUE *itav)
+	{
+	if( !hdr) goto err;
+
+	if( !CMP_ITAV_stack_item_push0(&hdr->generalInfo, itav))
+		goto err;
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ * 
+ * push itav to general message
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_PKIMESSAGE_genm_item_push0(CMP_PKIMESSAGE *msg, const CMP_INFOTYPEANDVALUE *itav)
+	{
+	if (!msg) goto err;
+
+	if (CMP_PKIMESSAGE_get_bodytype(msg) != V_CMP_PKIBODY_GENM) goto err;
+
+	if (!CMP_ITAV_stack_item_push0( &msg->body->value.genm, itav))
+		goto err;
+	return 1;
+err:
+	return 0;
+	}
+
+/* ############################################################################ * 
+ * push given itav to given stack
+ *
+ * @itav: a pointer to the infoTypeAndValue item to push on the stack.
+ *		  If NULL it will only made sure the stack exists, that might be
+ *		  needed for creating an empty general message
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CMP_ITAV_stack_item_push0(STACK_OF(CMP_INFOTYPEANDVALUE) **itav_sk_p, const CMP_INFOTYPEANDVALUE *itav)
+	{
+	int created = 0;
+
+	if (!itav_sk_p) goto err;
+
+	if (!*itav_sk_p)
+		{
+		/* not yet created */
+		if (!(*itav_sk_p = sk_CMP_INFOTYPEANDVALUE_new_null()))
+			goto err;
+		created = 1;
+		}
+	if (itav)
+		{
+		if (!sk_CMP_INFOTYPEANDVALUE_push(*itav_sk_p, itav)) goto err;
+		}
+	return 1;
+err:
+	if (created)
+		{
+		sk_CMP_INFOTYPEANDVALUE_pop_free(*itav_sk_p, CMP_INFOTYPEANDVALUE_free);
+		*itav_sk_p = NULL;
+		}
+	return 0;
+}
+
+/* ############################################################################ * 
+ * returns the PKIStatus of the given PKIStatusInfo
+ * returns -1 on error
+ * ############################################################################ */
+long CMP_PKISTATUSINFO_PKIstatus_get( CMP_PKISTATUSINFO *statusInfo)
+	{
+	if (!statusInfo) return -1;
+	if (!statusInfo->status) return -1;
+	return ASN1_INTEGER_get(statusInfo->status);
+	}
+
+/* ############################################################################ * 
+ * internal function
+ *
+ * convert PKIstatus to human readable string
+ *
+ * returns pointer to character array containing a sting representing the 
+ * PKIStatus of the given PKIStatusInfo
+ * returns NULL on error
+ * ############################################################################ */
+static char *CMP_PKISTATUSINFO_PKIstatus_get_string( CMP_PKISTATUSINFO *statusInfo)
+	{
+	long PKIstatus;
+
+	if (!statusInfo) return 0;
+
+	PKIstatus = CMP_PKISTATUSINFO_PKIstatus_get(statusInfo);
+	switch (PKIstatus)
+		{
+		case CMP_PKISTATUS_accepted:
+			return "PKIStatus: accepted";
+		case CMP_PKISTATUS_grantedWithMods:
+			return "PKIStatus: granded with mods";
+		case CMP_PKISTATUS_rejection:
+			return "PKIStatus: rejection";
+		case CMP_PKISTATUS_waiting:
+			return "PKIStatus: waiting";
+		case CMP_PKISTATUS_revocationWarning:
+			return "PKIStatus: revocation warning";
+		case CMP_PKISTATUS_revocationNotification:
+			return "PKIStatus: revocation notification";
+		case CMP_PKISTATUS_keyUpdateWarning:
+			return "PKIStatus: key update warning";
+		case -1:
+		default:
+			CMPerr(CMP_F_CMP_PKISTATUSINFO_PKISTATUS_GET_STRING, CMP_R_ERROR_PARSING_PKISTATUS);
+			return 0;
+		}
+	return 0;
+	}
+
+/* ############################################################################ * 
+ * internal function
+ *
+ * convert PKIstatus to human readable string
+ *
+ * returns pointer to string containing the the PKIFailureInfo
+ * returns NULL on error
+ * ############################################################################ */
+static char *CMP_PKISTATUSINFO_PKIFailureInfo_get_string( CMP_PKISTATUSINFO *statusInfo)
+	{
+	int i;
+
+	if (!statusInfo) return 0;
+	for (i=0; i <= CMP_PKIFAILUREINFO_MAX; i++)
+		{
+		if (ASN1_BIT_STRING_get_bit(statusInfo->failInfo, i))
+			{
+			switch (i)
+				{
+				case CMP_PKIFAILUREINFO_badAlg:
+					return "PKIFailureInfo: badAlg";
+				case CMP_PKIFAILUREINFO_badMessageCheck:
+					return "PKIFailureInfo: badMessageCheck";
+				case CMP_PKIFAILUREINFO_badRequest:
+					return "PKIFailureInfo: badRequest";
+				case CMP_PKIFAILUREINFO_badTime:
+					return "PKIFailureInfo: badTime";
+				case CMP_PKIFAILUREINFO_badCertId:
+					return "PKIFailureInfo: badCertId";
+				case CMP_PKIFAILUREINFO_badDataFormat:
+					return "PKIFailureInfo: badDataFormat";
+				case CMP_PKIFAILUREINFO_wrongAuthority:
+					return "PKIFailureInfo: wrongAuthority";
+				case CMP_PKIFAILUREINFO_incorrectData:
+					return "PKIFailureInfo: incorrectData";
+				case CMP_PKIFAILUREINFO_missingTimeStamp:
+					return "PKIFailureInfo: missingTimeStamp";
+				case CMP_PKIFAILUREINFO_badPOP:
+					return "PKIFailureInfo: badPOP";
+				case CMP_PKIFAILUREINFO_certRevoked:
+					return "PKIFailureInfo: certRevoked";
+				case CMP_PKIFAILUREINFO_certConfirmed:
+					return "PKIFailureInfo: certConfirmed";
+				case CMP_PKIFAILUREINFO_wrongIntegrity:
+					return "PKIFailureInfo: wrongIntegrity";
+				case CMP_PKIFAILUREINFO_badRecipientNonce:
+					return "PKIFailureInfo: badRecipientNonce";
+				case CMP_PKIFAILUREINFO_timeNotAvailable:
+					return "PKIFailureInfo: timeNotAvailable";
+				case CMP_PKIFAILUREINFO_unacceptedPolicy:
+					return "PKIFailureInfo: unacceptedPolicy";
+				case CMP_PKIFAILUREINFO_unacceptedExtension:
+					return "PKIFailureInfo: unacceptedExtension";
+				case CMP_PKIFAILUREINFO_addInfoNotAvailable:
+					return "PKIFailureInfo: addInfoNotAvailable";
+				case CMP_PKIFAILUREINFO_badSenderNonce:
+					return "PKIFailureInfo: badSenderNonce";
+				case CMP_PKIFAILUREINFO_badCertTemplate:
+					return "PKIFailureInfo: badCertTemplate";
+				case CMP_PKIFAILUREINFO_signerNotTrusted:
+					return "PKIFailureInfo: signerNotTrusted";
+				case CMP_PKIFAILUREINFO_transactionIdInUse:
+					return "PKIFailureInfo: transactionIdInUse";
+				case CMP_PKIFAILUREINFO_unsupportedVersion:
+					return "PKIFailureInfo: unsupportedVersion";
+				case CMP_PKIFAILUREINFO_notAuthorized:
+					return "PKIFailureInfo: notAuthorized";
+				case CMP_PKIFAILUREINFO_systemUnavail:
+					return "PKIFailureInfo: systemUnavail";
+				case CMP_PKIFAILUREINFO_systemFailure:
+					return "PKIFailureInfo: systemFailure";
+				case CMP_PKIFAILUREINFO_duplicateCertReq:
+					return "PKIFailureInfo: duplicateCertReq";
+				}
+			}
+		}
+	return 0;
+	}
+
+/* ############################################################################ *
+ * returns the PKIStatus of the given certReqId inside a Rev
+ * returns -1 on error
+ * ############################################################################ */
+long CMP_REVREPCONTENT_PKIStatus_get( CMP_REVREPCONTENT *revRep, long reqId)
+	{
+	CMP_PKISTATUSINFO *status=NULL;
+	if (!revRep) return -1;
+
+	if ( (status = sk_CMP_PKISTATUSINFO_value( revRep->status, reqId)) )
+		{
+		return CMP_PKISTATUSINFO_PKIstatus_get(status);
+		}
+
+	CMPerr(CMP_F_CMP_REVREPCONTENT_PKISTATUS_GET, CMP_R_ERROR_REQID_NOT_FOUND);
+	return -1;
+	}
+
+/* ############################################################################ *
+ * returns the PKIStatus of the given certReqId inside a CertRepMessage
+ * returns -1 on error
+ * ############################################################################ */
+long CMP_CERTREPMESSAGE_PKIStatus_get( CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	CMP_CERTRESPONSE *certResponse=NULL;
+	if (!certRep) return -1;
+
+	if ( (certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		{
+		return CMP_PKISTATUSINFO_PKIstatus_get(certResponse->status);
+		}
+
+	CMPerr(CMP_F_CMP_CERTREPMESSAGE_PKISTATUS_GET, CMP_R_ERROR_REQID_NOT_FOUND);
+	return -1;
+	}
+
+/* ############################################################################ * 
+ * returns pointer to PKIFailureInfo of given certRep message
+ * returns NULL on error or if no matching failInfo was found
+ * ############################################################################ */
+CMP_PKIFAILUREINFO *CMP_CERTREPMESSAGE_PKIFailureInfo_get0(CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	CMP_CERTRESPONSE *certResponse=NULL;
+	if (!certRep) return NULL;
+
+	if ( (certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		{
+		if (certResponse->status)
+			return certResponse->status->failInfo;
+		}
+
+	CMPerr(CMP_F_CMP_CERTREPMESSAGE_PKIFAILUREINFO_GET0, CMP_R_ERROR_REQID_NOT_FOUND);
+	return NULL;
+	}
+
+/* ############################################################################ * 
+ * returns pointer to PKIFailureInfoString character array of given certRep message
+ * returns NULL on error or if no matching failInfo was found
+ * ############################################################################ */
+char *CMP_CERTREPMESSAGE_PKIFailureInfoString_get0(CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	CMP_CERTRESPONSE *certResponse=NULL;
+	if (!certRep) return NULL;
+
+	if ( (certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		{
+		if (certResponse->status)
+			return CMP_PKISTATUSINFO_PKIFailureInfo_get_string(certResponse->status);
+		}
+
+	CMPerr(CMP_F_CMP_CERTREPMESSAGE_PKIFAILUREINFOSTRING_GET0, CMP_R_ERROR_REQID_NOT_FOUND);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * returns the status string of the given certReqId inside a CertRepMessage
+ * returns NULL on error
+ * ############################################################################ */
+STACK_OF(ASN1_UTF8STRING)* CMP_CERTREPMESSAGE_PKIStatusString_get0( CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	CMP_CERTRESPONSE *certResponse=NULL;
+	if (!certRep) return NULL;
+
+	if ( (certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		{
+		return certResponse->status->statusString;
+		}
+
+	CMPerr(CMP_F_CMP_CERTREPMESSAGE_PKISTATUSSTRING_GET0, CMP_R_ERROR_REQID_NOT_FOUND);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * checks bits in given PKIFailureInfo
+ * returns 1 if a given bit is set in a PKIFailureInfo
+ *				0 if			not set
+ *			   -1 on error
+ * PKIFailureInfo ::= ASN1_BIT_STRING
+ * ############################################################################ */
+int CMP_PKIFAILUREINFO_check( ASN1_BIT_STRING *failInfo, int codeBit)
+	{
+	if (!failInfo) return -1;
+	if ( (codeBit < 0) || (codeBit > CMP_PKIFAILUREINFO_MAX)) return -1;
+
+	return ASN1_BIT_STRING_get_bit( failInfo, codeBit);
+	}
+
+/* ############################################################################ *
+ * returns a pointer to the CertResponse with the given certReqId inside a CertRepMessage
+ * returns NULL on error or if no CertResponse available
+ * ############################################################################ */
+CMP_CERTRESPONSE *CMP_CERTREPMESSAGE_certResponse_get0( CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	CMP_CERTRESPONSE *certResponse=NULL;
+	int certRespCount;
+	int i;
+
+	if( !certRep) return NULL;
+
+	certRespCount = sk_CMP_CERTRESPONSE_num( certRep->response);
+
+	for( i=0; i < certRespCount; i++)
+		{
+		/* is it the right certReqId */
+		if( certReqId == ASN1_INTEGER_get(sk_CMP_CERTRESPONSE_value(certRep->response,i)->certReqId) )
+			{
+			certResponse = sk_CMP_CERTRESPONSE_value(certRep->response,i);
+			break;
+			}
+		}
+
+	return certResponse;
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * returns a pointer to a copy of the Certificate with the given certReqId inside a CertRepMessage
+ * returns NULL on error or if no Certificate available
+ * ############################################################################ */
+static X509 *CMP_CERTREPMESSAGE_cert_get1( CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	X509 *certCopy=NULL;
+	CMP_CERTRESPONSE *certResponse=NULL;
+
+	if( !certRep) return NULL;
+
+	if ( (certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		{
+		certCopy = X509_dup(certResponse->certifiedKeyPair->certOrEncCert->value.certificate);
+		}
+
+	return certCopy;
+	}
+
+/* ############################################################################# *
+ * internal function
+ *
+ * Decrypts the certificate with the given certReqId inside a CertRepMessage and
+ * this is needed for the indirect PoP method as in section 5.2.8.2
+ *
+ * returns a pointer to the decrypted certificate
+ * returns NULL on error or if no Certificate available
+ * ############################################################################# */
+static X509 *CMP_CERTREPMESSAGE_encCert_get1( CMP_CERTREPMESSAGE *certRep, long certReqId, EVP_PKEY *pkey)
+	{
+	CRMF_ENCRYPTEDVALUE *encCert   = NULL;
+	X509				*cert	   = NULL; /* decrypted certificate					  */
+	EVP_CIPHER_CTX		*evp_ctx   = NULL; /* context for symmetric encryption		  */
+	unsigned char		*ek		   = NULL; /* decrypted symmetric encryption key	  */
+	const EVP_CIPHER	*cipher    = NULL; /* used cipher							  */
+	unsigned char		*iv		   = NULL; /* initial vector for symmetric encryption */
+	unsigned char		*outbuf    = NULL; /* decryption output buffer				  */
+	const unsigned char *p		   = NULL; /* needed for decoding ASN1				  */
+	int					 symmAlg   = 0;    /* NIDs for symmetric algorithm            */
+	int					 n, outlen = 0;
+	EVP_PKEY_CTX		*pkctx	   = NULL; /* private key context */
+	CMP_CERTRESPONSE *certResponse = NULL;
+
+	if ( !(certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		goto err;
+
+	if ( !(encCert = certResponse->certifiedKeyPair->certOrEncCert->value.encryptedCert)) 
+		goto err;
+
+	if ( !(symmAlg = OBJ_obj2nid(encCert->symmAlg->algorithm)))
+		goto err;
+
+	/* first the symmetric key needs to be decrypted */
+	if ((pkctx = EVP_PKEY_CTX_new(pkey, NULL)) && EVP_PKEY_decrypt_init(pkctx))
+		{
+		ASN1_BIT_STRING *encKey = encCert->encSymmKey;
+		size_t eksize = 0;
+
+		if (EVP_PKEY_decrypt(pkctx, NULL, &eksize, encKey->data, encKey->length) <= 0
+			|| !(ek = OPENSSL_malloc(eksize))
+			|| EVP_PKEY_decrypt(pkctx, ek, &eksize, encKey->data, encKey->length) <= 0)
+			{
+			CMPerr(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1, CMP_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
+			goto err;
+			}
+		EVP_PKEY_CTX_free(pkctx);
+		}
+	else {
+		CMPerr(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1, CMP_R_ERROR_DECRYPTING_KEY);
+		goto err;
+		}
+
+	/* select symmetric cipher based on algorithm given in message */
+	if (!(cipher = EVP_get_cipherbynid(symmAlg)))
+		{
+		CMPerr(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1, CMP_R_UNSUPPORTED_CIPHER);
+		goto err;
+		}
+	if (!(iv = OPENSSL_malloc(cipher->iv_len))) goto err;
+	ASN1_TYPE_get_octetstring(encCert->symmAlg->parameter, iv, cipher->iv_len);
+
+	/* d2i_X509 changes the given pointer, so use p for decoding the message and keep the 
+	 * original pointer in outbuf so that the memory can be freed later */
+	if (!(p = outbuf = OPENSSL_malloc(encCert->encValue->length + cipher->block_size))) goto err;
+	evp_ctx = EVP_CIPHER_CTX_new();
+	EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
+
+	if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv)
+		|| !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen, encCert->encValue->data, encCert->encValue->length)
+		|| !EVP_DecryptFinal(evp_ctx, outbuf+outlen, &n))
+		{
+		CMPerr(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1, CMP_R_ERROR_DECRYPTING_CERTIFICATE);
+		goto err;
+		}
+	outlen += n;
+
+	/* convert decrypted certificate from DER to internal ASN.1 structure */
+	if (!(cert = d2i_X509(NULL, &p, outlen)))
+		{
+		CMPerr(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1, CMP_R_ERROR_DECODING_CERTIFICATE);
+		goto err;
+		}
+
+	OPENSSL_free(outbuf);
+	EVP_CIPHER_CTX_free(evp_ctx);
+	OPENSSL_free(ek);
+	OPENSSL_free(iv);
+	return cert;
+err:
+	CMPerr(CMP_F_CMP_CERTREPMESSAGE_ENCCERT_GET1, CMP_R_ERROR_DECRYPTING_ENCCERT);
+	if (outbuf) OPENSSL_free(outbuf);
+	if (evp_ctx) EVP_CIPHER_CTX_free(evp_ctx);
+	if (ek) OPENSSL_free(ek);
+	if (iv) OPENSSL_free(iv);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * returns the type of the certificate contained in the certificate response
+ * returns -1 on errror
+ * ############################################################################ */
+int CMP_CERTREPMESSAGE_certType_get( CMP_CERTREPMESSAGE *certRep, long certReqId)
+	{
+	CMP_CERTRESPONSE *certResponse=NULL;
+
+	if( !certRep) return -1;
+	if( !(certResponse = CMP_CERTREPMESSAGE_certResponse_get0( certRep, certReqId)) )
+		return -1;
+
+	return certResponse->certifiedKeyPair->certOrEncCert->type;
+	}
+
+/* ############################################################################ *
+ * returns 1 on success
+ * returns 0 on error
+ * ############################################################################ */
+int CMP_PKIMESSAGE_set_bodytype( CMP_PKIMESSAGE *msg, int type)
+	{
+	if( !msg) return 0;
+
+	msg->body->type = type;
+
+	return 1;
+	}
+
+/* ############################################################################ *
+ * returns the body type of the given CMP message
+ * returns -1 on error
+ * ############################################################################ */
+int CMP_PKIMESSAGE_get_bodytype( CMP_PKIMESSAGE *msg)
+	{
+	if( !msg) return -1;
+
+	return msg->body->type;
+	}
+
+/* ############################################################################ *
+ * return pointer to human readable error message string created out of the
+ * information extracted from given error message
+ * returns NULL on error
+ * ############################################################################ */
+char *CMP_PKIMESSAGE_parse_error_msg( CMP_PKIMESSAGE *msg, char *errormsg, int bufsize)
+	{
+	char *status, *failureinfo;
+
+	if( !msg) return NULL;
+	if( CMP_PKIMESSAGE_get_bodytype(msg) != V_CMP_PKIBODY_ERROR) return NULL;
+
+	status = CMP_PKISTATUSINFO_PKIstatus_get_string(msg->body->value.error->pKIStatusInfo);
+	if (!status)
+		{
+		CMPerr(CMP_F_CMP_PKIMESSAGE_PARSE_ERROR_MSG, CMP_R_ERROR_PARSING_ERROR_MESSAGE);
+		return NULL;
+		}
+
+	/* PKIFailureInfo is optional */
+	failureinfo = CMP_PKISTATUSINFO_PKIFailureInfo_get_string(msg->body->value.error->pKIStatusInfo);
+
+	STACK_OF(ASN1_UTF8STRING) *details = msg->body->value.error->pKIStatusInfo->statusString;
+	ASN1_UTF8STRING *str = 0;
+	if (details && sk_ASN1_UTF8STRING_num(details) > 0)
+		str = sk_ASN1_UTF8STRING_value(details, 0);
+
+	if (failureinfo && str && str->data) {
+		BIO_snprintf(errormsg, bufsize, "%s, %s: %s", status, failureinfo,
+					 str->data);
+	}
+	else if (failureinfo)
+		BIO_snprintf(errormsg, bufsize, "%s, %s", status, failureinfo);
+	else
+		BIO_snprintf(errormsg, bufsize, "%s", status);
+
+	return errormsg;
+	}
+
+/* ############################################################################ *
+ * Retrieve the returned certificate from the given certrepmessage.
+ * returns NULL if not found
+ * TODO: create another function handing multiple certreps when 2 certificates
+ * had been requested
+ * ############################################################################ */
+X509 *CMP_CERTREPMESSAGE_get_certificate(CMP_CTX *ctx, CMP_CERTREPMESSAGE *certrep)
+	{
+	X509 *newClCert = NULL;
+	int repNum = 0;
+
+	/* Get the certReqId of the first certresponse. Need to do it this way instead
+	 * of just using certReqId==0, because in error cases the server might reply with a certReqId
+	 * of -1... */
+	if (sk_CMP_CERTRESPONSE_num(certrep->response) > 0)
+		repNum = ASN1_INTEGER_get(sk_CMP_CERTRESPONSE_value(certrep->response, 0)->certReqId);
+	
+	CMP_CTX_set_failInfoCode(ctx, CMP_CERTREPMESSAGE_PKIFailureInfo_get0(certrep, repNum));
+
+	ctx->lastPKIStatus = CMP_CERTREPMESSAGE_PKIStatus_get( certrep, repNum);
+	switch (ctx->lastPKIStatus)
+		{
+		case CMP_PKISTATUS_waiting:
+			goto err;
+			break;
+
+		case CMP_PKISTATUS_grantedWithMods:
+			CMP_printf( ctx, "WARNING: got \"grantedWithMods\"");
+
+		case CMP_PKISTATUS_accepted:
+			/* if we received a certificate then place it to ctx->newClCert and return,
+			 * if the cert is encrypted then we first decrypt it. */
+			switch (CMP_CERTREPMESSAGE_certType_get(certrep, repNum))
+				{
+				case CMP_CERTORENCCERT_CERTIFICATE:
+					if( !(newClCert = CMP_CERTREPMESSAGE_cert_get1(certrep,repNum)))
+						{
+						CMPerr(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE, CMP_R_CERTIFICATE_NOT_FOUND);
+						goto err;
+						}
+					break;
+					/* certificate encrypted for PoP using indirect method according to section 5.2.8.2 */
+				case CMP_CERTORENCCERT_ENCRYPTEDCERT:
+					if( !(newClCert = CMP_CERTREPMESSAGE_encCert_get1(certrep,repNum,ctx->newPkey)))
+						{
+						CMPerr(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE, CMP_R_CERTIFICATE_NOT_FOUND);
+						goto err;
+						}					
+					break;
+				default:
+					CMPerr(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE, CMP_R_UNKNOWN_CERTTYPE);
+					goto err;
+				}
+			break;
+
+			/* get all information in case of a rejection before going to error */
+		case CMP_PKISTATUS_rejection: {
+			char *failInfoString = NULL;
+			char *statusString = NULL;
+			int statusLen = 0;
+			ASN1_UTF8STRING *status = NULL;
+			STACK_OF(ASN1_UTF8STRING) *strstack = CMP_CERTREPMESSAGE_PKIStatusString_get0(certrep, repNum);
+
+			CMPerr(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE, CMP_R_REQUEST_REJECTED_BY_CA);
+
+			failInfoString = CMP_CERTREPMESSAGE_PKIFailureInfoString_get0(certrep, repNum);
+			if (failInfoString)
+				/* initialize status string with human readable failure info */
+				statusString = OPENSSL_strdup(failInfoString);
+			else
+				statusString = OPENSSL_strdup("<no failure info received>");
+
+			statusLen = strlen(statusString)+18;
+			statusString = OPENSSL_realloc(statusString, statusLen);
+			strcat(statusString, ", statusString: \""); /* length = 17 */
+
+			while ((status = sk_ASN1_UTF8STRING_pop(strstack)))
+				{
+				statusLen += strlen((char*)status->data)+1;
+				statusString = OPENSSL_realloc(statusString, statusLen);
+				if (!statusString) goto err;
+				strcat(statusString, (char*)status->data);
+				strcat(statusString, " "); 
+				}
+
+			strcat(statusString, "\"");
+			ERR_add_error_data(1, statusString);
+
+			goto err;
+			break;
+			}
+
+		case CMP_PKISTATUS_revocationWarning:
+		case CMP_PKISTATUS_revocationNotification:
+		case CMP_PKISTATUS_keyUpdateWarning:
+			CMPerr(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE, CMP_R_NO_CERTIFICATE_RECEIVED);
+			goto err;
+			break;
+
+		default: {
+			STACK_OF(ASN1_UTF8STRING) *strstack = CMP_CERTREPMESSAGE_PKIStatusString_get0(certrep, 0);
+			ASN1_UTF8STRING *status = NULL;
+
+			CMPerr(CMP_F_CMP_CERTREPMESSAGE_GET_CERTIFICATE, CMP_R_UNKNOWN_PKISTATUS);
+			while ((status = sk_ASN1_UTF8STRING_pop(strstack)))
+				ERR_add_error_data(3, "statusString=\"", status->data, "\"");
+
+			CMP_printf( ctx, "ERROR: unknown pkistatus %ld", CMP_CERTREPMESSAGE_PKIStatus_get( certrep, repNum));
+			goto err;
+			break;
+			}
+		}
+
+	return newClCert;
+err:
+	return NULL;
+	}
+
+/* ################################################################ *
+ * Builds up the certificate chain of cert as high up as possible using
+ * the given X509_STORE containing all possible intermediate certificates and
+ * optionally the (possible) trust anchor(s).
+ *
+ * Intended use of this function is to find all the certificates below the trust
+ * anchor needed to verify an EE's own certificate.  Those are supposed to be
+ * included in the ExtraCerts field of every first sent message of an tansaction 
+ * when MSG_SIG_ALG is utilized.
+ * 
+ * NOTE: This creates duplicates of each certificate,
+ * so when the stack is no longer needed it should be freed with
+ * sk_X509_pop_free()
+ * NOTE: in case there are more than one possibilities for certificates up the
+ * chain, OpenSSL seems to take the first one, check X509_verify_cert() for
+ * details.
+ *
+ * returns a pointer to a stack of (duplicated) X509 certificates containing:
+ *	- the EE certificate given in the function arguments (cert)
+ *	- all intermediate certificates up the chain towards the trust anchor
+ *	- the trust anchor if it was included in the store
+ *	returns NULL on error
+ * ################################################################ */
+STACK_OF(X509) *CMP_build_cert_chain(X509_STORE *store, X509 *cert)
+	{
+	STACK_OF(X509) *chain = NULL, *chainDup = NULL;
+	X509_STORE_CTX *csc = NULL;
+	int i=0;
+
+	if (!store || !cert) goto err;
+
+	csc = X509_STORE_CTX_new();
+	if (!csc) goto err;
+
+	/* chainDup to store the duplicated certificates */
+	chainDup = sk_X509_new_null();
+	if (!chainDup) goto err;
+
+	X509_STORE_set_flags(store, 0); /* clear all flags, e.g. do not check CRLs */
+	if(!X509_STORE_CTX_init(csc,store,cert,NULL))
+		goto err;
+
+	X509_verify_cert(csc); /* ignore return value as it would fail without trust anchor given in store */
+
+	chain = X509_STORE_CTX_get_chain(csc);
+	for (i = 0; i < sk_X509_num(chain); i++)
+		{
+		X509 *certDup = X509_dup( sk_X509_value(chain, i) );
+		sk_X509_push(chainDup, certDup);
+		}
+
+	X509_STORE_CTX_free(csc);
+
+	return chainDup;
+
+err:
+	if (csc) X509_STORE_CTX_free(csc);
+	if (chainDup) sk_X509_free(chainDup);
+	return NULL;
+	}
+
+/* ############################################################################ 
+ * this function is inteded to be used only within the CMP library although it is
+ * included in cmp.h
+ *
+ * Returns the subject key identifier of the given certificate
+ * returns NULL on error, respecively when none was found.
+ * ############################################################################ */
+ASN1_OCTET_STRING *CMP_get_cert_subject_key_id(const X509 *cert)
+	{
+	unsigned char *subjKeyIDStrDer = NULL;
+	X509_EXTENSION *ex = NULL;
+	int subjKeyIDLoc = -1;
+
+	if(!cert) goto err;
+
+	subjKeyIDLoc = X509_get_ext_by_NID( (X509*) cert, NID_subject_key_identifier, -1);
+	if (subjKeyIDLoc == -1) goto err;
+
+	/* found a subject key ID */
+	if(!(ex = sk_X509_EXTENSION_value( cert->cert_info->extensions, subjKeyIDLoc))) goto err;
+
+	subjKeyIDStrDer = ex->value->data;
+	return d2i_ASN1_OCTET_STRING( NULL, (const unsigned char **) &subjKeyIDStrDer, ex->value->length);
+err:
+	return NULL;
+	}
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_msg.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_msg.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_msg.c	(revision 764)
@@ -0,0 +1,533 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* crypto/cmp/cmp_msg.c
+ * Functions for creating CMP (RFC 4210) messages for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2014 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/cmp.h>
+#include <openssl/x509.h>
+#include <openssl/safestack.h>
+#include <openssl/err.h>
+
+#include <string.h>
+
+/* ############################################################################ 
+ * Takes a stack of GENERAL_NAMEs and adds them to the given extension stack.
+ * this is used to setting subject alternate names to a certTemplate
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+static int add_altname_extensions(X509_EXTENSIONS **extensions, STACK_OF(GENERAL_NAME) *altnames, int critical)
+	{
+	X509_EXTENSION *ext = NULL;
+	unsigned char *der = NULL;
+	int derlen = 0;
+	ASN1_OCTET_STRING *str = NULL;;
+
+	if(!extensions) goto err;
+	if(!altnames) goto err;
+
+	if(!(str = ASN1_OCTET_STRING_new())) goto err;
+
+	if(!(ASN1_seq_pack_GENERAL_NAME(altnames, i2d_GENERAL_NAME, &der, &derlen))) goto err;
+
+	if(!ASN1_STRING_set(str, der, derlen)) goto err;
+	if(!X509_EXTENSION_create_by_NID(&ext, NID_subject_alt_name, critical, str)) goto err;
+
+	ASN1_OCTET_STRING_free(str);
+	OPENSSL_free(der);
+
+	if(!X509v3_add_ext(extensions, ext, 0)) goto err;
+
+	X509_EXTENSION_free(ext);
+
+	return 1;
+err:
+	if (ext) X509_EXTENSION_free(ext);
+	return 0;
+	}
+
+/* ############################################################################ 
+ * Takes a CERTIFICATEPOLICIES structure and adds it to the given extension stack.
+ * this is used to setting certificate policy OIDs to a certTemplate
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+static int add_policy_extensions(X509_EXTENSIONS **extensions, CERTIFICATEPOLICIES *policies)
+	{
+	X509_EXTENSION *ext = NULL;
+	unsigned char *der = NULL;
+	int derlen = 0;
+	ASN1_OCTET_STRING *str = NULL;
+
+	if(!extensions || !policies) goto err;
+
+	if(!(str = ASN1_OCTET_STRING_new())) goto err;
+
+	derlen = i2d_CERTIFICATEPOLICIES(policies, &der);
+	if(!ASN1_STRING_set(str, der, derlen)) goto err;
+	if(!X509_EXTENSION_create_by_NID(&ext, NID_certificate_policies, 1, str)) goto err;
+
+	ASN1_OCTET_STRING_free(str);
+	OPENSSL_free(der);
+
+	if(!X509v3_add_ext(extensions, ext, 0)) goto err;
+
+	X509_EXTENSION_free(ext);
+
+	return 1;
+err:
+	if (ext) X509_EXTENSION_free(ext);
+	return 0;
+	}
+
+/* ############################################################################
+ * Adds the certificates to the extraCerts fields in the given message.  For
+ * this it tries to build the certificate chain of our client cert (ctx->clCert)
+ * by using certificates in ctx->untrusted_store. If no untrusted store is set, 
+ * it will at least place the client certificate into extraCerts.
+ * Additionally all the certificates explicitly specified to be sent out
+ * (i.e. ctx->extraCertsOut) are added to the stack.
+ *
+ * Note: it will NOT put the trust anchor in the extraCerts - unless it would be
+ * in the untrusted store.
+ *
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+static int add_extraCerts(CMP_CTX *ctx, CMP_PKIMESSAGE *msg)
+	{
+	int i;
+
+	if (!ctx) goto err;
+	if (!msg) goto err;
+	if (!msg->extraCerts && !(msg->extraCerts = sk_X509_new_null())) goto err;
+
+	/* add any additional certificates from ctx->extraCertsOut */
+	for (i = 0; i < sk_X509_num(ctx->extraCertsOut); i++)
+		sk_X509_push(msg->extraCerts, X509_dup(sk_X509_value(ctx->extraCertsOut, i)));
+
+	if (ctx->clCert)
+		{
+		/* if we have untrusted store, try to add all the intermediate certs and our own */
+		if (ctx->untrusted_store)
+			{
+			STACK_OF(X509) *chain = CMP_build_cert_chain(ctx->untrusted_store, ctx->clCert);
+			int i;
+			for(i = 0; i < sk_X509_num(chain); i++)
+				{
+				X509 *cert = sk_X509_value(chain, i);
+				sk_X509_push(msg->extraCerts, cert);
+				}
+			sk_X509_free(chain); /* only frees the stack, not the content */
+			} else {
+			/* Make sure that at least our own cert gets sent */
+			sk_X509_push(msg->extraCerts, X509_dup(ctx->clCert));
+			}
+		}
+
+	return 1;
+
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * Creates a new polling request PKIMessage for the given request ID
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * ############################################################################ */
+CMP_PKIMESSAGE * CMP_pollReq_new( CMP_CTX *ctx, int reqId)
+	{
+	CMP_PKIMESSAGE *msg = NULL;
+	CMP_POLLREQ    *preq = NULL;
+	if (!ctx) goto err;
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if( !CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_POLLREQ);
+
+	if(!(preq = CMP_POLLREQ_new())) goto err;
+	/* TODO support multiple cert request ids to poll */
+	ASN1_INTEGER_set(preq->certReqId, reqId);
+	if (!(msg->body->value.pollReq = sk_CMP_POLLREQ_new_null()))
+		goto err;
+
+	sk_CMP_POLLREQ_push(msg->body->value.pollReq, preq);
+
+	if(!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	return msg;
+err:
+	CMPerr(CMP_F_CMP_POLLREQ_NEW, CMP_R_ERROR_CREATING_POLLREQ);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Create a new Initial Request PKIMessage based on the settings in given ctx
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * ############################################################################ */
+CMP_PKIMESSAGE * CMP_ir_new( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE	*msg=NULL;
+	CRMF_CERTREQMSG *certReq0=NULL;
+	X509_EXTENSIONS *extensions = NULL;
+	X509_NAME *subject=NULL;
+
+	if (!ctx) goto err;
+
+	/* for authentication we need either a reference value/secret or external identity certificate (E.7) and private key */
+	if (!((ctx->referenceValue && ctx->secretValue) || (ctx->pkey && ctx->clCert))) goto err;
+
+	/* new key pair for new Certificate must be set */
+	if (!ctx->newPkey) goto err;
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if (!CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+
+	if (ctx->implicitConfirm)
+		if (! CMP_PKIMESSAGE_set_implicitConfirm(msg)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_IR);
+
+	if (ctx->subjectName)
+		subject = ctx->subjectName;
+	else if (ctx->clCert && sk_GENERAL_NAME_num(ctx->subjectAltNames) <= 0)
+		/* get subject name from existing certificate (E.7) */
+		subject = X509_get_subject_name(ctx->clCert);
+	else
+		subject = NULL;
+
+	if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0)
+		/* According to RFC5280, subjectAltName MUST be critical if subject is null */
+		add_altname_extensions(&extensions, ctx->subjectAltNames, ctx->setSubjectAltNameCritical || subject == NULL);
+
+	if (ctx->policies)
+		add_policy_extensions(&extensions, ctx->policies);
+
+	if (!(msg->body->value.ir = sk_CRMF_CERTREQMSG_new_null())) goto err;
+	if (!(certReq0 = CRMF_cr_new(0L, ctx->newPkey, subject, extensions))) goto err;
+	sk_CRMF_CERTREQMSG_push( msg->body->value.ir, certReq0);
+	/* TODO: here also the optional 2nd certreqmsg could be pushed to the stack */
+
+    /* sets the id-regCtrl-regToken to regInfo (not described in RFC, but EJBCA
+	 * in CA mode might insist on that) */
+	if (ctx->regToken)
+		if (!CRMF_CERTREQMSG_set1_regInfo_regToken(certReq0, ctx->regToken)) goto err;
+
+	CRMF_CERTREQMSG_calc_and_set_popo( certReq0, ctx->newPkey, ctx->popoMethod);
+
+	add_extraCerts(ctx, msg);
+	if (!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	/* cleanup */
+	if (extensions) sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free);
+	
+	return msg;
+
+err:
+	CMPerr(CMP_F_CMP_IR_NEW, CMP_R_ERROR_CREATING_IR);
+	if (extensions) sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Creates a new Revocation Request PKIMessage based on the settings in ctx
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * ############################################################################ */
+CMP_PKIMESSAGE * CMP_rr_new( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE	*msg=NULL;
+	CRMF_CERTTEMPLATE *certTpl=NULL;
+	X509_NAME *subject=NULL;
+	CMP_REVDETAILS *rd=NULL;
+
+	if (!ctx) goto err;
+	if (!ctx->clCert) goto err;
+	if (!ctx->pkey) goto err;
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if (!CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_RR);
+
+	if (!(msg->body->value.rr = sk_CMP_REVDETAILS_new_null())) goto err;
+	if (!(rd = CMP_REVDETAILS_new())) goto err;
+	sk_CMP_REVDETAILS_push( msg->body->value.rr, rd);
+
+	if (!(certTpl = CRMF_CERTTEMPLATE_new())) goto err;
+	rd->certDetails = certTpl;
+
+	/* Set the subject from the previous certificate */
+	if (!(subject = X509_get_subject_name(ctx->clCert))) goto err;
+	X509_NAME_set(&certTpl->subject, subject);
+	X509_PUBKEY_set(&certTpl->publicKey, ctx->pkey);
+	if (!(certTpl->serialNumber = ASN1_INTEGER_dup(ctx->clCert->cert_info->serialNumber))) goto err;
+	X509_NAME_set(&certTpl->issuer, ctx->clCert->cert_info->issuer);
+
+	/* TODO: the Revocation Passphrase according to section 5.3.19.9 could be set here if set in ctx */
+
+	if(!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	return msg;
+
+err:
+	CMPerr(CMP_F_CMP_RR_NEW, CMP_R_ERROR_CREATING_RR);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Creates a new Certificate Request PKIMessage based on the settings in ctx
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * ############################################################################ */
+CMP_PKIMESSAGE * CMP_cr_new( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE	*msg=NULL;
+	CRMF_CERTREQMSG *certReq0=NULL;
+	X509_NAME *subject=NULL;
+
+	if (!ctx) goto err;
+	/* for authentication we need either a reference value/secret for MSG_MAC_ALG 
+	 * or existing certificate and private key for MSG_SIG_ALG */
+	if (!((ctx->referenceValue && ctx->secretValue) || (ctx->pkey && ctx->clCert))) goto err;
+	if (!ctx->pkey) goto err;
+
+	if (ctx->subjectName)
+		subject = ctx->subjectName;
+	else if (ctx->clCert) /* get subject name from existing certificate */
+		subject = X509_get_subject_name(ctx->clCert);
+	else
+		goto err;
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if (!CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+	if (ctx->implicitConfirm)
+		if (! CMP_PKIMESSAGE_set_implicitConfirm(msg)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_CR);
+
+	if (!(msg->body->value.cr = sk_CRMF_CERTREQMSG_new_null())) goto err;
+	if (!(certReq0 = CRMF_cr_new(0L, ctx->pkey, subject, NULL))) goto err;
+	sk_CRMF_CERTREQMSG_push( msg->body->value.cr, certReq0);
+	/* TODO: here also the optional 2nd certreqmsg could be pushed to the stack */
+
+	CRMF_CERTREQMSG_calc_and_set_popo( certReq0, ctx->pkey, ctx->popoMethod);
+
+	add_extraCerts(ctx, msg);
+	if (!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	return msg;
+
+err:
+	CMPerr(CMP_F_CMP_CR_NEW, CMP_R_ERROR_CREATING_CR);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Creates a new Key Update Request PKIMessage based on the settings in ctx
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * TODO: the differentiation between certificate used to sign the CMP messages
+ * and the certificate to update should be improved - so far only the clCert
+ * could be updated
+ * ############################################################################ */
+CMP_PKIMESSAGE * CMP_kur_new( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *msg=NULL;
+	CRMF_CERTREQMSG *certReq0=NULL;
+	X509_EXTENSIONS *extensions = NULL;
+	X509_NAME *subject=NULL;
+
+	if (!ctx) goto err;
+	/* for authentication we need either a reference value/secret for MSG_MAC_ALG 
+	 * or existing certificate and private key for MSG_SIG_ALG */
+	if (!((ctx->referenceValue && ctx->secretValue) || (ctx->pkey && ctx->clCert))) goto err;
+	if (!ctx->newPkey) goto err;
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if (!CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+	if (ctx->implicitConfirm)
+		if (! CMP_PKIMESSAGE_set_implicitConfirm( msg)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_KUR);
+
+	if (ctx->subjectName)
+		subject = ctx->subjectName;
+	else
+		subject = X509_get_subject_name( (X509*) ctx->clCert); /* TODO: from certificate to be renewed */
+
+	if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0)
+		/* According to RFC5280, subjectAltName MUST be critical if subject is null */
+		add_altname_extensions(&extensions, ctx->subjectAltNames, ctx->setSubjectAltNameCritical || subject == NULL);
+
+	if (ctx->policies)
+		add_policy_extensions(&extensions, ctx->policies);
+
+	if (!(msg->body->value.kur = sk_CRMF_CERTREQMSG_new_null())) goto err;
+	if (!(certReq0 = CRMF_cr_new(0L, ctx->newPkey, subject, extensions))) goto err;
+	sk_CRMF_CERTREQMSG_push( msg->body->value.kur, certReq0);
+	/* TODO: here also the optional 2nd certreqmsg could be pushed to the stack */
+
+	/* setting OldCertId according to D.6:
+	   7.  regCtrl OldCertId SHOULD be used */
+
+	if (ctx->oldClCert)
+		CRMF_CERTREQMSG_set1_control_oldCertId( certReq0, ctx->oldClCert);
+	else
+		CRMF_CERTREQMSG_set1_control_oldCertId( certReq0, ctx->clCert);
+
+
+	CRMF_CERTREQMSG_calc_and_set_popo( certReq0, ctx->newPkey, ctx->popoMethod);
+
+	add_extraCerts(ctx, msg);
+	if (!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	if (extensions) sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free);
+
+	return msg;
+
+err:
+	CMPerr(CMP_F_CMP_KUR_NEW, CMP_R_ERROR_CREATING_KUR);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+	if (extensions) sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Creates a new Certificate Confirmation PKIMessage
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * TODO: handle both possible certificates when signing and encrypting
+ * certificates have been requested/received
+ * ############################################################################ */
+CMP_PKIMESSAGE * CMP_certConf_new( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *msg=NULL;
+	CMP_CERTSTATUS *certStatus=NULL;
+
+	if (!ctx) goto err;
+	/* for authentication we need either a reference value/secret for MSG_MAC_ALG 
+	 * or existing certificate and private key for MSG_SIG_ALG */
+	if (!((ctx->referenceValue && ctx->secretValue) || (ctx->pkey && ctx->clCert))) goto err;
+	if (!ctx->newClCert) goto err; /* in this case we wouldn't have received a certificate */
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if (!CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_CERTCONF);
+	if (!(msg->body->value.certConf = sk_CMP_CERTSTATUS_new_null())) goto err;
+
+	if (!(certStatus = CMP_CERTSTATUS_new())) goto err;
+	if (!sk_CMP_CERTSTATUS_push( msg->body->value.certConf, certStatus)) goto err;
+	/* set the # of the certReq */
+	ASN1_INTEGER_set(certStatus->certReqId,0L);
+	/* -- the hash of the certificate, using the same hash algorithm
+	 * -- as is used to create and verify the certificate signature */
+	CMP_CERTSTATUS_set_certHash( certStatus, ctx->newClCert);
+
+	/* execute the callback function set in ctx which can be used to examine a
+	 * certificate and reject it */
+	if (ctx->certConf_cb && ctx->newClCert && ctx->certConf_cb(ctx->lastPKIStatus, ctx->newClCert) == 0)
+		{
+		certStatus->statusInfo = CMP_PKISTATUSINFO_new();
+		ASN1_INTEGER_set(certStatus->statusInfo->status, CMP_PKISTATUS_rejection);
+		CMP_printf(ctx, "INFO: rejecting certificate.");
+		}
+
+	if (!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	return msg;
+
+err:
+	CMPerr(CMP_F_CMP_CERTCONF_NEW, CMP_R_ERROR_CREATING_CERTCONF);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Creates a new General Message with an empty itav stack
+ * returns a pointer to the PKIMessage on success, NULL on error
+ * ############################################################################ */
+CMP_PKIMESSAGE *CMP_genm_new( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *msg=NULL;
+
+	if (!ctx) goto err;
+
+	if (!(msg = CMP_PKIMESSAGE_new())) goto err;
+	if (!CMP_PKIHEADER_init( ctx, msg->header)) goto err;
+	CMP_PKIMESSAGE_set_bodytype( msg, V_CMP_PKIBODY_GENM);
+	if (!(msg->body->value.genm = sk_CMP_INFOTYPEANDVALUE_new_null())) goto err; /* initialize with empty stack */
+
+	if (!CMP_PKIMESSAGE_protect(ctx, msg)) goto err;
+
+	return msg;
+
+err:
+	CMPerr(CMP_F_CMP_GENM_NEW, CMP_R_ERROR_CREATING_GENM);
+	if (msg) CMP_PKIMESSAGE_free(msg);
+	return NULL;
+	}
+
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_ses.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_ses.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_ses.c	(revision 764)
@@ -0,0 +1,866 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+ /* crypto/cmp/cmp_ses.c
+ * Functions to do CMP (RFC 4210) message sequences for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <string.h>
+
+#include <openssl/cmp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+#include <unistd.h>
+
+/* XXX this is here to fool the openssl perl script that checks errors codes strictly
+ *     without func() the macro below would cause the script to complain */
+#if 0
+static void func() { }
+#endif
+/* adds connection error information to OpenSSL error queue */
+#define ADD_HTTP_ERROR_INFO(cmp_f_func, errcode, msg)\
+		if (ERR_GET_REASON(ERR_peek_last_error()) != CMP_R_NULL_ARGUMENT\
+			&& ERR_GET_REASON(ERR_peek_last_error()) != CMP_R_SERVER_NOT_REACHABLE)\
+			CMPerr(cmp_f_func, errcode);\
+		else\
+			add_error_data("unable to send "msg);
+
+/* ############################################################################ *
+ * table used to translate PKIMessage body type number into a printable string
+ * ############################################################################ */
+static char *V_CMP_TABLE[] = {
+	"IR",
+	"IP",
+	"CR",
+	"CP",
+	"P10CR",
+	"POPDECC",
+	"POPDECR",
+	"KUR",
+	"KUP",
+	"KRR",
+	"KRP",
+	"RR",
+	"RP",
+	"CCR",
+	"CCP",
+	"CKUANN",
+	"CANN",
+	"RANN",
+	"CRLANN",
+	"PKICONF",
+	"NESTED",
+	"GENM",
+	"GENP",
+	"ERROR",
+	"CERTCONF",
+	"POLLREQ",
+	"POLLREP",
+};
+
+#define MSG_TYPE_STR(type)	\
+	(((unsigned int) (type) < sizeof(V_CMP_TABLE)/sizeof(V_CMP_TABLE[0])) \
+	 ? V_CMP_TABLE[(unsigned int)(type)] : "unknown")
+
+/* ############################################################################ * 
+ * internal function
+ *
+ * Prints error data of the given CMP_PKIMESSAGE into a buffer specified by out
+ * and returns pointer to the buffer.
+ * ############################################################################ */
+static char *PKIError_data(CMP_PKIMESSAGE *msg, char *out, int outsize)
+	{
+	char tempbuf[1024];
+	switch (CMP_PKIMESSAGE_get_bodytype(msg))
+		{
+		case V_CMP_PKIBODY_ERROR:
+			BIO_snprintf(out, outsize, "bodytype=%d, error=\"%s\"",
+				V_CMP_PKIBODY_ERROR,
+				CMP_PKIMESSAGE_parse_error_msg( msg, tempbuf, sizeof(tempbuf)));
+			break;
+		case -1:
+			BIO_snprintf(out, outsize, "received NO message");
+			break;
+		default:
+			BIO_snprintf(out, outsize, "received unexpected message of type '%s'", MSG_TYPE_STR(CMP_PKIMESSAGE_get_bodytype( msg)));
+			break;
+		}
+	return out;
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * Adds text to the extra error data field of the last error in openssl's error
+ * queue. ERR_add_error_data() simply overwrites the previous contents of the error
+ * data, while this function can be used to add a string to the end of it.
+ * ############################################################################ */
+static void add_error_data(const char *txt)
+	{
+	const char *current_error=NULL;
+	ERR_peek_last_error_line_data(NULL, NULL, &current_error, NULL);
+	ERR_add_error_data(3, current_error, ":", txt);
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * When a 'waiting' PKIStatus has been received, this function is used to attempt
+ * to poll for a response message. 
+ *
+ * A maxPollTime timeout can be set in the context.  The function will continue
+ * to poll until the timeout is reached and then poll a last time even when that
+ * is before the "checkAfter" sent by the server.  If ctx->maxPollTime is 0, the
+ * timeout is disabled.
+ *
+ * returns 1 on success, returns received PKIMESSAGE in *msg argument
+ * returns 0 on error or when timeout is reached without a received messsage
+ *
+ * TODO handle multiple pollreqs for multiple certificates
+ * ############################################################################ */
+static int pollForResponse(CMP_CTX *ctx, CMP_CERTREPMESSAGE *certrep, CMP_PKIMESSAGE **msg)
+	{
+	int maxTimeLeft = ctx->maxPollTime;
+	CMP_PKIMESSAGE *preq = NULL;
+	CMP_PKIMESSAGE *prep = NULL;
+	CMP_POLLREP *pollRep = NULL;
+
+	CMP_printf(ctx, "INFO: Received 'waiting' PKIStatus, attempting to poll server for response.");
+	for (;;)
+		{
+		if(!(preq = CMP_pollReq_new(ctx, 0))) goto err; /* TODO: this only handles one certificate request so far */
+
+
+		CMP_printf(ctx, "INFO: Sending polling request...");
+		/* immediately send the first pollReq */
+		if (! (CMP_PKIMESSAGE_http_perform(ctx, preq, &prep)))
+			{
+			/* set message to error stack */
+			ADD_HTTP_ERROR_INFO(CMP_F_POLLFORRESPONSE, CMP_R_POLLREP_NOT_RECEIVED, "pollReq");
+			goto err;
+			}
+
+		/* handle potential pollRep */
+		if (CMP_PKIMESSAGE_get_bodytype(prep) == V_CMP_PKIBODY_POLLREP)
+			{
+			int checkAfter;
+			if(!(pollRep = sk_CMP_POLLREP_value(prep->body->value.pollRep, 0))) goto err; /* TODO: this only handles one certificate request so far */
+			checkAfter = ASN1_INTEGER_get(pollRep->checkAfter);
+			/* TODO: print OPTIONAL reason (PKIFreeText) from message */
+			CMP_printf(ctx, "INFO: Received polling response, waiting checkAfter = %ld seconds before sending another polling request...", checkAfter);
+
+			if (ctx->maxPollTime != 0)
+				{        /* timout is set in context */
+				if (maxTimeLeft == 0) goto err; /* timeout reached */
+				if (maxTimeLeft > checkAfter)
+					{
+					maxTimeLeft -= checkAfter;
+					}
+				else
+					{
+					checkAfter = maxTimeLeft; /* poll a last time just when the set timeout will be reached */
+					maxTimeLeft = 0;
+					}
+				}
+
+			CMP_PKIMESSAGE_free(prep);
+			CMP_PKIMESSAGE_free(preq);
+			sleep(checkAfter);
+			}
+		else break; /* final success */
+		}
+	if (!prep) goto err;
+
+	CMP_PKIMESSAGE_free(preq);
+	*msg = prep;
+
+	return 1; 
+err:
+	CMP_PKIMESSAGE_free(preq);
+	CMP_PKIMESSAGE_free(prep);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * send certConf for IR, CR or KUR sequences
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+static int sendCertConf( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *certConf=NULL;
+	CMP_PKIMESSAGE *PKIconf=NULL;
+
+	/* crate Certificate Confirmation - certConf */
+	if (!(certConf = CMP_certConf_new(ctx))) goto err;
+
+	CMP_printf( ctx, "INFO: Sending Certificate Confirm");
+	if (! (CMP_PKIMESSAGE_http_perform(ctx, certConf, &PKIconf)))
+		{
+		ADD_HTTP_ERROR_INFO(CMP_F_SENDCERTCONF, CMP_R_PKICONF_NOT_RECEIVED, "certConf");
+		goto err;
+		}
+
+	/* make sure the received messagetype indicates an PKIconf message */
+	if (CMP_PKIMESSAGE_get_bodytype(PKIconf) != V_CMP_PKIBODY_PKICONF)
+		{
+		char errmsg[256];
+		CMPerr(CMP_F_SENDCERTCONF, CMP_R_PKIBODY_ERROR);
+		ERR_add_error_data(1, PKIError_data( PKIconf, errmsg, sizeof(errmsg)));
+		goto err;
+		}
+
+	/* validate message protection */
+	if (CMP_validate_msg(ctx, PKIconf))
+		{
+		CMP_printf( ctx,"SUCCESS: validating protection of incoming message");
+		}
+	else
+		{
+		CMPerr(CMP_F_SENDCERTCONF, CMP_R_ERROR_VALIDATING_PROTECTION);
+		goto err;
+		}
+
+	/* compare received nonce with the one sent in certConf */
+	if (PKIconf->header->recipNonce)
+		{
+		if(ASN1_OCTET_STRING_cmp(certConf->header->senderNonce, PKIconf->header->recipNonce))
+			{
+			CMPerr(CMP_F_SENDCERTCONF, CMP_R_ERROR_NONCES_DO_NOT_MATCH);
+			goto err;
+			}
+		} /* it's not clear from the RFC whether recipNonce MUST be set or not */
+
+	CMP_PKIMESSAGE_free(certConf);
+	CMP_PKIMESSAGE_free(PKIconf);
+	return 1;
+err:
+	if (certConf) CMP_PKIMESSAGE_free(certConf);
+	if (PKIconf) CMP_PKIMESSAGE_free(PKIconf);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * saves error information from PKIStatus field of a certrepmessage into the ctx
+ * TODO: in case we would get multiple certreps, this function would need to be 
+ *       extended to save the status from each one
+ * ############################################################################ */
+static void save_certrep_statusInfo(CMP_CTX *ctx, CMP_CERTREPMESSAGE *certrep)
+	{
+	CMP_CERTRESPONSE *resp=NULL;
+	int i = 0;
+
+	if (sk_CMP_CERTRESPONSE_num(certrep->response) > 0 &&
+		(resp = sk_CMP_CERTRESPONSE_value(certrep->response, 0)) &&
+		resp->status != NULL)
+		{
+		CMP_CTX_set_failInfoCode(ctx, resp->status->failInfo);
+		ctx->lastPKIStatus = CMP_PKISTATUSINFO_PKIstatus_get(resp->status);
+
+		if (!ctx->lastStatusString)
+			ctx->lastStatusString = sk_ASN1_UTF8STRING_new_null();
+
+		if (ctx->lastStatusString)
+			{
+			for (i = 0; i < sk_ASN1_UTF8STRING_num(resp->status->statusString); i++)
+				{
+				ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(resp->status->statusString, i);
+				sk_ASN1_UTF8STRING_push(ctx->lastStatusString, ASN1_STRING_dup(str));
+				}
+			}
+		}
+	}
+
+/* ############################################################################ *
+ * do the full sequence for IR, including IR, IP, certConf, PKIconf and
+ * potential polling
+ *
+ * All options need to be set in the context.
+ *
+ * TODO: another function to request two certificates at once should be created
+ *
+ * returns pointer to received certificate, NULL if none was received
+ * ############################################################################ */
+X509 *CMP_doInitialRequestSeq( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *ir=NULL;
+	CMP_PKIMESSAGE *ip=NULL;
+
+	/* check if all necessary options are set */
+	if (!ctx || !ctx->newPkey ||
+		/* for authentication we need either reference/secret or external 
+		 * identity certificate and private key, the server name/cert might not be
+		 * known here yet especiallaly in case of E.7 */
+			(!(ctx->referenceValue && ctx->secretValue) &&  /* MSG_MAC_ALG */
+			!(ctx->pkey && ctx->clCert)) )
+		{ /* MSG_SIG_ALG for E.7 */
+		CMPerr(CMP_F_CMP_DOINITIALREQUESTSEQ, CMP_R_INVALID_ARGS);
+		goto err;
+		}
+
+	/* create Initialization Request - ir */
+	if (!(ir = CMP_ir_new(ctx))) goto err;
+
+	CMP_printf(ctx, "INFO: Sending Initialization Request");
+	if (! (CMP_PKIMESSAGE_http_perform(ctx, ir, &ip)))
+		{
+		ADD_HTTP_ERROR_INFO(CMP_F_CMP_DOINITIALREQUESTSEQ, CMP_R_IP_NOT_RECEIVED, "ir");
+		goto err;
+		}
+	
+	/* catch if the received messagetype does not indicate an IP message (e.g. error)*/
+	if (CMP_PKIMESSAGE_get_bodytype(ip) != V_CMP_PKIBODY_IP)
+		{
+		char errmsg[256];
+		CMPerr(CMP_F_CMP_DOINITIALREQUESTSEQ, CMP_R_PKIBODY_ERROR);
+		ERR_add_error_data(1, PKIError_data(ip, errmsg, sizeof(errmsg)));
+		goto err;
+		}
+
+	save_certrep_statusInfo(ctx, ip->body->value.ip);
+
+	/* validate message protection */
+	if (CMP_validate_msg(ctx, ip))
+		{
+		CMP_printf( ctx, "SUCCESS: validating protection of incoming message");
+		} else {
+		CMPerr(CMP_F_CMP_DOINITIALREQUESTSEQ, CMP_R_ERROR_VALIDATING_PROTECTION);
+		goto err;
+		}
+
+	/* compare received nonce with the one sent in IR */
+	if (ip->header->recipNonce)
+		{
+		if(ASN1_OCTET_STRING_cmp(ir->header->senderNonce, ip->header->recipNonce))
+			{
+			/* senderNonce != recipNonce (sic although there is no "!" in the if) */
+			CMPerr(CMP_F_CMP_DOINITIALREQUESTSEQ, CMP_R_ERROR_NONCES_DO_NOT_MATCH);
+			goto err;
+			}
+		} /* it's not clear from the RFC whether recipNonce MUST be set or not */
+	CMP_CTX_set1_recipNonce(ctx, ip->header->senderNonce); /* store for setting in the next msg */
+
+	/* make sure the PKIStatus for the *first* CERTrepmessage indicates a certificate was granted */
+	/* TODO handle second CERTrepmessages if two would have sent */
+	if (CMP_CERTREPMESSAGE_PKIStatus_get( ip->body->value.ip, 0) == CMP_PKISTATUS_waiting)
+		if (!pollForResponse(ctx, ip->body->value.ip, &ip))
+			{
+			CMPerr(CMP_F_CMP_DOINITIALREQUESTSEQ, CMP_R_IP_NOT_RECEIVED);
+			ERR_add_error_data(1, "received 'waiting' pkistatus but polling failed");
+			goto err;
+			}
+
+	if (!(ctx->newClCert = CMP_CERTREPMESSAGE_get_certificate(ctx, ip->body->value.ip))) goto err;
+
+	/* if the CA returned certificates in the caPubs field, copy them
+	 * to the context so that they can be retrieved if necessary 
+	 *
+	 * section 5.3.2:
+	 * Note that if the PKI
+	 * Message Protection is "shared secret information" (see Section
+	 * 5.1.3), then any certificate transported in the caPubs field may be
+	 * directly trusted as a root CA certificate by the initiator. */
+
+	if (ip->body->value.ip->caPubs)
+		CMP_CTX_set1_caPubs(ctx, ip->body->value.ip->caPubs);
+
+	/* copy any received extraCerts to ctx->extraCertsIn so they can be retrieved */
+	if (ip->extraCerts)
+		CMP_CTX_set1_extraCertsIn(ctx, ip->extraCerts);
+
+	/* check if implicit confirm is set in generalInfo and send certConf if not */
+	if (!CMP_PKIMESSAGE_check_implicitConfirm(ip)) 
+		if (!sendCertConf(ctx)) goto err;
+
+	CMP_PKIMESSAGE_free(ir);
+	CMP_PKIMESSAGE_free(ip);
+	return ctx->newClCert;
+
+err:
+	if (ir) CMP_PKIMESSAGE_free(ir);
+	if (ip) CMP_PKIMESSAGE_free(ip);
+
+	/* print out openssl and cmp errors to error_cb if it's set */
+	if (ctx&&ctx->error_cb) ERR_print_errors_cb(CMP_CTX_error_callback, (void*) ctx);
+	return NULL;
+	}
+
+
+/* ############################################################################ *
+ * do the full sequence for RR, including RR, RP and potential polling
+ *
+ * All options need to be set in the context.
+ *
+ * TODO: this function can only revoke one certifcate so far, should be possible
+ * for several according to 5.3.9
+ * TODO: this actually revokes the current clCertificate - it might be desired
+ * to revoke another certificate the EE posesses.
+ *
+ * The RFC is vague in which PKIStatus should be returned by the server, so we
+ * take "accepted, grantedWithMods, revocationWaring, revocationNotification"
+ * as information that the certifcate was revoked, "rejection" as information
+ * that the revocation was rejected and don't expect "waiting, keyUpdateWarning"
+ * (which are handled as error)
+ *
+ * returns according to PKIStatus received, 0 on error
+ *          accepted               (1)
+ *          grantedWithMods        (2)
+ *          rejection              (3) (this is not an error!)
+ *          revocationWarning      (5)
+ *          revocationNotification (6)
+ * ############################################################################ */
+int CMP_doRevocationRequestSeq( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *rr=NULL;
+	CMP_PKIMESSAGE *rp=NULL;
+	int pkiStatus = 0;
+
+	if (!ctx || !ctx->serverName || !ctx->pkey ||
+		!ctx->clCert || !(ctx->srvCert || ctx->trusted_store))
+		{
+		CMPerr(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_INVALID_ARGS);
+		goto err;
+		}
+
+	if (! (rr = CMP_rr_new(ctx))) goto err;
+
+	CMP_printf( ctx, "INFO: Sending Revocation Request");
+	if (! (CMP_PKIMESSAGE_http_perform(ctx, rr, &rp)))
+		{
+		ADD_HTTP_ERROR_INFO(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_RP_NOT_RECEIVED, "rr");
+		goto err;
+		}
+
+	/* make sure the received messagetype indicates an RP message */
+	if (CMP_PKIMESSAGE_get_bodytype( rp) != V_CMP_PKIBODY_RP)
+		{
+		char errmsg[256];
+		CMPerr(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_PKIBODY_ERROR);
+		ERR_add_error_data(1, PKIError_data( rp, errmsg, sizeof(errmsg)));
+		goto err;
+		}
+
+	/* validate message protection */
+	if (CMP_validate_msg(ctx, rp))
+		{
+		CMP_printf(  ctx, "SUCCESS: validating protection of incoming message");
+		}
+	else
+		{
+		CMPerr(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_ERROR_VALIDATING_PROTECTION);
+		goto err;
+		}
+
+	/* compare received nonce with the one sent in RR */
+	if (rp->header->recipNonce)
+		{
+		if(ASN1_OCTET_STRING_cmp(rr->header->senderNonce, rp->header->recipNonce))
+			{
+			/* senderNonce != recipNonce (sic although there is no "!" in the if) */
+			CMPerr(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_ERROR_NONCES_DO_NOT_MATCH);
+			goto err;
+			}
+		} /* it's not clear from the RFC whether recipNonce MUST be set or not */
+	
+
+	/* evaluate PKIStatus field */
+	switch (pkiStatus = CMP_REVREPCONTENT_PKIStatus_get( rp->body->value.rp, 0)) 
+		{
+		case CMP_PKISTATUS_accepted:
+			CMP_printf( ctx, "INFO: revocation accepted (PKIStatus=accepted)");
+			break;
+		case CMP_PKISTATUS_grantedWithMods:
+			CMP_printf( ctx, "INFO: revocation accepted (PKIStatus=grantedWithMods)");
+			break;
+		case CMP_PKISTATUS_rejection:
+			CMP_printf( ctx, "INFO: revocation rejected (PKIStatus=rejection)");
+			break;
+		case CMP_PKISTATUS_revocationWarning:
+			CMP_printf( ctx, "INFO: revocation accepted (PKIStatus=revocationWarning)");
+			break;
+		case CMP_PKISTATUS_revocationNotification:
+			CMP_printf( ctx, "INFO: revocation accepted (PKIStatus=revocationNotification)");
+			break;
+		case CMP_PKISTATUS_waiting:
+		case CMP_PKISTATUS_keyUpdateWarning:
+			CMPerr(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_UNEXPECTED_PKISTATUS);
+			goto err;
+		default:
+			CMPerr(CMP_F_CMP_DOREVOCATIONREQUESTSEQ, CMP_R_UNKNOWN_PKISTATUS);
+			goto err;
+		}
+
+	CMP_PKIMESSAGE_free(rr);
+	CMP_PKIMESSAGE_free(rp);
+	return (pkiStatus+1);
+err:
+	if (ctx&&ctx->error_cb) ERR_print_errors_cb(CMP_CTX_error_callback, (void*) ctx);
+	if (rr) CMP_PKIMESSAGE_free(rr);
+	if (rp) CMP_PKIMESSAGE_free(rp);
+	return 0;
+	}
+
+
+/* ############################################################################ *
+ * do the full sequence for CR, including CR, CP, certConf, PKIconf and
+ * potential polling
+ *
+ * All options need to be set in the context.
+ *
+ * TODO: another function to request two certificates at once should be created
+ *
+ * returns pointer to received certificate, NULL if non was received
+ * ############################################################################ */
+X509 *CMP_doCertificateRequestSeq( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *cr=NULL;
+	CMP_PKIMESSAGE *cp=NULL;
+
+	/* check if all necessary options are set */
+	if (!ctx ||  !ctx->pkey ||
+			(!(ctx->referenceValue && ctx->secretValue) && /* MSG_MAC_ALG */
+			!(ctx->pkey && ctx->clCert && (ctx->srvCert || ctx->trusted_store))) /* MSG_SIG_ALG */
+		)
+		{
+		CMPerr(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ, CMP_R_INVALID_ARGS);
+		goto err;
+		}
+
+	/* create Certificate Request - cr */
+	if (! (cr = CMP_cr_new(ctx))) goto err;
+
+	CMP_printf( ctx, "INFO: Sending Certificate Request");
+	if (! (CMP_PKIMESSAGE_http_perform(ctx, cr, &cp)))
+		{
+		ADD_HTTP_ERROR_INFO(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ, CMP_R_CP_NOT_RECEIVED, "cr");
+		goto err;
+		}
+
+	/* make sure the received messagetype indicates an CP message */
+	if (CMP_PKIMESSAGE_get_bodytype( cp) != V_CMP_PKIBODY_CP)
+		{
+		char errmsg[256];
+		CMPerr(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ, CMP_R_PKIBODY_ERROR);
+		ERR_add_error_data(1, PKIError_data( cp, errmsg, sizeof(errmsg)));
+		goto err;
+		}
+
+	save_certrep_statusInfo(ctx, cp->body->value.cp);
+
+	/* validate message protection */
+	if (CMP_validate_msg(ctx, cp))
+		{
+		CMP_printf(  ctx, "SUCCESS: validating protection of incoming message");
+		} else {
+		CMPerr(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ, CMP_R_ERROR_VALIDATING_PROTECTION);
+		goto err;
+		}
+
+	/* compare received nonce with the one sent in CR */
+	if (cp->header->recipNonce)
+		{
+		if(ASN1_OCTET_STRING_cmp(cr->header->senderNonce, cp->header->recipNonce))
+			{
+			/* senderNonce != recipNonce (sic although there is no "!" in the if) */
+			CMPerr(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ, CMP_R_ERROR_NONCES_DO_NOT_MATCH);
+			goto err;
+			}
+		} /* it's not clear from the RFC whether recipNonce MUST be set or not */
+	CMP_CTX_set1_recipNonce(ctx, cp->header->senderNonce); /* store for setting in the next msg */
+
+	/* evaluate PKIStatus field */
+	if (CMP_CERTREPMESSAGE_PKIStatus_get( cp->body->value.cp, 0) == CMP_PKISTATUS_waiting)
+		if (!pollForResponse(ctx, cp->body->value.cp, &cp))
+			{
+			CMPerr(CMP_F_CMP_DOCERTIFICATEREQUESTSEQ, CMP_R_CP_NOT_RECEIVED);
+			ERR_add_error_data(1, "received 'waiting' pkistatus but polling failed");
+			goto err;
+			}
+
+	if (!(ctx->newClCert = CMP_CERTREPMESSAGE_get_certificate(ctx, cp->body->value.cp))) goto err;
+
+	/* copy any received extraCerts to ctx->etraCertsIn so they can be retrieved */
+	if (cp->extraCerts)
+		CMP_CTX_set1_extraCertsIn(ctx, cp->extraCerts);
+
+	/* check if implicit confirm is set in generalInfo and send certConf if not */
+	if (!CMP_PKIMESSAGE_check_implicitConfirm(cp)) 
+		if (!sendCertConf(ctx)) goto err;
+
+	CMP_PKIMESSAGE_free(cr);
+	CMP_PKIMESSAGE_free(cp);
+	return ctx->newClCert;
+
+err:
+	if (cr) CMP_PKIMESSAGE_free(cr);
+	if (cp) CMP_PKIMESSAGE_free(cp);
+
+	/* print out openssl and cmp errors to error_cb if it's set */
+	if (ctx&&ctx->error_cb) ERR_print_errors_cb(CMP_CTX_error_callback, (void*) ctx);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * do the full sequence for KUR, including KUR, KUP, certConf, PKIconf and
+ * potential polling
+ *
+ * All options need to be set in the context.
+ *
+ * NB: the ctx->newKey can be set *by the user* as the same as the current key 
+ * as per section 5.3.5:
+ * An update is a replacement
+ * certificate containing either a new subject public key or the current
+ * subject public key (although the latter practice may not be
+ * appropriate for some environments).
+ *
+ * TODO: another function to request two certificates at once should be created
+ *
+ * returns pointer to received certificate, NULL if non was received
+ * ############################################################################ */
+X509 *CMP_doKeyUpdateRequestSeq( CMP_CTX *ctx)
+	{
+	CMP_PKIMESSAGE *kur=NULL;
+	CMP_PKIMESSAGE *kup=NULL;
+
+	/* check if all necessary options are set */
+	if (!ctx ||  !ctx->newPkey ||
+			(!(ctx->referenceValue && ctx->secretValue) && /* MSG_MAC_ALG */
+			!(ctx->pkey && ctx->clCert && (ctx->srvCert || ctx->trusted_store)))) /* MSG_SIG_ALG */
+		{
+		CMPerr(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ, CMP_R_INVALID_ARGS);
+		goto err;
+		}
+
+	/* create Key Update Request - kur */
+	if (! (kur = CMP_kur_new(ctx))) goto err;
+
+	CMP_printf( ctx, "INFO: Sending Key Update Request");
+	if (! (CMP_PKIMESSAGE_http_perform(ctx, kur, &kup)))
+		{
+		ADD_HTTP_ERROR_INFO(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ, CMP_R_KUP_NOT_RECEIVED, "kur");
+		goto err;
+		}
+
+	/* make sure the received messagetype indicates an KUP message */
+	if (CMP_PKIMESSAGE_get_bodytype( kup) != V_CMP_PKIBODY_KUP)
+		{
+		char errmsg[256];
+		CMPerr(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ, CMP_R_PKIBODY_ERROR);
+		ERR_add_error_data(1, PKIError_data( kup, errmsg, sizeof(errmsg)));
+		goto err;
+		}
+
+	save_certrep_statusInfo(ctx, kup->body->value.kup);
+
+	/* validate message protection */
+	if (CMP_validate_msg(ctx, kup))
+		{
+		CMP_printf( ctx,	"SUCCESS: validating protection of incoming message");
+		} else {
+		CMPerr(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ, CMP_R_ERROR_VALIDATING_PROTECTION);
+		goto err;
+		}
+
+	/* compare received nonce with the one sent in KUR */
+	if (kup->header->recipNonce)
+		{
+		if(ASN1_OCTET_STRING_cmp(kur->header->senderNonce, kup->header->recipNonce))
+			{
+			/* senderNonce != recipNonce (sic although there is no "!" in the if) */
+			CMPerr(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ, CMP_R_ERROR_NONCES_DO_NOT_MATCH);
+			goto err;
+			}
+		} /* it's not clear from the RFC whether recipNonce MUST be set or not */
+	CMP_CTX_set1_recipNonce(ctx, kup->header->senderNonce); /* store for setting in the next msg */
+
+	/* evaluate PKIStatus field */
+	if (CMP_CERTREPMESSAGE_PKIStatus_get( kup->body->value.kup, 0) == CMP_PKISTATUS_waiting)
+		{
+		if (!pollForResponse(ctx, kup->body->value.kup, &kup)) {
+			CMPerr(CMP_F_CMP_DOKEYUPDATEREQUESTSEQ, CMP_R_KUP_NOT_RECEIVED);
+			ERR_add_error_data(1, "received 'waiting' pkistatus but polling failed");
+			goto err;
+			}
+		}
+
+	if (!(ctx->newClCert = CMP_CERTREPMESSAGE_get_certificate(ctx, kup->body->value.kup))) goto err;
+
+	/* copy received capubs to the context */
+	if (kup->body->value.kup->caPubs)
+		CMP_CTX_set1_caPubs(ctx, kup->body->value.kup->caPubs);
+
+	/* copy any received extraCerts to ctx->etraCertsIn so they can be retrieved */
+	if (kup->extraCerts)
+		CMP_CTX_set1_extraCertsIn(ctx, kup->extraCerts);
+
+	/* check if implicit confirm is set in generalInfo and send certConf if not */
+	if (!CMP_PKIMESSAGE_check_implicitConfirm(kup)) 
+		if (!sendCertConf(ctx)) goto err;
+
+	CMP_PKIMESSAGE_free(kur);
+	CMP_PKIMESSAGE_free(kup);
+	return ctx->newClCert;
+
+err:
+	if (kur) CMP_PKIMESSAGE_free(kur);
+	if (kup) CMP_PKIMESSAGE_free(kup);
+
+	/* print out openssl and cmp errors to error_cb if it's set */
+	if (ctx&&ctx->error_cb) ERR_print_errors_cb(CMP_CTX_error_callback, (void*) ctx);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * Sends a general message to the server to request information specified in the
+ * InfoType and Value (itav) given in the nid (section 5.3.19 and E.5).
+ *
+ * all obtions besides the single ITAV and it's value to be sent need to be set
+ * in the context.
+ *
+ * TODO: this could take multiple nids to have several ITAVs in the Genm
+ *
+ * returns pointer to stack of ITAVs received in the answer or NULL on error
+ * ############################################################################ */
+STACK_OF(CMP_INFOTYPEANDVALUE) *CMP_doGeneralMessageSeq( CMP_CTX *ctx, int nid, char *value)
+	{
+	CMP_PKIMESSAGE *genm=NULL;
+	CMP_PKIMESSAGE *genp=NULL;
+	CMP_INFOTYPEANDVALUE *itav=NULL;
+	STACK_OF(CMP_INFOTYPEANDVALUE) *rcvdItavs=NULL;
+
+	/* check if all necessary options are set */
+	if (!ctx || (!(ctx->referenceValue && ctx->secretValue) && /* MSG_MAC_ALG */
+			!(ctx->pkey && ctx->clCert && (ctx->srvCert || ctx->trusted_store)))) /* MSG_SIG_ALG */
+		{
+		CMPerr(CMP_F_CMP_DOGENERALMESSAGESEQ, CMP_R_INVALID_ARGS);
+		goto err;
+		}
+
+	/* crate GenMsgContent - genm*/
+	if (! (genm = CMP_genm_new(ctx))) goto err;
+
+	/* set itav - TODO: let this function take a STACK of ITAV as arguments */
+	itav = CMP_INFOTYPEANDVALUE_new();
+	itav->infoType = OBJ_nid2obj(nid);
+	itav->infoValue.ptr = value;
+	CMP_PKIMESSAGE_genm_item_push0( genm, itav);
+
+	CMP_printf( ctx, "INFO: Sending General Message");
+	if (! (CMP_PKIMESSAGE_http_perform(ctx, genm, &genp)))
+		{
+		ADD_HTTP_ERROR_INFO(CMP_F_CMP_DOGENERALMESSAGESEQ, CMP_R_GENP_NOT_RECEIVED, "genm");
+		goto err;
+		}
+
+	/* make sure the received messagetype indicates an GENP message */
+	if (CMP_PKIMESSAGE_get_bodytype(genp) != V_CMP_PKIBODY_GENP)
+		{
+		char errmsg[256];
+		CMPerr(CMP_F_CMP_DOGENERALMESSAGESEQ, CMP_R_PKIBODY_ERROR);
+		ERR_add_error_data(1, PKIError_data( genp, errmsg, sizeof(errmsg)));
+		goto err;
+		}
+
+	/* validate message protection */
+	if (CMP_validate_msg(ctx, genp))
+		{
+		CMP_printf( ctx, "SUCCESS: validating protection of incoming message");
+		} else {
+		CMPerr(CMP_F_CMP_DOGENERALMESSAGESEQ, CMP_R_ERROR_VALIDATING_PROTECTION);
+		goto err;
+		}
+
+	/* compare received nonce with the one sent in genm */
+	if (genp->header->recipNonce)
+		{
+		if(ASN1_OCTET_STRING_cmp(genm->header->senderNonce, genp->header->recipNonce))
+			{
+			CMPerr(CMP_F_CMP_DOGENERALMESSAGESEQ, CMP_R_ERROR_NONCES_DO_NOT_MATCH);
+			goto err;
+			}
+		} /* it's not clear from the RFC whether recipNonce MUST be set or not */
+	
+	/* the received stack of itavs shouldn't be freed with the message */
+	rcvdItavs = genp->body->value.genp;
+	genp->body->value.genp = NULL;
+
+	CMP_PKIMESSAGE_free(genm);
+	CMP_PKIMESSAGE_free(genp);
+
+	return rcvdItavs;
+
+err:
+	if (genm) CMP_PKIMESSAGE_free(genm);
+	if (genp) CMP_PKIMESSAGE_free(genp);
+
+	/* print out openssl and cmp errors to error_cb if it's set */
+	if (ctx&&ctx->error_cb) ERR_print_errors_cb(CMP_CTX_error_callback, (void*) ctx);
+	return NULL;
+	}
+
Index: openssl-1.0.1h-cmp/crypto/cmp/cmp_vfy.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/cmp/cmp_vfy.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/cmp/cmp_vfy.c	(revision 764)
@@ -0,0 +1,484 @@
+/* vim: set noet ts=4 sts=4 sw=4: */
+/* crypto/cmp/cmp_vfy.c
+ * Functions to verify CMP (RFC 4210) messages for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/cmp.h>
+#include <openssl/err.h>
+
+/* ############################################################################ *
+ * internal function
+ *
+ * validate a message protected by signature according to section 5.1.3.3
+ * (sha1+RSA/DSA or any other algorithm supported by OpenSSL)
+ * returns 0 on error
+ * ############################################################################ */
+static int CMP_verify_signature( CMP_PKIMESSAGE *msg, X509 *cert)
+	{
+	EVP_MD_CTX *ctx=NULL;
+	CMP_PROTECTEDPART protPart;
+	int ret=0;
+	EVP_MD *digest=NULL;
+	EVP_PKEY *pubkey=NULL;
+
+	size_t protPartDerLen=0;
+	unsigned char *protPartDer=NULL;
+
+	if (!msg || !cert) return 0;
+
+	pubkey = X509_get_pubkey((X509*) cert);
+	if (!pubkey) return 0;
+
+	/* create the DER representation of protected part */
+	protPart.header = msg->header;
+	protPart.body	= msg->body;
+	protPartDerLen	= i2d_CMP_PROTECTEDPART(&protPart, &protPartDer);
+
+	/* verify prtotection of protected part */
+	ctx = EVP_MD_CTX_create();
+	if(!(digest = (EVP_MD *)EVP_get_digestbynid(OBJ_obj2nid(msg->header->protectionAlg->algorithm)))) goto notsup;
+	EVP_VerifyInit_ex(ctx, digest, NULL);
+	EVP_VerifyUpdate(ctx, protPartDer, protPartDerLen);
+	ret = EVP_VerifyFinal(ctx, msg->protection->data, msg->protection->length, pubkey);
+
+	/* cleanup */
+	EVP_MD_CTX_destroy(ctx);
+	OPENSSL_free(protPartDer);
+	EVP_PKEY_free(pubkey);
+	return ret;
+notsup:
+	CMPerr(CMP_F_CMP_VERIFY_SIGNATURE, CMP_R_ALGORITHM_NOT_SUPPORTED);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * Validates a message protected with PBMAC
+ * ############################################################################ */
+static int CMP_verify_MAC( CMP_PKIMESSAGE *msg, const ASN1_OCTET_STRING *secret)
+	{
+	ASN1_BIT_STRING *protection=NULL;
+	int valid = 0;
+	
+	/* generate expected protection for the message */
+	if (!(protection = CMP_calc_protection_pbmac( msg, secret)))
+		goto err; /* failed to generate protection string! */
+	
+	valid = M_ASN1_BIT_STRING_cmp( protection, msg->protection) == 0;
+	ASN1_BIT_STRING_free(protection);
+	return valid;
+err:
+	return 0;
+	}
+
+/* ############################################################################ *
+ * internal function
+ *
+ * Attempt to validate certificate path. returns 1 if the path was
+ * validated successfully and 0 if not.
+ * ############################################################################ */
+int CMP_validate_cert_path(X509_STORE *trusted_store, X509_STORE *untrusted_store, X509 *cert)
+	{
+	int ret=0,valid=0;
+	X509_STORE_CTX *csc=NULL;
+	STACK_OF(X509) *untrusted_stack=NULL;
+
+	if (!cert) goto end;
+
+	if (!trusted_store)
+		{
+		CMPerr(CMP_F_CMP_VALIDATE_CERT_PATH, CMP_R_NO_TRUSTED_CERTIFICATES_SET);
+		goto end;
+		}
+
+	/* A cert callback could be used to do additional checking, policies for example.*/
+	/* X509_STORE_set_verify_cb(trusted_store, CMP_cert_callback); */
+
+	if (!(csc = X509_STORE_CTX_new())) goto end;
+
+	/* note: there doesn't seem to be a good way to get a stack of all
+	 * the certs in an X509_STORE, so we need to try and find the chain
+	 * of intermediate certs here. */
+	if (untrusted_store)
+		untrusted_stack = CMP_build_cert_chain(untrusted_store, cert);
+
+	X509_STORE_set_flags(trusted_store, 0);
+	if(!X509_STORE_CTX_init(csc, trusted_store, cert, untrusted_stack))
+		goto end;
+
+	/* CRLs could be handled here */
+	/* if (crls) X509_STORE_CTX_set0_crls(csc, crls); */
+
+	valid=X509_verify_cert(csc);
+
+	X509_STORE_CTX_free(csc);
+
+	ret=0;
+
+	end:
+	if (untrusted_stack)
+		sk_X509_pop_free(untrusted_stack, X509_free);
+	
+	if (valid > 0)
+		{
+		ret = 1;
+		}
+
+	return(ret);
+	}
+
+#if 0
+/* ############################################################################ *
+ * NOTE: This is only needed if/when we want to do additional checking on the certificates!
+ *		 It is not currently used.
+ * 
+ * This is called for every valid certificate. Here we could add additional checks,
+ * for policies for example.
+ * ############################################################################ */
+int CMP_cert_callback(int ok, X509_STORE_CTX *ctx)
+	{
+	int cert_error = X509_STORE_CTX_get_error(ctx);
+	X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
+
+	if (!ok)
+		{
+		switch(cert_error)
+			{
+			case X509_V_ERR_NO_EXPLICIT_POLICY:
+				/* policies_print(NULL, ctx); */
+			case X509_V_ERR_CERT_HAS_EXPIRED:
+
+				/* since we are just checking the certificates, it is
+				 * ok if they are self signed. But we should still warn
+				 * the user.
+				 */
+
+			case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+				/* Continue after extension errors too */
+			case X509_V_ERR_INVALID_CA:
+			case X509_V_ERR_INVALID_NON_CA:
+			case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+			case X509_V_ERR_INVALID_PURPOSE:
+			case X509_V_ERR_CRL_HAS_EXPIRED:
+			case X509_V_ERR_CRL_NOT_YET_VALID:
+			case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+				ok = 1;
+
+			}
+
+		return ok;
+		}
+
+#if 0
+	/* TODO: we could check policies here too */
+	if (cert_error == X509_V_OK && ok == 2)
+		policies_print(NULL, ctx);
+#endif
+
+	return(ok);
+	}
+#endif
+
+
+/* ############################################################################ *
+ * internal function
+ *
+ * Find server certificate by:
+ * - first see if we can find it in trusted store
+ * - then try to find it in untrusted store
+ * - then search for certs with matching name in extraCerts
+ *	 - if only one match found, return that
+ *	 - if more than one, try to find a cert with the matching senderKID if available
+ *	 - if keyID is not available, return first cert found
+ * returns pointer to found server Certificate on success
+ * returns NULL on error or when no certificate could be found
+ * ############################################################################ */
+static X509 *findSrvCert(CMP_CTX *ctx, CMP_PKIMESSAGE *msg)
+	{
+	X509 *srvCert = NULL;
+	X509_STORE_CTX *csc = NULL;
+	X509_OBJECT obj;
+	STACK_OF(X509) *found_certs = NULL;
+	int n;
+
+	if(!(csc = X509_STORE_CTX_new())) return NULL;
+
+	/* first attempt lookup in trusted_store */
+	if (X509_STORE_CTX_init(csc, ctx->trusted_store, NULL, NULL))
+		{
+		if (X509_STORE_get_by_subject(csc, X509_LU_X509, msg->header->sender->d.directoryName, &obj))
+			{
+			srvCert = obj.data.x509;
+			X509_STORE_CTX_free(csc);
+			return srvCert;
+			}
+		}
+	
+	/* attempt lookup in untrusted_store */
+	if (X509_STORE_CTX_init(csc, ctx->untrusted_store, NULL, NULL))
+		{
+		if (X509_STORE_get_by_subject(csc, X509_LU_X509, msg->header->sender->d.directoryName, &obj))
+			{
+			srvCert = obj.data.x509;
+			X509_STORE_CTX_free(csc);
+			return srvCert;
+			}
+		}
+
+	/* not found in trusted_store, so look through extraCerts */
+	if(!(found_certs = sk_X509_new_null())) return NULL;
+
+	for (n = 0; n < sk_X509_num(msg->extraCerts); n++)
+		{
+		X509 *cert = sk_X509_value(msg->extraCerts, n);
+		X509_NAME *name = NULL;
+		if (!cert) continue;
+		name = X509_get_subject_name(cert);
+
+		if (name && !X509_NAME_cmp(name, msg->header->sender->d.directoryName))
+			sk_X509_push(found_certs, cert);
+		}
+
+	/* if found exactly one cert, we'll use that */
+	if (sk_X509_num(found_certs) == 1)
+		srvCert = sk_X509_pop(found_certs);
+
+	/* found more than one with a matching name, so try to search
+	   through the found certs by key ID if we have it.  if not,
+	   just return first one. */
+	else if (sk_X509_num(found_certs) > 1)
+		{
+		if (msg->header->senderKID) {
+			for (n = 0; n < sk_X509_num(found_certs); n++)
+				{
+				X509 *cert = sk_X509_value(found_certs, n);
+				ASN1_OCTET_STRING *cert_keyid = NULL;
+
+				if (!(cert_keyid = CMP_get_cert_subject_key_id(cert))) return NULL;
+
+				if (!ASN1_OCTET_STRING_cmp(cert_keyid, msg->header->senderKID))
+					{
+					srvCert = cert;
+					break;
+					}
+				}
+			}
+
+		if (!srvCert)
+			{
+			/* key id not available or we didn't find a cert with matching keyID.
+			 * -> return the first one with matching name */
+			srvCert = sk_X509_pop(found_certs);
+			}
+		}
+
+	sk_X509_free(found_certs);
+
+	return srvCert;
+	}
+
+
+/* ############################################################################ *
+ * internal function
+ *
+ * Creates a new certificate store and adds all the self-signed certificates from
+ * the given stack to the store.
+ * ############################################################################ */
+static X509_STORE *createTempTrustedStore(STACK_OF(X509) *stack)
+	{
+	X509_STORE *store = X509_STORE_new();
+	int i;
+
+	if (!store) goto err;
+
+	for (i = 0; i < sk_X509_num(stack); i++)
+		{
+		X509 *cert = sk_X509_value(stack, i);
+		EVP_PKEY *pubkey = X509_get_pubkey(cert);
+
+		if (pubkey && X509_verify(cert, pubkey))
+			X509_STORE_add_cert(store, cert);
+
+		EVP_PKEY_free(pubkey);
+		}
+
+	return store;
+
+	err:
+	return NULL;	
+	}
+
+/* ############################################################################
+ * Validates the protection of the given PKIMessage using either password
+ * based mac or a signature algorithm. In the case of signature algorithm, the
+ * certificate can be provided in ctx->srvCert or it is taken from 
+ * extraCerts and validate against ctx->trusted_store utilizing 
+ * ctx->untrusted_store and extraCerts.
+ *
+ * If ctx->permitTAInExtraCertsForIR is true, the trust anchor may be taken from
+ * the extraCerts field when a self-signed certificate is found there which can
+ * be used to validate the issued certificate returned in IP.  This is according
+ * to the need given in 3GPP TS 33.310.
+ *
+ * returns 1 on success, 0 on error or validation failed
+ * ############################################################################ */
+int CMP_validate_msg(CMP_CTX *ctx, CMP_PKIMESSAGE *msg)
+	{
+	X509 *srvCert = ctx->srvCert;
+	int srvCert_valid = 0;
+	int nid = 0;
+	ASN1_OBJECT *algorOID=NULL;
+
+	if (!msg->header->protectionAlg)
+		/* unprotected message */
+		return 0;
+
+	/* determine the nid for the used protection algorithm */
+	X509_ALGOR_get0( &algorOID, NULL, NULL, msg->header->protectionAlg);
+	nid = OBJ_obj2nid(algorOID);
+
+	switch (nid)
+		{
+		/* 5.1.3.1.  Shared Secret Information */
+		case NID_id_PasswordBasedMAC:
+			return CMP_verify_MAC(msg, ctx->secretValue);
+
+			/* TODO: 5.1.3.2.  DH Key Pairs */
+		case NID_id_DHBasedMac:
+			CMPerr(CMP_F_CMP_VALIDATE_MSG, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC);
+			break;
+
+			/* 5.1.3.3.  Signature */
+			/* TODO: should that better whitelist DSA/RSA etc.? -> check all possible options from OpenSSL, should there be a makro? */
+		default:
+			if (!srvCert) {
+				/* if we've already found and validated a server cert, and it matches the sender name,
+				 * we will use that, this is used for PKIconf where the server
+				 * certificate and others could be missing from the extraCerts */
+				if (ctx->validatedSrvCert &&
+					!X509_NAME_cmp(X509_get_subject_name(ctx->validatedSrvCert), msg->header->sender->d.directoryName))
+					{
+					srvCert = ctx->validatedSrvCert;
+					srvCert_valid = 1;
+					}
+				else
+					{
+					/* load the provided extraCerts to help with cert path validation */
+					CMP_CTX_loadUntrustedStack(ctx, msg->extraCerts);
+
+					/* try to find the server certificate from 1) trusted_store 2) untrusted_store 3) extaCerts*/
+					srvCert = findSrvCert(ctx, msg);
+
+					/* validate the that the found server Certificate is trusted */
+					srvCert_valid = CMP_validate_cert_path(ctx->trusted_store, ctx->untrusted_store, srvCert);
+
+					/* do an exceptional handling for 3GPP */	
+					if (!srvCert_valid)
+						{
+						/* For IP: when the ctxOption is set, extract the Trust Anchor from
+						 * ExtraCerts, provided that there is a self-signed certificate
+						 * which can be used to validate the issued certificate - refer to 3GPP TS 33.310 */
+
+						if (ctx->permitTAInExtraCertsForIR && CMP_PKIMESSAGE_get_bodytype(msg) == V_CMP_PKIBODY_IP)
+							{
+							X509_STORE *tempStore = createTempTrustedStore(msg->extraCerts);
+							/* TODO: check that issued certificates can validate against
+							 * trust achnor - and then exclusively use this CA */
+							srvCert_valid = CMP_validate_cert_path(tempStore, ctx->untrusted_store, srvCert);
+
+							if (srvCert_valid)
+								{
+								/* verify that our received certificate can also be validated with the same
+								 * trusted store as srvCert */
+								X509 *newClCert = CMP_CERTREPMESSAGE_get_certificate(ctx, msg->body->value.ip);
+								if (newClCert)
+									srvCert_valid = CMP_validate_cert_path(tempStore, ctx->untrusted_store, newClCert);
+								}
+							
+							X509_STORE_free(tempStore);
+							}
+						}
+					}
+				
+				/* verification failed if no valid server cert was found */
+				if (!srvCert_valid)
+					{
+					CMPerr(CMP_F_CMP_VALIDATE_MSG, CMP_R_NO_VALID_SRVCERT_FOUND);
+					return 0; 
+					}
+
+				/* store trusted server cert for future messages in this interaction */
+				ctx->validatedSrvCert = srvCert;
+				}
+			return CMP_verify_signature(msg, srvCert);
+		}
+	return 0;
+	}
+
Index: openssl-1.0.1h-cmp/crypto/crmf/Makefile
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/Makefile	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/Makefile	(revision 765)
@@ -0,0 +1,76 @@
+#
+# OpenSSL/crmf/Makefile
+#
+
+DIR=	crmf
+TOP=	../..
+CC=	cc
+INCLUDES= -I.. -I$(TOP) -I../../include
+CFLAG=-g
+MAKEFILE=	Makefile
+AR=		ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG) -Wall -DCRMF_DEBUG
+
+GENERAL=Makefile README
+TEST=
+APPS=
+
+LIB=$(TOP)/libcrypto.a
+LIBSRC= crmf_asn.c crmf_lib.c crmf_pbm.c crmf_msg.c crmf_err.c
+LIBOBJ= crmf_asn.o crmf_lib.o crmf_pbm.o crmf_msg.o crmf_err.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= crmf.h
+HEADER=	$(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+top:
+	(cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all:	lib
+
+lib:	$(LIBOBJ)
+	$(AR) $(LIB) $(LIBOBJ)
+	$(RANLIB) $(LIB) || echo Never mind.
+	@touch lib
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+
+links:
+	@$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+	@$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+	@$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+	@headerlist="$(EXHEADER)"; for i in $$headerlist ; \
+	do  \
+	(cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+	chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+	done;
+
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+	@[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
+	$(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(LIBSRC)
+
+dclean:
+	$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+	mv -f Makefile.new $(MAKEFILE)
+
+clean:
+	rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
Index: openssl-1.0.1h-cmp/crypto/crmf/crmf.h
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/crmf.h	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/crmf.h	(revision 764)
@@ -0,0 +1,626 @@
+/* vim: set cino={1s noet ts=4 sts=4 sw=4: */
+/* crypto/crmf/crmf.h
+ * Header file for CRMF (RFC 4211) for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#ifndef HEADER_CRMF_H
+#define HEADER_CRMF_H
+
+#include <openssl/ossl_typ.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/safestack.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+
+/*
+Attributes ::= SET OF Attribute
+=> X509_ATTRIBUTE
+
+PrivateKeyInfo ::= SEQUENCE {
+   version					 INTEGER,
+   privateKeyAlgorithm		 AlgorithmIdentifier,
+   privateKey				 OCTET STRING,
+   attributes				 [0] IMPLICIT Attributes OPTIONAL
+}
+*/
+typedef struct crmf_privatekeyinfo_st
+	{
+	ASN1_INTEGER			 *version;
+	X509_ALGOR				 *AlgorithmIdentifier;
+	ASN1_OCTET_STRING		 *privateKey;
+	STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+	} CRMF_PRIVATEKEYINFO;
+DECLARE_ASN1_FUNCTIONS(CRMF_PRIVATEKEYINFO)
+	
+
+/* section 4.2.1 Private Key Info Content Type
+   id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+
+EncKeyWithID ::= SEQUENCE {
+  privateKey		   PrivateKeyInfo,
+  identifier CHOICE {
+	string			   UTF8String,
+	generalName		   GeneralName
+  } OPTIONAL
+}
+*/
+typedef struct crmf_enckeywithid_identifier_st
+	{
+	int type;
+	union
+		{
+		ASN1_UTF8STRING *string;
+		GENERAL_NAME	*generalName;
+		} value;
+	} CRMF_ENCKEYWITHID_IDENTIFIER;
+	DECLARE_ASN1_FUNCTIONS(CRMF_ENCKEYWITHID_IDENTIFIER)
+
+typedef struct crmf_enckeywithid_st
+	{
+	CRMF_PRIVATEKEYINFO			 *privateKey;
+	CRMF_ENCKEYWITHID_IDENTIFIER *identifier; /* [0] */
+	} CRMF_ENCKEYWITHID;
+DECLARE_ASN1_FUNCTIONS(CRMF_ENCKEYWITHID)
+
+/*
+CertId ::= SEQUENCE {
+ issuer			  GeneralName,
+ serialNumber	  INTEGER }
+ */
+typedef struct crmf_certid_st
+	{
+	GENERAL_NAME *issuer;
+	ASN1_INTEGER *serialNumber;
+	} CRMF_CERTID;
+DECLARE_ASN1_FUNCTIONS(CRMF_CERTID)
+DECLARE_STACK_OF(CRMF_CERTID)
+
+/*
+EncryptedValue ::= SEQUENCE {
+ intendedAlg   [0] AlgorithmIdentifier	OPTIONAL,
+ -- the intended algorithm for which the value will be used
+ symmAlg	   [1] AlgorithmIdentifier	OPTIONAL,
+ -- the symmetric algorithm used to encrypt the value
+ encSymmKey    [2] BIT STRING			OPTIONAL,
+ -- the (encrypted) symmetric key used to encrypt the value
+ keyAlg		   [3] AlgorithmIdentifier	OPTIONAL,
+ -- algorithm used to encrypt the symmetric key
+ valueHint	   [4] OCTET STRING			OPTIONAL,
+ -- a brief description or identifier of the encValue content
+ -- (may be meaningful only to the sending entity, and used only
+ -- if EncryptedValue might be re-examined by the sending entity
+ -- in the future)
+ encValue		BIT STRING }
+ -- the encrypted value itself
+*/
+typedef struct crmf_encrypetedvalue_st
+	{
+	X509_ALGOR				 *intendedAlg; /* 0 */
+	X509_ALGOR				 *symmAlg; /* 1 */
+	ASN1_BIT_STRING			 *encSymmKey; /* 2 */
+	X509_ALGOR				 *keyAlg; /* 3 */
+	ASN1_OCTET_STRING		 *valueHint; /* 4 */
+	ASN1_BIT_STRING			 *encValue;
+	} CRMF_ENCRYPTEDVALUE;
+DECLARE_ASN1_FUNCTIONS(CRMF_ENCRYPTEDVALUE)
+
+/*
+EncryptedKey ::= CHOICE {
+ encryptedValue		   EncryptedValue,	 -- Deprecated
+ envelopedData	   [0] EnvelopedData }
+ */
+typedef struct crmf_encryptedkey_st
+	{
+	int type;
+	union
+		{
+		CRMF_ENCRYPTEDVALUE *encryptedValue; /* Deprecated */
+		/* TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be somehow taken from crypto/cms which exists now - this is not used anywhere so far */
+		ASN1_NULL *envelopedData;
+		} value;
+	} CRMF_ENCRYPTEDKEY;
+DECLARE_ASN1_FUNCTIONS(CRMF_ENCRYPTEDKEY)
+
+/*
+PKIArchiveOptions ::= CHOICE {
+ encryptedPrivKey	  [0] EncryptedKey,
+ -- the actual value of the private key
+ keyGenParameters	  [1] KeyGenParameters,
+ -- parameters that allow the private key to be re-generated
+ archiveRemGenPrivKey [2] BOOLEAN }
+ -- set to TRUE if sender wishes receiver to archive the private
+ -- key of a key pair that the receiver generates in response to
+ -- this request; set to FALSE if no archival is desired.
+*/
+typedef struct crmf_pkiarchiveoptions_st
+	{
+	int type;
+	union
+		{
+		CRMF_ENCRYPTEDKEY *encryptedPrivKey; /* 0 */
+		ASN1_OCTET_STRING *keyGenParameters; /* KeyGenParameters ::= OCTET STRING */ /* 1 */
+		ASN1_BOOLEAN	  *archiveRemGenPrivKey; /* 2 */
+		} value;
+	} CRMF_PKIARCHIVEOPTIONS;
+DECLARE_ASN1_FUNCTIONS(CRMF_PKIARCHIVEOPTIONS)
+CRMF_PKIARCHIVEOPTIONS *CRMF_PKIARCHIVEOPTIONS_dup( CRMF_PKIARCHIVEOPTIONS *pkiPubInfo);
+
+/*
+SinglePubInfo ::= SEQUENCE {
+ pubMethod	  INTEGER {
+	 dontCare	 (0),
+	 x500		 (1),
+	 web		 (2),
+	 ldap		 (3) },
+ pubLocation  GeneralName OPTIONAL }
+ */
+typedef struct crmf_singlepubinfo_st
+	{
+	ASN1_INTEGER *pubMethod;
+	GENERAL_NAME *pubLocation;
+	} CRMF_SINGLEPUBINFO;
+DECLARE_ASN1_FUNCTIONS(CRMF_SINGLEPUBINFO)
+
+/*
+PKIPublicationInfo ::= SEQUENCE {
+action	   INTEGER {
+			 dontPublish (0),
+			 pleasePublish (1) },
+pubInfos  SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+  -- pubInfos MUST NOT be present if action is "dontPublish"
+  -- (if action is "pleasePublish" and pubInfos is omitted,
+  -- "dontCare" is assumed)
+*/
+typedef struct crmf_pkipublicationinfo_st
+	{
+	ASN1_INTEGER *action;
+	CRMF_SINGLEPUBINFO *pubinfos;
+	} CRMF_PKIPUBLICATIONINFO;
+DECLARE_ASN1_FUNCTIONS(CRMF_PKIPUBLICATIONINFO)
+CRMF_PKIPUBLICATIONINFO *CRMF_PKIPUBLICATIONINFO_dup( CRMF_PKIPUBLICATIONINFO *pkiPubInfo);
+
+/*
+PKMACValue ::= SEQUENCE {
+algId  AlgorithmIdentifier,
+-- algorithm value shall be PasswordBasedMac {1 2 840 113533 7 66 13}
+-- parameter value is PBMParameter
+value  BIT STRING }
+*/
+typedef struct crmf_pkmacvalue_st
+	{
+	X509_ALGOR		*algId;
+	ASN1_BIT_STRING *value;
+	} CRMF_PKMACVALUE;
+DECLARE_ASN1_FUNCTIONS(CRMF_PKMACVALUE)
+
+/*
+SubsequentMessage ::= INTEGER {
+ encrCert (0),
+ -- requests that resulting certificate be encrypted for the
+ -- end entity (following which, POP will be proven in a
+ -- confirmation message)
+ challengeResp (1) }
+ -- requests that CA engage in challenge-response exchange with
+ -- end entity in order to prove private key possession
+
+POPOPrivKey ::= CHOICE {
+ thisMessage	   [0] BIT STRING,		   -- Deprecated
+ -- possession is proven in this message (which contains the private
+ -- key itself (encrypted for the CA))
+ subsequentMessage [1] SubsequentMessage,
+ -- possession will be proven in a subsequent message
+ dhMAC			   [2] BIT STRING,		   -- Deprecated
+ agreeMAC		   [3] PKMACValue,
+ encryptedKey	   [4] EnvelopedData }
+*/
+#define CRMF_POPOPRIVKEY_THISMESSAGE	   0
+#define CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE 1
+#define CRMF_POPOPRIVKEY_DHMAC			   2
+#define CRMF_POPOPRIVKEY_AGREEMAC		   3
+#define CRMF_POPOPRIVKEY_ENCRYPTEDKEY	   4
+
+#define CRMF_SUBSEQUENTMESSAGE_ENCRCERT		 0
+#define CRMF_SUBSEQUENTMESSAGE_CHALLENGERESP 1
+
+typedef struct crmf_popoprivkey_st
+	{
+	int type;
+	union
+		{
+		ASN1_BIT_STRING   *thisMessage; /* Deprecated */ /* 0 */
+		ASN1_INTEGER	  *subsequentMessage; /* 1 */
+		ASN1_BIT_STRING   *dhMAC; /* 2 */
+		CRMF_PKMACVALUE   *agreeMAC; /* 3 */
+		/* TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be somehow taken from crypto/cms which exists now - this is not used anywhere so far */
+		ASN1_NULL		  *encryptedKey; /* 4 */
+		} value;
+	} CRMF_POPOPRIVKEY;
+DECLARE_ASN1_FUNCTIONS(CRMF_POPOPRIVKEY)
+
+/*
+PBMParameter ::= SEQUENCE {
+   salt				   OCTET STRING,
+   owf				   AlgorithmIdentifier,
+   -- AlgId for a One-Way Function (SHA-1 recommended)
+   iterationCount	   INTEGER,
+   -- number of times the OWF is applied
+   mac				   AlgorithmIdentifier
+   -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+}	-- or HMAC [HMAC, RFC2202])
+*/
+typedef struct crmf_pbmparameter_st
+	{
+	ASN1_OCTET_STRING *salt;
+	X509_ALGOR		  *owf;
+	ASN1_INTEGER	  *iterationCount;
+	X509_ALGOR		  *mac;
+	} CRMF_PBMPARAMETER;
+DECLARE_ASN1_FUNCTIONS(CRMF_PBMPARAMETER)
+
+/*
+POPOSigningKeyInput ::= SEQUENCE {
+ authInfo			 CHOICE {
+	 sender				 [0] GeneralName,
+	 -- used only if an authenticated identity has been
+	 -- established for the sender (e.g., a DN from a
+	 -- previously-issued and currently-valid certificate)
+	 publicKeyMAC		 PKMACValue },
+	 -- used if no authenticated GeneralName currently exists for
+	 -- the sender; publicKeyMAC contains a password-based MAC
+	 -- on the DER-encoded value of publicKey
+ publicKey			 SubjectPublicKeyInfo }  -- from CertTemplate
+*/
+typedef struct crmf_poposigningkeyinput_authinfo_st
+	{
+	int type;
+	union
+		{
+		GENERAL_NAME	*sender; /* 0 */
+		CRMF_PKMACVALUE *publicKeyMAC; /* 1 */
+		} value;
+	} CRMF_POPOSIGNINGKEYINPUT_AUTHINFO;
+DECLARE_ASN1_FUNCTIONS(CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+
+typedef struct crmf_poposigningkeyinput_st
+	{
+	CRMF_POPOSIGNINGKEYINPUT_AUTHINFO *authinfo;
+	X509_PUBKEY *publicKey;
+	} CRMF_POPOSIGNINGKEYINPUT;
+DECLARE_ASN1_FUNCTIONS(CRMF_POPOSIGNINGKEYINPUT)
+
+/*
+POPOSigningKey ::= SEQUENCE {
+ poposkInput		   [0] POPOSigningKeyInput OPTIONAL,
+ algorithmIdentifier   AlgorithmIdentifier,
+ signature			   BIT STRING }
+ */
+typedef struct crmf_poposigningkey_st
+	{
+	CRMF_POPOSIGNINGKEYINPUT *poposkInput;
+	X509_ALGOR				 *algorithmIdentifier;
+	ASN1_BIT_STRING			 *signature;
+	} CRMF_POPOSIGNINGKEY;
+DECLARE_ASN1_FUNCTIONS(CRMF_POPOSIGNINGKEY)
+
+/*
+ProofOfPossession ::= CHOICE {
+ raVerified		   [0] NULL,
+ -- used if the RA has already verified that the requester is in
+ -- possession of the private key
+ signature		   [1] POPOSigningKey,
+ keyEncipherment   [2] POPOPrivKey,
+ keyAgreement	   [3] POPOPrivKey }
+ */
+#define CRMF_PROOFOFPOSESSION_RAVERIFIED	  0
+#define CRMF_PROOFOFPOSESSION_SIGNATURE		  1
+#define CRMF_PROOFOFPOSESSION_KEYENCIPHERMENT 2
+#define CRMF_PROOFOFPOSESSION_KEYAGREEMENT	  3
+typedef struct crmf_proofofpossesion_st
+	{
+	int type;
+	union
+		{
+		ASN1_NULL			*raVerified; /* 0 */
+		CRMF_POPOSIGNINGKEY *signature;  /* 1 */
+		CRMF_POPOPRIVKEY	*keyEncipherment; /* 2 */
+		CRMF_POPOPRIVKEY	*keyAgreement; /* 3 */
+		} value;
+	} CRMF_PROOFOFPOSSESION;
+DECLARE_ASN1_FUNCTIONS(CRMF_PROOFOFPOSSESION)
+
+/*
+OptionalValidity ::= SEQUENCE {
+ notBefore	[0] Time OPTIONAL,
+ notAfter	[1] Time OPTIONAL } -- at least one MUST be present
+ */
+typedef struct crmf_optionalvalidity_st
+	{
+	ASN1_TIME *notBefore; /* 0 */
+	ASN1_TIME *notAfter;  /* 1 */
+	} CRMF_OPTIONALVALIDITY;
+DECLARE_ASN1_FUNCTIONS(CRMF_OPTIONALVALIDITY)
+
+/*
+CertTemplate ::= SEQUENCE {
+ version	  [0] Version				OPTIONAL,
+ serialNumber [1] INTEGER				OPTIONAL,
+ signingAlg   [2] AlgorithmIdentifier	OPTIONAL,
+ issuer		  [3] Name					OPTIONAL,
+ validity	  [4] OptionalValidity		OPTIONAL,
+ subject	  [5] Name					OPTIONAL,
+ publicKey	  [6] SubjectPublicKeyInfo	OPTIONAL,
+ issuerUID	  [7] UniqueIdentifier		OPTIONAL,
+ subjectUID   [8] UniqueIdentifier		OPTIONAL,
+ extensions   [9] Extensions			OPTIONAL }
+ */
+
+typedef struct crmf_certtemplate_st
+	{
+	ASN1_INTEGER *version;		 /* 0 */
+	/* serialNumber MUST be omitted.  This field is assigned by the CA
+	 * during certificate creation. */
+	ASN1_INTEGER *serialNumber;  /* 1 */
+	/* signingAlg MUST be omitted.	This field is assigned by the CA
+	 * during certificate creation. */
+	X509_ALGOR	 *signingAlg;	 /* 2 */
+	X509_NAME	 *issuer;		 /* 3 */
+	CRMF_OPTIONALVALIDITY *validity; /* 4 */
+	X509_NAME	 *subject;		 /* 5 */
+	X509_PUBKEY  *publicKey;	 /* 6 */
+	/* According to rfc 3280:
+	   UniqueIdentifier  ::=  BIT STRING
+	*/
+	/* issuerUID is deprecated in version 2 */
+	ASN1_BIT_STRING *issuerUID;  /* 7 */
+	/* subjectUID is deprecated in version 2 */
+	ASN1_BIT_STRING *subjectUID; /* 8 */
+#if 0
+	/* TODO: That should be - but that's only cosmetical */
+	X509_EXTENSIONS	*extensions; /* 9 */
+#endif
+	STACK_OF(X509_EXTENSION)  *extensions; /* 9 */
+	} CRMF_CERTTEMPLATE;
+DECLARE_ASN1_FUNCTIONS(CRMF_CERTTEMPLATE)
+
+/*
+CertRequest ::= SEQUENCE {
+ certReqId	   INTEGER,			 -- ID for matching request and reply
+ certTemplate  CertTemplate,  -- Selected fields of cert to be issued
+ controls	   Controls OPTIONAL }	 -- Attributes affecting issuance
+ */
+typedef struct crmf_certrequest_st
+	{
+	ASN1_INTEGER	  *certReqId;
+	CRMF_CERTTEMPLATE *certTemplate;
+	/* TODO: make CRMF_CONTROLS out of that - but only cosmetical */
+	STACK_OF(CRMF_ATTRIBUTETYPEANDVALUE) *controls;
+	} CRMF_CERTREQUEST;
+DECLARE_ASN1_FUNCTIONS(CRMF_CERTREQUEST)
+CRMF_CERTREQUEST *CRMF_CERTREQUEST_dup( CRMF_CERTREQUEST *atav);
+
+/* TODO: isn't there a better way to have this for ANY type? */
+typedef struct crmf_attributetypeandvalue_st
+	{
+	ASN1_OBJECT *type;
+	union
+		{
+		/* NID_id_regCtrl_regToken */ 
+		ASN1_UTF8STRING *regToken;
+
+		/* NID_id_regCtrl_authenticator */ 
+		ASN1_UTF8STRING *authenticator;
+
+		/* NID_id_regCtrl_pkiPublicationInfo */
+		CRMF_PKIPUBLICATIONINFO *pkiPublicationInfo;
+
+		/* NID_id_regCtrl_pkiArchiveOptions */ 
+		CRMF_PKIARCHIVEOPTIONS *pkiArchiveOptions;
+
+		/* NID_id_regCtrl_oldCertID */
+		CRMF_CERTID		*oldCertId;
+
+		/* NID_id_regCtrl_protocolEncrKey */
+		X509_PUBKEY		*protocolEncrKey;
+
+		/* NID_id_regInfo_utf8Pairs */ 
+		ASN1_UTF8STRING *utf8pairs;
+
+		/* NID_id_regInfo_certReq */ 
+		CRMF_CERTREQUEST *certReq;
+
+		ASN1_TYPE *other;
+		} value;
+	} CRMF_ATTRIBUTETYPEANDVALUE;
+DECLARE_ASN1_FUNCTIONS(CRMF_ATTRIBUTETYPEANDVALUE)
+DECLARE_STACK_OF(CRMF_ATTRIBUTETYPEANDVALUE)
+CRMF_ATTRIBUTETYPEANDVALUE *CRMF_ATTRIBUTETYPEANDVALUE_dup( CRMF_ATTRIBUTETYPEANDVALUE *atav);
+
+/*
+CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+
+CertReqMsg ::= SEQUENCE {
+ certReq   CertRequest,
+ popo		ProofOfPossession  OPTIONAL,
+ -- content depends upon key type
+ regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+ */
+typedef struct crmf_certreqmsg_st
+	{
+	CRMF_CERTREQUEST		   *certReq;
+	CRMF_PROOFOFPOSSESION	   *popo;	 /* 0 */
+	STACK_OF(CRMF_ATTRIBUTETYPEANDVALUE) *regInfo; /* 1 */
+	} CRMF_CERTREQMSG;
+DECLARE_ASN1_FUNCTIONS(CRMF_CERTREQMSG)
+
+typedef STACK_OF(CRMF_CERTREQMSG) CRMF_CERTREQMESSAGES;
+DECLARE_ASN1_FUNCTIONS(CRMF_CERTREQMESSAGES)
+
+DECLARE_STACK_OF(CRMF_CERTREQMSG) /* CertReqMessages */
+DECLARE_ASN1_SET_OF(CRMF_CERTREQMSG) /* CertReqMessages */
+
+
+/* ########################################################################## *
+ * function DECLARATIONS
+ * ########################################################################## */
+/* crmf_msg.c */
+CRMF_CERTREQMSG * CRMF_cr_new( const long certReqId, const EVP_PKEY *pkey, const X509_NAME *subject, X509_EXTENSIONS *extensions);
+
+/* crmf_pbm.c */
+CRMF_PBMPARAMETER * CRMF_pbm_new(void);
+int CRMF_passwordBasedMac_new( const CRMF_PBMPARAMETER *pbm, const unsigned char* msg, size_t msgLen, const unsigned char* secret, size_t secretLen, unsigned char** mac, unsigned int* macLen);
+
+/* crmf_lib.c */
+int CRMF_CERTREQMSG_push0_control( CRMF_CERTREQMSG *certReqMsg, CRMF_ATTRIBUTETYPEANDVALUE *control);
+int CRMF_CERTREQMSG_set1_control_regToken( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *tok);
+int CRMF_CERTREQMSG_set1_control_authenticator( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *auth);
+int CRMF_CERTREQMSG_push0_regInfo( CRMF_CERTREQMSG *certReqMsg, CRMF_ATTRIBUTETYPEANDVALUE *regInfo);
+int CRMF_CERTREQMSG_set1_regInfo_regToken( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *tok);
+
+int CRMF_CERTREQMSG_set_version2( CRMF_CERTREQMSG *certReqMsg);
+int CRMF_CERTREQMSG_set_validity( CRMF_CERTREQMSG *certReqMsg, time_t notBefore, time_t notAfter);
+int CRMF_CERTREQMSG_set_certReqId( CRMF_CERTREQMSG *certReqMsg, const long certReqId);
+int CRMF_CERTREQMSG_set1_publicKey( CRMF_CERTREQMSG *certReqMsg, const EVP_PKEY *pkey);
+int CRMF_CERTREQMSG_set1_subject( CRMF_CERTREQMSG *certReqMsg, const X509_NAME *subject);
+int CRMF_CERTREQMSG_push0_extension( CRMF_CERTREQMSG *certReqMsg, X509_EXTENSION *ext);
+
+#define CRMF_POPO_NONE		0
+#define CRMF_POPO_SIGNATURE 1
+#define CRMF_POPO_ENCRCERT	2
+#define CRMF_POPO_RAVERIFIED	3
+int CRMF_CERTREQMSG_calc_and_set_popo( CRMF_CERTREQMSG *certReqMsg, const EVP_PKEY *pkey, int popoMethod);
+
+CRMF_POPOSIGNINGKEY * CRMF_poposigningkey_new( CRMF_CERTREQUEST *certReq, const EVP_PKEY *pkey);
+
+int CRMF_CERTREQMSG_set1_control_oldCertId( CRMF_CERTREQMSG *certReqMsg, X509 *oldCert);
+
+/* 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.
+ */
+void ERR_load_CRMF_strings(void);
+
+/* Error codes for the CRMF functions. */
+
+/* Function codes. */
+#define CRMF_F_CRMF_CERTREQMSG_CALC_AND_SET_POPO	 107
+#define CRMF_F_CRMF_CERTREQMSG_PUSH0_CONTROL		 100
+#define CRMF_F_CRMF_CERTREQMSG_PUSH0_EXTENSION		 101
+#define CRMF_F_CRMF_CERTREQMSG_PUSH0_REGINFO		 102
+#define CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_AUTHENTICATOR 121
+#define CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_OLDCERTID	 122
+#define CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PKIARCHIVEOPTIONS 131
+#define CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PKIPUBLICATIONINFO 123
+#define CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PROTOCOLENCRKEY 124
+#define CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_REGTOKEN	 108
+#define CRMF_F_CRMF_CERTREQMSG_SET1_PUBLICKEY		 103
+#define CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_CERTREQ	 125
+#define CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_REGTOKEN	 126
+#define CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_UTF8PAIRS	 127
+#define CRMF_F_CRMF_CERTREQMSG_SET1_SUBJECT		 128
+#define CRMF_F_CRMF_CERTREQMSG_SET_CERTREQID		 129
+#define CRMF_F_CRMF_CERTREQMSG_SET_VALIDITY		 104
+#define CRMF_F_CRMF_CERTREQMSG_SET_VERSION2		 130
+#define CRMF_F_CRMF_CR_NEW				 105
+#define CRMF_F_CRMF_PASSWORDBASEDMAC_NEW		 106
+#define CRMF_F_CRMF_POPOSIGNINGKEY_NEW			 109
+#define CRMF_F_CRMF_SET1_CONTROL_AUTHENTICATOR		 110
+#define CRMF_F_CRMF_SET1_CONTROL_OLDCERTID		 111
+#define CRMF_F_CRMF_SET1_CONTROL_PKIARCHIVEOPTIONS	 112
+#define CRMF_F_CRMF_SET1_CONTROL_PKIPUBLICATIONINFO	 113
+#define CRMF_F_CRMF_SET1_CONTROL_PROTOCOLENCRKEY	 114
+#define CRMF_F_CRMF_SET1_REGINFO_CERTREQ		 115
+#define CRMF_F_CRMF_SET1_REGINFO_UTF8PAIRS		 116
+#define CRMF_F_CRMF_SET1_REGTOKEN_CERTREQ		 117
+#define CRMF_F_CRMF_SET1_SUBJECT			 118
+#define CRMF_F_CRMF_SET_CERTREQID			 119
+#define CRMF_F_CRMF_SET_VERSION2			 120
+
+/* Reason codes. */
+#define CRMF_R_CRMFERROR				 100
+#define CRMF_R_ERROR_CALCULATING_AND_SETTING_POPO	 103
+#define CRMF_R_ERROR_SETTING_CONTROL_AUTHENTICATOR_ATAV	 104
+#define CRMF_R_ERROR_SETTING_CONTROL_OLDCERTID_ATAV	 105
+#define CRMF_R_ERROR_SETTING_CONTROL_PKIARCHIVEOPTIONS_ATAV 106
+#define CRMF_R_ERROR_SETTING_CONTROL_PKIPUBLICATIONINFO_ATAV 107
+#define CRMF_R_ERROR_SETTING_CONTROL_PROTOCOLENCRKEY_ATAV 108
+#define CRMF_R_ERROR_SETTING_POPSIGNINGKEY		 109
+#define CRMF_R_ERROR_SETTING_PUBLIC_KEY			 101
+#define CRMF_R_ERROR_SETTING_REGINFO_CERTREQ_ATAV	 110
+#define CRMF_R_ERROR_SETTING_REGINFO_UTF8PAIRS_ATAV	 111
+#define CRMF_R_ERROR_SETTING_REGTOKEN_ATAV		 112
+#define CRMF_R_ERROR_SETTING_REGTOKEN_CERTREQ_ATAV	 113
+#define CRMF_R_ERROR_SETTING_VERSION_2			 114
+#define CRMF_R_UNSUPPORTED_ALGORITHM			 102
+#define CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY	 115
+#define CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO	 116
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
Index: openssl-1.0.1h-cmp/crypto/crmf/crmf_asn.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/crmf_asn.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/crmf_asn.c	(revision 764)
@@ -0,0 +1,275 @@
+/* vim: set cino={1s noet ts=4 sts=4 sw=4: */
+/* crmf_asn.c
+ * OpenSSL ASN.1 definitions for CRMF (RFC 4211)
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+
+ASN1_SEQUENCE(CRMF_PRIVATEKEYINFO) = {
+	ASN1_SIMPLE(CRMF_PRIVATEKEYINFO, version, ASN1_INTEGER),
+	ASN1_SIMPLE(CRMF_PRIVATEKEYINFO, AlgorithmIdentifier, X509_ALGOR),
+	ASN1_SIMPLE(CRMF_PRIVATEKEYINFO, privateKey, ASN1_OCTET_STRING),
+	ASN1_IMP_SET_OF_OPT(CRMF_PRIVATEKEYINFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END(CRMF_PRIVATEKEYINFO)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_PRIVATEKEYINFO)
+
+
+ASN1_CHOICE(CRMF_ENCKEYWITHID_IDENTIFIER) = {
+	ASN1_IMP(CRMF_ENCKEYWITHID_IDENTIFIER, value.string, ASN1_UTF8STRING, 0),
+	ASN1_IMP(CRMF_ENCKEYWITHID_IDENTIFIER, value.generalName, GENERAL_NAME, 1)
+} ASN1_CHOICE_END(CRMF_ENCKEYWITHID_IDENTIFIER)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_ENCKEYWITHID_IDENTIFIER)
+
+
+ASN1_SEQUENCE(CRMF_ENCKEYWITHID) = {
+	ASN1_SIMPLE(CRMF_ENCKEYWITHID, privateKey, CRMF_PRIVATEKEYINFO),
+	ASN1_IMP_OPT(CRMF_ENCKEYWITHID, identifier, CRMF_ENCKEYWITHID_IDENTIFIER,0)
+} ASN1_SEQUENCE_END(CRMF_ENCKEYWITHID)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_ENCKEYWITHID)
+
+
+ASN1_SEQUENCE(CRMF_CERTID) = {
+	ASN1_SIMPLE(CRMF_CERTID, issuer, GENERAL_NAME),
+	ASN1_SIMPLE(CRMF_CERTID, serialNumber, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(CRMF_CERTID)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_CERTID)
+
+
+ASN1_SEQUENCE(CRMF_ENCRYPTEDVALUE) = {
+	ASN1_IMP_OPT(CRMF_ENCRYPTEDVALUE, intendedAlg, X509_ALGOR,0),
+	ASN1_IMP_OPT(CRMF_ENCRYPTEDVALUE, symmAlg, X509_ALGOR,1),
+	ASN1_IMP_OPT(CRMF_ENCRYPTEDVALUE, encSymmKey, ASN1_BIT_STRING,2),
+	ASN1_IMP_OPT(CRMF_ENCRYPTEDVALUE, keyAlg, X509_ALGOR,3),
+	ASN1_IMP_OPT(CRMF_ENCRYPTEDVALUE, valueHint, ASN1_OCTET_STRING,4),
+	ASN1_SIMPLE(CRMF_ENCRYPTEDVALUE, encValue, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(CRMF_ENCRYPTEDVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_ENCRYPTEDVALUE)
+
+
+ASN1_CHOICE(CRMF_ENCRYPTEDKEY) = {
+	ASN1_IMP(CRMF_ENCRYPTEDKEY, value.encryptedValue, CRMF_ENCRYPTEDVALUE, 0),
+	/* TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be somehow taken from crypto/cms which exists now - this is not used anywhere so far */
+	ASN1_IMP(CRMF_ENCRYPTEDKEY, value.envelopedData, ASN1_NULL, 1)
+} ASN1_CHOICE_END(CRMF_ENCRYPTEDKEY)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_ENCRYPTEDKEY)
+
+
+ASN1_CHOICE(CRMF_PKIARCHIVEOPTIONS) = {
+	ASN1_IMP(CRMF_PKIARCHIVEOPTIONS, value.encryptedPrivKey, CRMF_ENCRYPTEDKEY, 0),
+	ASN1_IMP(CRMF_PKIARCHIVEOPTIONS, value.keyGenParameters, ASN1_OCTET_STRING, 1),
+	ASN1_IMP(CRMF_PKIARCHIVEOPTIONS, value.archiveRemGenPrivKey, ASN1_BOOLEAN, 2)
+} ASN1_CHOICE_END(CRMF_PKIARCHIVEOPTIONS)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_PKIARCHIVEOPTIONS)
+IMPLEMENT_ASN1_DUP_FUNCTION(CRMF_PKIARCHIVEOPTIONS)
+
+
+ASN1_SEQUENCE(CRMF_SINGLEPUBINFO) = {
+	ASN1_SIMPLE(CRMF_SINGLEPUBINFO, pubMethod, ASN1_INTEGER),
+	ASN1_SIMPLE(CRMF_SINGLEPUBINFO, pubLocation, GENERAL_NAME)
+} ASN1_SEQUENCE_END(CRMF_SINGLEPUBINFO)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_SINGLEPUBINFO)
+
+
+ASN1_SEQUENCE(CRMF_PKIPUBLICATIONINFO) = {
+	ASN1_SIMPLE(CRMF_PKIPUBLICATIONINFO, action, ASN1_INTEGER),
+	ASN1_SEQUENCE_OF_OPT(CRMF_PKIPUBLICATIONINFO, pubinfos, GENERAL_NAME)
+} ASN1_SEQUENCE_END(CRMF_PKIPUBLICATIONINFO)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_PKIPUBLICATIONINFO)
+IMPLEMENT_ASN1_DUP_FUNCTION(CRMF_PKIPUBLICATIONINFO)
+
+
+ASN1_SEQUENCE(CRMF_PKMACVALUE) = {
+	ASN1_SIMPLE(CRMF_PKMACVALUE, algId, X509_ALGOR),
+	ASN1_SIMPLE(CRMF_PKMACVALUE, value, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(CRMF_PKMACVALUE)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_PKMACVALUE)
+
+
+ASN1_CHOICE(CRMF_POPOPRIVKEY) = {
+	ASN1_IMP(CRMF_POPOPRIVKEY, value.thisMessage, ASN1_BIT_STRING, 0),
+	ASN1_IMP(CRMF_POPOPRIVKEY, value.subsequentMessage, ASN1_INTEGER, 1),
+	ASN1_IMP(CRMF_POPOPRIVKEY, value.dhMAC, ASN1_BIT_STRING, 2),
+	ASN1_IMP(CRMF_POPOPRIVKEY, value.agreeMAC, CRMF_PKMACVALUE, 3),
+	/* TODO: This is not ASN1_NULL but CMS_ENVELOPEDDATA which should be somehow taken from crypto/cms which exists now - this is not used anywhere so far */
+	ASN1_IMP(CRMF_POPOPRIVKEY, value.encryptedKey, ASN1_NULL, 4),
+} ASN1_CHOICE_END(CRMF_POPOPRIVKEY)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_POPOPRIVKEY)
+
+
+ASN1_SEQUENCE(CRMF_PBMPARAMETER) = {
+	ASN1_SIMPLE(CRMF_PBMPARAMETER, salt, ASN1_OCTET_STRING),
+	ASN1_SIMPLE(CRMF_PBMPARAMETER, owf, X509_ALGOR),
+	ASN1_SIMPLE(CRMF_PBMPARAMETER, iterationCount, ASN1_INTEGER),
+	ASN1_SIMPLE(CRMF_PBMPARAMETER, mac, X509_ALGOR)
+} ASN1_SEQUENCE_END(CRMF_PBMPARAMETER)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_PBMPARAMETER)
+
+
+ASN1_CHOICE(CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) = {
+	ASN1_EXP(CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.sender, GENERAL_NAME, 0),
+	ASN1_SIMPLE(CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.publicKeyMAC, CRMF_PKMACVALUE)
+} ASN1_CHOICE_END(CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_POPOSIGNINGKEYINPUT_AUTHINFO)
+
+
+ASN1_SEQUENCE(CRMF_POPOSIGNINGKEYINPUT) = {
+	ASN1_SIMPLE(CRMF_POPOSIGNINGKEYINPUT, authinfo, CRMF_POPOSIGNINGKEYINPUT_AUTHINFO),
+	ASN1_SIMPLE(CRMF_POPOSIGNINGKEYINPUT, publicKey, X509_PUBKEY)
+} ASN1_SEQUENCE_END(CRMF_POPOSIGNINGKEYINPUT)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_POPOSIGNINGKEYINPUT)
+
+
+ASN1_SEQUENCE(CRMF_POPOSIGNINGKEY) = {
+	ASN1_IMP_OPT(CRMF_POPOSIGNINGKEY, poposkInput, CRMF_POPOSIGNINGKEYINPUT,0),
+	ASN1_SIMPLE(CRMF_POPOSIGNINGKEY, algorithmIdentifier, X509_ALGOR),
+	ASN1_SIMPLE(CRMF_POPOSIGNINGKEY, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(CRMF_POPOSIGNINGKEY)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_POPOSIGNINGKEY)
+
+
+ASN1_CHOICE(CRMF_PROOFOFPOSSESION) = {
+	ASN1_IMP(CRMF_PROOFOFPOSSESION, value.raVerified, ASN1_NULL, 0),
+	ASN1_IMP(CRMF_PROOFOFPOSSESION, value.signature, CRMF_POPOSIGNINGKEY, 1),
+	ASN1_EXP(CRMF_PROOFOFPOSSESION, value.keyEncipherment, CRMF_POPOPRIVKEY, 2),
+	ASN1_IMP(CRMF_PROOFOFPOSSESION, value.keyAgreement, CRMF_POPOPRIVKEY, 3)
+} ASN1_CHOICE_END(CRMF_PROOFOFPOSSESION)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_PROOFOFPOSSESION)
+
+
+ASN1_ADB_TEMPLATE(attributetypeandvalue_default) = ASN1_OPT(CRMF_ATTRIBUTETYPEANDVALUE, value.other, ASN1_ANY);
+ASN1_ADB(CRMF_ATTRIBUTETYPEANDVALUE) = {
+	ADB_ENTRY(NID_id_regCtrl_regToken,			 ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.regToken,		   ASN1_UTF8STRING)),
+	ADB_ENTRY(NID_id_regCtrl_authenticator,		 ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.authenticator,	   ASN1_UTF8STRING)),
+	ADB_ENTRY(NID_id_regCtrl_pkiPublicationInfo, ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.pkiPublicationInfo, CRMF_PKIPUBLICATIONINFO)),
+	ADB_ENTRY(NID_id_regCtrl_pkiArchiveOptions,  ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.pkiArchiveOptions,  CRMF_PKIARCHIVEOPTIONS)),
+	ADB_ENTRY(NID_id_regCtrl_oldCertID,			 ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.oldCertId,		   CRMF_CERTID)),
+	ADB_ENTRY(NID_id_regCtrl_protocolEncrKey,	 ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.protocolEncrKey,    X509_PUBKEY)),
+	ADB_ENTRY(NID_id_regInfo_utf8Pairs,			 ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.utf8pairs,		   ASN1_UTF8STRING)),
+	ADB_ENTRY(NID_id_regInfo_certReq,			 ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, value.certReq,			   CRMF_CERTREQUEST)),
+} ASN1_ADB_END(CRMF_ATTRIBUTETYPEANDVALUE, 0, type, 0, &attributetypeandvalue_default_tt, NULL);
+
+
+ASN1_SEQUENCE(CRMF_ATTRIBUTETYPEANDVALUE) = 
+{
+	ASN1_SIMPLE(CRMF_ATTRIBUTETYPEANDVALUE, type, ASN1_OBJECT),
+	ASN1_ADB_OBJECT(CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(CRMF_ATTRIBUTETYPEANDVALUE)
+
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_ATTRIBUTETYPEANDVALUE)
+IMPLEMENT_ASN1_DUP_FUNCTION(CRMF_ATTRIBUTETYPEANDVALUE)
+
+
+ASN1_SEQUENCE(CRMF_OPTIONALVALIDITY) = {
+	ASN1_EXP_OPT(CRMF_OPTIONALVALIDITY, notBefore, ASN1_TIME, 0),
+	ASN1_EXP_OPT(CRMF_OPTIONALVALIDITY, notAfter, ASN1_TIME, 1)
+} ASN1_SEQUENCE_END(CRMF_OPTIONALVALIDITY)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_OPTIONALVALIDITY)
+
+
+ASN1_SEQUENCE(CRMF_CERTTEMPLATE) = {
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, version, ASN1_INTEGER, 0),
+	/* serialNumber MUST be omitted.  This field is assigned by the CA
+	 * during certificate creation. */
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, serialNumber, ASN1_INTEGER, 1),
+	/* signingAlg MUST be omitted.	This field is assigned by the CA
+	 * during certificate creation. */
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, signingAlg, X509_ALGOR, 2),
+	ASN1_EXP_OPT(CRMF_CERTTEMPLATE, issuer, X509_NAME, 3),
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, validity, CRMF_OPTIONALVALIDITY, 4),
+	ASN1_EXP_OPT(CRMF_CERTTEMPLATE, subject, X509_NAME, 5),
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, publicKey, X509_PUBKEY, 6),
+	/* issuerUID is deprecated in version 2 */
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, issuerUID, ASN1_BIT_STRING, 7),
+	/* subjectUID is deprecated in version 2 */
+	ASN1_IMP_OPT(CRMF_CERTTEMPLATE, subjectUID, ASN1_BIT_STRING, 8),
+	ASN1_IMP_SEQUENCE_OF_OPT(CRMF_CERTTEMPLATE, extensions, X509_EXTENSION, 9),
+} ASN1_SEQUENCE_END(CRMF_CERTTEMPLATE)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_CERTTEMPLATE)
+
+
+ASN1_SEQUENCE(CRMF_CERTREQUEST) = {
+	ASN1_SIMPLE(CRMF_CERTREQUEST, certReqId, ASN1_INTEGER),
+	ASN1_SIMPLE(CRMF_CERTREQUEST, certTemplate, CRMF_CERTTEMPLATE),
+	ASN1_SEQUENCE_OF_OPT(CRMF_CERTREQUEST, controls, CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(CRMF_CERTREQUEST)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_CERTREQUEST)
+IMPLEMENT_ASN1_DUP_FUNCTION(CRMF_CERTREQUEST)
+
+
+ASN1_SEQUENCE(CRMF_CERTREQMSG) = {
+	ASN1_SIMPLE(CRMF_CERTREQMSG, certReq, CRMF_CERTREQUEST),
+	ASN1_OPT(CRMF_CERTREQMSG, popo, CRMF_PROOFOFPOSSESION),
+	ASN1_SEQUENCE_OF_OPT(CRMF_CERTREQMSG, regInfo, CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(CRMF_CERTREQMSG)
+IMPLEMENT_ASN1_FUNCTIONS(CRMF_CERTREQMSG)
+
+
+ASN1_ITEM_TEMPLATE(CRMF_CERTREQMESSAGES) =
+	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRMF_CERTREQMESSAGES, CRMF_CERTREQMSG)
+ASN1_ITEM_TEMPLATE_END(CRMF_CERTREQMESSAGES)
+
Index: openssl-1.0.1h-cmp/crypto/crmf/crmf_err.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/crmf_err.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/crmf_err.c	(revision 764)
@@ -0,0 +1,142 @@
+/* crypto/crmf/crmf_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2011 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at 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 <openssl/crmf.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_CRMF,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_CRMF,0,reason)
+
+static ERR_STRING_DATA CRMF_str_functs[]=
+	{
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_CALC_AND_SET_POPO),	"CRMF_CERTREQMSG_calc_and_set_popo"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_PUSH0_CONTROL),	"CRMF_CERTREQMSG_push0_control"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_PUSH0_EXTENSION),	"CRMF_CERTREQMSG_push0_extension"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_PUSH0_REGINFO),	"CRMF_CERTREQMSG_push0_regInfo"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_AUTHENTICATOR),	"CRMF_CERTREQMSG_set1_control_authenticator"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_OLDCERTID),	"CRMF_CERTREQMSG_set1_control_oldCertId"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PKIARCHIVEOPTIONS),	"CRMF_CERTREQMSG_SET1_CONTROL_PKIARCHIVEOPTIONS"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PKIPUBLICATIONINFO),	"CRMF_CERTREQMSG_SET1_CONTROL_PKIPUBLICATIONINFO"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PROTOCOLENCRKEY),	"CRMF_CERTREQMSG_SET1_CONTROL_PROTOCOLENCRKEY"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_REGTOKEN),	"CRMF_CERTREQMSG_set1_control_regToken"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_PUBLICKEY),	"CRMF_CERTREQMSG_set1_publicKey"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_CERTREQ),	"CRMF_CERTREQMSG_SET1_REGINFO_CERTREQ"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_REGTOKEN),	"CRMF_CERTREQMSG_set1_regInfo_regToken"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_UTF8PAIRS),	"CRMF_CERTREQMSG_SET1_REGINFO_UTF8PAIRS"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET1_SUBJECT),	"CRMF_CERTREQMSG_set1_subject"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET_CERTREQID),	"CRMF_CERTREQMSG_set_certReqId"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET_VALIDITY),	"CRMF_CERTREQMSG_set_validity"},
+{ERR_FUNC(CRMF_F_CRMF_CERTREQMSG_SET_VERSION2),	"CRMF_CERTREQMSG_set_version2"},
+{ERR_FUNC(CRMF_F_CRMF_CR_NEW),	"CRMF_cr_new"},
+{ERR_FUNC(CRMF_F_CRMF_PASSWORDBASEDMAC_NEW),	"CRMF_passwordBasedMac_new"},
+{ERR_FUNC(CRMF_F_CRMF_POPOSIGNINGKEY_NEW),	"CRMF_poposigningkey_new"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_CONTROL_AUTHENTICATOR),	"CRMF_SET1_CONTROL_AUTHENTICATOR"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_CONTROL_OLDCERTID),	"CRMF_SET1_CONTROL_OLDCERTID"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_CONTROL_PKIARCHIVEOPTIONS),	"CRMF_SET1_CONTROL_PKIARCHIVEOPTIONS"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_CONTROL_PKIPUBLICATIONINFO),	"CRMF_SET1_CONTROL_PKIPUBLICATIONINFO"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_CONTROL_PROTOCOLENCRKEY),	"CRMF_SET1_CONTROL_PROTOCOLENCRKEY"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_REGINFO_CERTREQ),	"CRMF_SET1_REGINFO_CERTREQ"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_REGINFO_UTF8PAIRS),	"CRMF_SET1_REGINFO_UTF8PAIRS"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_REGTOKEN_CERTREQ),	"CRMF_SET1_REGTOKEN_CERTREQ"},
+{ERR_FUNC(CRMF_F_CRMF_SET1_SUBJECT),	"CRMF_SET1_SUBJECT"},
+{ERR_FUNC(CRMF_F_CRMF_SET_CERTREQID),	"CRMF_SET_CERTREQID"},
+{ERR_FUNC(CRMF_F_CRMF_SET_VERSION2),	"CRMF_SET_VERSION2"},
+{0,NULL}
+	};
+
+static ERR_STRING_DATA CRMF_str_reasons[]=
+	{
+{ERR_REASON(CRMF_R_CRMFERROR)            ,"crmferror"},
+{ERR_REASON(CRMF_R_ERROR_CALCULATING_AND_SETTING_POPO),"error calculating and setting popo"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_CONTROL_AUTHENTICATOR_ATAV),"error setting control authenticator atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_CONTROL_OLDCERTID_ATAV),"error setting control oldcertid atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_CONTROL_PKIARCHIVEOPTIONS_ATAV),"error setting control pkiarchiveoptions atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_CONTROL_PKIPUBLICATIONINFO_ATAV),"error setting control pkipublicationinfo atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_CONTROL_PROTOCOLENCRKEY_ATAV),"error setting control protocolencrkey atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_POPSIGNINGKEY),"error setting popsigningkey"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_PUBLIC_KEY),"error setting public key"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_REGINFO_CERTREQ_ATAV),"error setting reginfo certreq atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_REGINFO_UTF8PAIRS_ATAV),"error setting reginfo utf8pairs atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_REGTOKEN_ATAV),"error setting regtoken atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_REGTOKEN_CERTREQ_ATAV),"error setting regtoken certreq atav"},
+{ERR_REASON(CRMF_R_ERROR_SETTING_VERSION_2),"error setting version 2"},
+{ERR_REASON(CRMF_R_UNSUPPORTED_ALGORITHM),"unsupported algorithm"},
+{ERR_REASON(CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY),"unsupported alg for popsigningkey"},
+{ERR_REASON(CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO),"unsupported method for creating popo"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_CRMF_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(CRMF_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,CRMF_str_functs);
+		ERR_load_strings(0,CRMF_str_reasons);
+		}
+#endif
+	}
Index: openssl-1.0.1h-cmp/crypto/crmf/crmf_lib.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/crmf_lib.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/crmf_lib.c	(revision 764)
@@ -0,0 +1,699 @@
+/* vim: set cino={1s noet ts=4 sts=4 sw=4: */
+/* crypto/crmf/crmf_lib.c
+ * CRMF (RFC 4211) library functions for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+/* NAMING
+ * The 0 version uses the supplied structure pointer directly in the parent and 
+ * it will be freed up when the parent is freed. In the above example crl would 
+ * be freed but rev would not.
+ *
+ * The 1 function uses a copy of the supplied structure pointer (or in some 
+ * cases increases its link count) in the parent and so both (x and obj above) 
+ * should be freed up. 
+ */
+/* ############################################################################ *
+ * In this file are the functions which set the individual items inside			*
+ * the CRMF structures															*
+ * ############################################################################ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+/* ############################################################################ *
+ * Pushes the given control attribute into the controls stack of a CertRequest
+ * (section 6)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_push0_control( CRMF_CERTREQMSG *certReqMsg, CRMF_ATTRIBUTETYPEANDVALUE *control)
+	{
+	int newControls = 0;
+
+	if (!certReqMsg) goto err;
+	if (!control) goto err;
+
+	if (!(certReqMsg->certReq->controls))
+		{
+		/* as it is OPTIONAL it might not yet be initialized */
+		if( !(certReqMsg->certReq->controls = sk_CRMF_ATTRIBUTETYPEANDVALUE_new_null())) goto err;
+		newControls = 1; /* for potential cleanup in error case */
+		}
+	if (!sk_CRMF_ATTRIBUTETYPEANDVALUE_push( certReqMsg->certReq->controls, control)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_PUSH0_CONTROL, CRMF_R_CRMFERROR);
+
+	if (newControls)
+		{
+		sk_CRMF_ATTRIBUTETYPEANDVALUE_pop_free(certReqMsg->certReq->controls, CRMF_ATTRIBUTETYPEANDVALUE_free);
+		certReqMsg->certReq->controls = NULL;
+		}
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets the id-regCtrl-regToken Control (section 6.1)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_control_regToken( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *tok)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!tok) goto err;
+	
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_regToken);
+	if (!(atav->value.regToken = ASN1_STRING_dup( tok))) goto err;
+
+	if (!CRMF_CERTREQMSG_push0_control( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_REGTOKEN, CRMF_R_ERROR_SETTING_REGTOKEN_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets the id-regCtrl-authenticator Control (section 6.2)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_control_authenticator( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *auth)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!auth) goto err;
+	
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_authenticator);
+	if (!(atav->value.regToken = ASN1_STRING_dup( auth))) goto err;
+	if( !CRMF_CERTREQMSG_push0_control( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_AUTHENTICATOR, CRMF_R_ERROR_SETTING_CONTROL_AUTHENTICATOR_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets the id-regCtrl-pkiPublicationInfo Control (section 6.3)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_control_pkiPublicationInfo( CRMF_CERTREQMSG *msg, CRMF_PKIPUBLICATIONINFO *pubinfo)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!pubinfo) goto err;
+
+	
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_pkiPublicationInfo);
+	if (!(atav->value.pkiPublicationInfo = CRMF_PKIPUBLICATIONINFO_dup( pubinfo))) goto err;
+	if( !CRMF_CERTREQMSG_push0_control( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PKIPUBLICATIONINFO, CRMF_R_ERROR_SETTING_CONTROL_PKIPUBLICATIONINFO_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################
+ * sets the id-regCtrl-pkiArchiveOptions Control (section 6.4)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_control_pkiArchiveOptions( CRMF_CERTREQMSG *msg, CRMF_PKIARCHIVEOPTIONS *archopts)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!archopts) goto err;
+	
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_pkiArchiveOptions);
+	if (!(atav->value.pkiArchiveOptions = CRMF_PKIARCHIVEOPTIONS_dup( archopts))) goto err;
+	if( !CRMF_CERTREQMSG_push0_control( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PKIARCHIVEOPTIONS, CRMF_R_ERROR_SETTING_CONTROL_PKIARCHIVEOPTIONS_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets the id-regCtrl-oldCertID Control (section 6.5) from the given
+ * certificate
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_control_oldCertId( CRMF_CERTREQMSG *certReqMsg, X509 *oldCert)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav   = NULL;
+	CRMF_CERTID				   *certId = NULL;
+	GENERAL_NAME			   *gName  = NULL;
+
+	if ( !certReqMsg) goto err;
+	if ( !oldCert) goto err;
+
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())
+		|| !(certId = CRMF_CERTID_new())
+		|| !(gName = GENERAL_NAME_new()))
+		goto err;
+
+	/* X509_NAME_set does not consume the pointer so this is ok */
+	X509_NAME_set( &gName->d.directoryName, X509_get_issuer_name( oldCert));
+	gName->type = GEN_DIRNAME;
+	certId->issuer = gName;
+	if (!(certId->serialNumber = ASN1_INTEGER_dup(X509_get_serialNumber(oldCert)))) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_oldCertID);
+	atav->value.oldCertId = certId;
+
+	if (!CRMF_CERTREQMSG_push0_control( certReqMsg, atav)) goto err;
+
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_OLDCERTID, CRMF_R_ERROR_SETTING_CONTROL_OLDCERTID_ATAV);
+	if (gName) GENERAL_NAME_free(gName);
+	if (certId)
+		{
+		certId->issuer = NULL;
+		CRMF_CERTID_free(certId);
+		}
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * For some reason X509_PUBKEY_dup() does not appear to be implemented by 
+ * OpenSSL's X509 code, so we implement it here. It's only needed in the following
+ * function so it can be declared static. *
+ * TODO: check whether that should go elsewhere *
+ * ############################################################################ */
+static IMPLEMENT_ASN1_DUP_FUNCTION(X509_PUBKEY);
+
+/* ############################################################################ *
+ * sets the id-regCtrl-protocolEncrKey Control (section 6.6) from the given
+ * public key
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_control_protocolEncrKey( CRMF_CERTREQMSG *msg, X509_PUBKEY *pubkey)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!pubkey) goto err;
+
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_protocolEncrKey);
+	if (!(atav->value.protocolEncrKey = X509_PUBKEY_dup(pubkey))) goto err;
+	if( !CRMF_CERTREQMSG_push0_control( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_CONTROL_PROTOCOLENCRKEY, CRMF_R_ERROR_SETTING_CONTROL_PROTOCOLENCRKEY_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * Pushes the attribute given in regInfo in to the CertReqMsg->regInfo stack.
+ * (section 7)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_push0_regInfo( CRMF_CERTREQMSG *certReqMsg, CRMF_ATTRIBUTETYPEANDVALUE *regInfo)
+	{
+	int newRegInfo = 0;
+
+	if (!certReqMsg) goto err;
+	if (!regInfo) goto err;
+
+	if (!(certReqMsg->regInfo))
+		{
+		/* as it is OPTIONAL it might not yet be initialized */
+		if( !(certReqMsg->regInfo = sk_CRMF_ATTRIBUTETYPEANDVALUE_new_null())) goto err;
+		newRegInfo = 1;
+		}
+	if (!sk_CRMF_ATTRIBUTETYPEANDVALUE_push( certReqMsg->regInfo, regInfo)) goto err;
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_PUSH0_REGINFO, CRMF_R_CRMFERROR);
+
+	if (newRegInfo)
+		{
+		sk_CRMF_ATTRIBUTETYPEANDVALUE_pop_free(certReqMsg->regInfo, CRMF_ATTRIBUTETYPEANDVALUE_free);
+		certReqMsg->regInfo = NULL;
+		}
+	return 0;
+}
+	
+/* ############################################################################ *
+ * sets the id-regInfo-utf8Pairs to regInfo (section 7.1) from a given
+ * UTF8string
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_regInfo_utf8Pairs( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *utf8pairs)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!utf8pairs) goto err;
+	
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regInfo_utf8Pairs);
+	if (!(atav->value.utf8pairs = ASN1_STRING_dup( utf8pairs))) goto err;
+
+	if (!CRMF_CERTREQMSG_push0_regInfo( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_UTF8PAIRS, CRMF_R_ERROR_SETTING_REGINFO_UTF8PAIRS_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets the id-regInfo-certReq to regInfo (section 7.2) from a given certificate
+ * request
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_regInfo_certReq( CRMF_CERTREQMSG *msg, CRMF_CERTREQUEST *certReq)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!certReq) goto err;
+
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regInfo_certReq);
+	if (!(atav->value.certReq = CRMF_CERTREQUEST_dup( certReq))) goto err;
+
+	if (!CRMF_CERTREQMSG_push0_regInfo( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_CERTREQ, CRMF_R_ERROR_SETTING_REGINFO_CERTREQ_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets the id-regCtrl-regToken to regInfo (not described in RFC)
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_regInfo_regToken( CRMF_CERTREQMSG *msg, ASN1_UTF8STRING *tok)
+	{
+	CRMF_ATTRIBUTETYPEANDVALUE *atav=NULL;
+
+	if (!msg) goto err;
+	if (!tok) goto err;
+	
+	if (!(atav = CRMF_ATTRIBUTETYPEANDVALUE_new())) goto err;
+
+	atav->type = OBJ_nid2obj(NID_id_regCtrl_regToken);
+	if (!(atav->value.regToken = ASN1_STRING_dup( tok))) goto err;
+
+	if (!CRMF_CERTREQMSG_push0_regInfo( msg, atav)) goto err;
+	
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_REGINFO_REGTOKEN, CRMF_R_ERROR_SETTING_REGTOKEN_CERTREQ_ATAV);
+	if (atav) CRMF_ATTRIBUTETYPEANDVALUE_free( atav);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets version to 2 in cert Template (section 5)
+ *	 version MUST be 2 if supplied.  It SHOULD be omitted.
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set_version2( CRMF_CERTREQMSG *certReqMsg)
+	{
+	if (! certReqMsg) goto err;
+
+	if (! certReqMsg->certReq->certTemplate->version)
+		/* as it is OPTIONAL it might not yet be initialized */
+		certReqMsg->certReq->certTemplate->version = ASN1_INTEGER_new();
+	ASN1_INTEGER_set( certReqMsg->certReq->certTemplate->version, 2L);
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET_VERSION2, CRMF_R_ERROR_SETTING_VERSION_2);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * sets notBefore and/or notAfter in certTemplate of the given certreqmsg
+ * (section 5) - if they are not given as 0
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set_validity( CRMF_CERTREQMSG *certReqMsg, time_t notBefore, time_t notAfter)
+	{
+	CRMF_OPTIONALVALIDITY *validity=NULL;
+	ASN1_TIME *notBeforeAsn=NULL;
+	ASN1_TIME *notAfterAsn=NULL;
+
+	if (! certReqMsg) goto err;
+
+	if (notBefore)
+		{
+		if( !(notBeforeAsn = ASN1_TIME_set(NULL, notBefore))) goto err;
+		}
+	if (notAfter)
+		{
+		if( !(notAfterAsn = ASN1_TIME_set(NULL, notAfter))) goto err;
+		}
+	if (!(validity = CRMF_OPTIONALVALIDITY_new())) goto err;
+
+	validity->notBefore = notBeforeAsn;
+	validity->notAfter	= notAfterAsn;
+
+	certReqMsg->certReq->certTemplate->validity = validity;
+
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET_VALIDITY, CRMF_R_CRMFERROR);
+	if (notBeforeAsn) ASN1_TIME_free(notBeforeAsn);
+	if (notAfterAsn) ASN1_TIME_free(notAfterAsn);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * set the certReqId (section 5)
+ *	  certReqId contains an integer value that is used by the
+ *	  certificate requestor to associate a specific certificate request
+ *	  with a certificate response.
+ * returns 0 on error, 1 on success
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set_certReqId( CRMF_CERTREQMSG *certReqMsg, const long certReqId)
+	{
+	if (! certReqMsg) goto err;
+	if (! certReqMsg->certReq) goto err;
+
+	return ASN1_INTEGER_set(certReqMsg->certReq->certReqId, certReqId);
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET_CERTREQID, CRMF_R_CRMFERROR);
+	return 0;
+	}
+
+/* ############################################################################ *
+ * set the public Key to the certTemplate (chapgter 5)
+ *	  publicKey contains the public key for which the certificate is
+ *	  being created.  This field MUST be filled in if the requestor
+ *	  generates its own key.  The field is omitted if the key is
+ *	  generated by the RA/CA.
+ * returns 0 on error, 1 on success
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_publicKey( CRMF_CERTREQMSG *certReqMsg, const EVP_PKEY *pkey) {
+	if (! certReqMsg) goto err;
+	if (! pkey) goto err;
+
+	/* this function is not consuming the pointer */
+	return X509_PUBKEY_set(&(certReqMsg->certReq->certTemplate->publicKey), (EVP_PKEY*) pkey);
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_PUBLICKEY, CRMF_R_CRMFERROR);
+	return 0;
+}
+
+/* ############################################################################ *
+ * Set the subject name in the given certificate template (section 5)
+ *	  subject is filled in with the suggested name for the requestor.
+ *	  This would normally be filled in by a name that has been
+ *	  previously issued to the requestor by the CA.
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_set1_subject( CRMF_CERTREQMSG *certReqMsg, const X509_NAME *subject) {
+	if (! certReqMsg) goto err;
+	if (! subject) goto err;
+
+	/* this function is *not* consuming the pointer */
+	return X509_NAME_set(&(certReqMsg->certReq->certTemplate->subject), (X509_NAME*) subject);
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_SET1_SUBJECT, CRMF_R_CRMFERROR);
+	return 0;
+}
+
+/* ############################################################################ *
+ * push an extension to the extension stack (section 5)
+ *	  extensions contains extensions that the requestor wants to have
+ *	  placed in the certificate.  These extensions would generally deal
+ *	  with things such as setting the key usage to keyEncipherment.
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_push0_extension( CRMF_CERTREQMSG *certReqMsg, X509_EXTENSION *ext) {
+	int createdStack = 0;
+
+	if (! certReqMsg) goto err;
+	if (! ext) goto err;
+
+	if (! certReqMsg->certReq->certTemplate->extensions)
+		{
+		if( !(certReqMsg->certReq->certTemplate->extensions = sk_X509_EXTENSION_new_null())) goto err;
+		createdStack = 1;
+		}
+
+	if( !sk_X509_EXTENSION_push(certReqMsg->certReq->certTemplate->extensions, ext)) goto err;
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_PUSH0_EXTENSION, CRMF_R_CRMFERROR);
+
+	if (createdStack)
+		{
+		sk_X509_EXTENSION_pop_free( certReqMsg->certReq->certTemplate->extensions, X509_EXTENSION_free);
+		certReqMsg->certReq->certTemplate->extensions = NULL;
+		}
+	return 0;
+}
+
+/* ############################################################################ *
+ * Create proof-of-posession information by signing the certrequest with our 
+ * private key (section 4.1). Algorithm according to key type.
+ * Aas default, for RSA+DSA SHA-1, is used for generating the input.
+ *
+ * TODO:
+ * This function does not yet work for cases other than the one listed in case 3
+ * of section 4.1.	For this it needs to put subject name and public key into
+ * the POPOSigningKey:
+ *
+   3.  The certificate subject places its name in the Certificate
+	   Template structure along with the public key.  In this case the
+	   poposkInput field is omitted from the POPOSigningKey structure.
+	   The signature field is computed over the DER-encoded certificate
+	   template structure.
+ *
+ * TODO: only RSA/DSA keys are supported so far
+ *
+ * returns a pointer to the created CRMF_POPOSIGNINGKEY on success, NULL on
+ * error
+ * ############################################################################ */
+CRMF_POPOSIGNINGKEY * CRMF_poposigningkey_new( CRMF_CERTREQUEST *certReq, const EVP_PKEY *pkey)
+	{
+	CRMF_POPOSIGNINGKEY *poposig=NULL;
+	size_t certReqSize, maxSignatureSize;
+	unsigned int sigLen;
+	unsigned char *certReqDer=NULL;
+	unsigned char *signature=NULL;
+	const EVP_MD *alg=NULL;
+
+	EVP_MD_CTX *ctx=NULL;
+
+	/* NOTE: PoposkInput is not handled here. */
+	if( !(poposig = CRMF_POPOSIGNINGKEY_new())) goto err;
+	/* get DER representation */
+	certReqSize = i2d_CRMF_CERTREQUEST( certReq, &certReqDer);
+
+	maxSignatureSize = EVP_PKEY_size( (EVP_PKEY*) pkey);
+	signature = OPENSSL_malloc(maxSignatureSize);
+
+	/* set the type of the algorithm */
+	switch (EVP_PKEY_type(pkey->type))
+		{
+#ifndef OPENSSL_NO_DSA
+		case EVP_PKEY_DSA:
+			X509_ALGOR_set0(poposig->algorithmIdentifier, OBJ_nid2obj(NID_dsaWithSHA1), V_ASN1_NULL, NULL);
+			alg = EVP_dss1();
+			break;
+#endif
+#ifndef OPENSSL_NO_RSA
+		case EVP_PKEY_RSA:
+			X509_ALGOR_set0(poposig->algorithmIdentifier, OBJ_nid2obj(NID_sha1WithRSAEncryption), V_ASN1_NULL, NULL);
+			alg = EVP_sha1();
+			break;
+#endif
+		default:
+			CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_NEW, CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY);
+			goto err;
+		}
+
+	ctx=EVP_MD_CTX_create();
+	if (!(EVP_SignInit_ex(ctx, alg, NULL))) goto err;
+	if (!(EVP_SignUpdate(ctx, certReqDer, certReqSize))) goto err;
+	if (!(EVP_SignFinal(ctx, signature, &sigLen, (EVP_PKEY*) pkey))) goto err;
+
+	/* set the signature value */
+	if (!(ASN1_BIT_STRING_set( poposig->signature, signature, sigLen))) goto err;
+
+	/* Actually this should not be needed but OpenSSL defaults all bitstrings to be a NamedBitList */
+	poposig->signature->flags &= ~0x07;
+	poposig->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+	/* cleanup */
+	OPENSSL_free(certReqDer);
+	EVP_MD_CTX_destroy(ctx);
+	OPENSSL_free(signature);
+	return poposig;
+err:
+	CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_NEW, CRMF_R_ERROR_SETTING_POPSIGNINGKEY);
+	if( poposig) CRMF_POPOSIGNINGKEY_free( poposig);
+	if( certReqDer) OPENSSL_free(certReqDer);
+	if( ctx) EVP_MD_CTX_destroy(ctx);
+	if( signature) OPENSSL_free(signature);
+	return NULL;
+	}
+
+/* ############################################################################ *
+ * calculate and set the proof of possession based on the popoMethod (define in cmp.h)
+ * the following types are supported so far (#defines in crfm.h):
+ *	 CRMF_POPO_NONE: ProofOfPossession field omitted, CA/RA uses out-of-band method to verify POP (compare RFC 4211, section 4).
+ *	 CRMF_POPO_SIGNATURE: according to section 4.1 (only case 3 supported so far)
+ *	 CRMF_POPO_ENCRCERT:  according to section 4.2 with the indirect method
+ *	 (subsequentMessage/enccert)
+ *
+	  subsequentMessage is used to indicate that the POP will be
+	  completed by decrypting a message from the CA/RA and returning a
+	  response.  The type of message to be decrypted is indicated by the
+	  value used.
+
+		 encrCert indicates that the certificate issued is to be
+		 returned in an encrypted form.  The requestor is required to
+		 decrypt the certificate and prove success to the CA/RA.  The
+		 details of this are provided by the CRP.
+ * returns 1 on success, 0 on error
+ * ############################################################################ */
+int CRMF_CERTREQMSG_calc_and_set_popo( CRMF_CERTREQMSG *certReqMsg, const EVP_PKEY *pkey, int popoMethod)
+	{
+	CRMF_PROOFOFPOSSESION *newPopo=NULL;
+
+	if (popoMethod == CRMF_POPO_NONE) return 1;  /* nothing to be done */
+
+	if (! certReqMsg) goto err;
+	if (! pkey) goto err;
+
+	if( !(newPopo = CRMF_PROOFOFPOSSESION_new())) goto err;
+
+	switch (popoMethod)
+		{
+		case CRMF_POPO_RAVERIFIED:
+			newPopo->type = CRMF_PROOFOFPOSESSION_RAVERIFIED;
+			newPopo->value.raVerified = ASN1_NULL_new();
+			break;
+
+		case CRMF_POPO_SIGNATURE:
+			if( !(newPopo->value.signature = CRMF_poposigningkey_new( certReqMsg->certReq, pkey))) goto err;
+			newPopo->type = CRMF_PROOFOFPOSESSION_SIGNATURE;
+			break;
+
+		case CRMF_POPO_ENCRCERT:
+			newPopo->type = CRMF_PROOFOFPOSESSION_KEYENCIPHERMENT;
+			newPopo->value.keyEncipherment = CRMF_POPOPRIVKEY_new();
+
+			newPopo->value.keyEncipherment->type = CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE;
+			
+			newPopo->value.keyEncipherment->value.subsequentMessage = ASN1_INTEGER_new();
+			ASN1_INTEGER_set(newPopo->value.keyEncipherment->value.subsequentMessage, CRMF_SUBSEQUENTMESSAGE_ENCRCERT);
+			break;
+
+		default: 
+			CRMFerr(CRMF_F_CRMF_CERTREQMSG_CALC_AND_SET_POPO, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO);
+			goto err;
+		}
+
+	if(certReqMsg->popo) 
+		/* OPTIONAL but initialized before */
+		CRMF_PROOFOFPOSSESION_free(certReqMsg->popo);
+	certReqMsg->popo = newPopo;
+
+	return 1;
+err:
+	CRMFerr(CRMF_F_CRMF_CERTREQMSG_CALC_AND_SET_POPO, CRMF_R_ERROR_CALCULATING_AND_SETTING_POPO);
+	if( newPopo) CRMF_PROOFOFPOSSESION_free( newPopo);
+	return 0;
+	}
+
Index: openssl-1.0.1h-cmp/crypto/crmf/crmf_msg.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/crmf_msg.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/crmf_msg.c	(revision 764)
@@ -0,0 +1,122 @@
+/* vim: set cino={1s noet ts=4 sts=4 sw=4: */
+/* crypto/crmf/crmf_msg.c
+ * Functions for creating CRMF (RFC 4211) messages for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+/* ############################################################################ */
+/* In this file are the functions which build and evaluate the CRMF messages	*/
+/* ############################################################################ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <string.h>
+
+/* ############################################################################ * 
+ * creates a new CRMF certifcate request message
+ * TODO there are some optional settings which are not cared for yet
+ * TODO maybe create a crmf_ctx?
+ * ############################################################################ */
+CRMF_CERTREQMSG * CRMF_cr_new( const long certReqId, 
+							   const EVP_PKEY *pkey, 
+							   const X509_NAME *subject, 
+							   X509_EXTENSIONS *extensions)
+	{
+	CRMF_CERTREQMSG *certReqMsg;
+	int i;
+
+	if( !(certReqMsg = CRMF_CERTREQMSG_new())) goto err;
+
+#if 0
+	/* version MUST be 2 if supplied.  It SHOULD be omitted. */
+	CRMF_CERTREQMSG_set_version2( certReqMsg);
+#endif
+
+	CRMF_CERTREQMSG_set_certReqId( certReqMsg, certReqId);
+	if (!CRMF_CERTREQMSG_set1_publicKey( certReqMsg, pkey))
+		{
+		CRMFerr(CRMF_F_CRMF_CR_NEW, CRMF_R_ERROR_SETTING_PUBLIC_KEY);
+		goto err;
+		}
+
+	CRMF_CERTREQMSG_set1_subject( certReqMsg, subject);
+
+	/* validity time could be set here */
+
+	for (i = 0; i < sk_X509_EXTENSION_num(extensions); i++)
+		/* X509v3_add_ext will allocate new stack if there isn't one already */
+		X509v3_add_ext(&certReqMsg->certReq->certTemplate->extensions, sk_X509_EXTENSION_value(extensions, i), i);
+	
+	return certReqMsg;
+err:
+	CRMFerr(CRMF_F_CRMF_CR_NEW, CRMF_R_CRMFERROR);
+	if( certReqMsg)
+		CRMF_CERTREQMSG_free( certReqMsg);
+	return NULL;
+	}
+
Index: openssl-1.0.1h-cmp/crypto/crmf/crmf_pbm.c
===================================================================
--- openssl-1.0.1h-cmp/crypto/crmf/crmf_pbm.c	(revision 0)
+++ openssl-1.0.1h-cmp/crypto/crmf/crmf_pbm.c	(revision 764)
@@ -0,0 +1,222 @@
+/* vim: set cino={1s noet ts=4 sts=4 sw=4: */
+/* crypto/crmf/crmf_pbm.c
+ * CRMF (RFC 4211) "Password Based Mac" functions for OpenSSL
+ */
+/* ====================================================================
+ * Originally written by Martin Peylo for the OpenSSL project.
+ * <martin dot peylo at nsn dot com>
+ * 2010-2012 Miikka Viljanen <mviljane at users.sourceforge.net>
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2007-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/crmf.h>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/err.h>
+
+#define SALT_LEN		 16
+#define ITERATION_COUNT 500
+
+/* ############################################################################ *
+ * creates and initializes CRMF_PBMPARAMETER (section 4.4)
+ * returns pointer to CRMF_PBMPARAMETER on success, NULL on error
+ * TODO: this should take the parameters to be set via the arguments
+ * ############################################################################ */
+CRMF_PBMPARAMETER * CRMF_pbm_new(void)
+	{
+	CRMF_PBMPARAMETER *pbm=NULL;
+	unsigned char salt[SALT_LEN];
+
+	if(!(pbm = CRMF_PBMPARAMETER_new())) goto err;
+
+	/* salt contains a randomly generated value used in computing the key
+	 * of the MAC process.	The salt SHOULD be at least 8 octets (64
+	 * bits) long.
+	 */
+	RAND_pseudo_bytes(salt, SALT_LEN);
+	if (!(ASN1_OCTET_STRING_set(pbm->salt, salt, SALT_LEN))) goto err;
+
+	/* owf identifies the algorithm and associated parameters used to
+	 * compute the key used in the MAC process.  All implementations MUST
+	 * support SHA-1.
+	 */
+	/* TODO right now SHA-1 is hardcoded */
+	X509_ALGOR_set0(pbm->owf, OBJ_nid2obj(NID_sha1), V_ASN1_UNDEF, NULL);
+
+	/*
+	   iterationCount identifies the number of times the hash is applied
+	   during the key computation process.	The iterationCount MUST be a
+	   minimum of 100.	Many people suggest using values as high as 1000
+	   iterations as the minimum value.  The trade off here is between
+	   protection of the password from attacks and the time spent by the
+	   server processing all of the different iterations in deriving
+	   passwords.  Hashing is generally considered a cheap operation but
+	   this may not be true with all hash functions in the future.
+	   */
+	ASN1_INTEGER_set(pbm->iterationCount, ITERATION_COUNT);
+
+	/* mac identifies the algorithm and associated parameters of the MAC
+	   function to be used.  All implementations MUST support HMAC-SHA1
+	   [HMAC].	All implementations SHOULD support DES-MAC and Triple-
+	   DES-MAC [PKCS11].
+	   */
+	/* TODO right now HMAC-SHA1 is hardcoded */
+	/* X509_ALGOR_set0(mac, OBJ_nid2obj(NID_id_alg_dh_sig_hmac_sha1), V_ASN1_UNDEF, NULL); */
+	X509_ALGOR_set0(pbm->mac, OBJ_nid2obj(NID_hmac_sha1), V_ASN1_UNDEF, NULL);
+
+	return pbm;
+err:
+	if(pbm) CRMF_PBMPARAMETER_free(pbm);
+	return NULL;
+	}
+
+
+/* ############################################################################
+ * this function calculates the PBM based on the settings of the given CRMF_PBMPARAMENTER
+ * @pbm identifies the algorithms to use
+ * @msg message to apply the PBM for
+ * @msgLen length of the message
+ * @secret key to use
+ * @secretLen length of the key
+ * @mac pointer to the computed mac, is allocated here, will be freed if not
+ *		pointing to NULL
+ * @macLen pointer to the length of the mac, will be set
+ *
+ * returns 1 at success, 0 at error
+ * ############################################################################ */
+int CRMF_passwordBasedMac_new( const CRMF_PBMPARAMETER *pbm,
+			   const unsigned char* msg, size_t msgLen, 
+			   const unsigned char* secret, size_t secretLen,
+			   unsigned char** mac, unsigned int* macLen
+			   )
+	{
+	const EVP_MD *m=NULL;
+	EVP_MD_CTX *ctx=NULL;
+	unsigned char basekey[EVP_MAX_MD_SIZE];
+	unsigned int basekeyLen;
+	long iterations;
+
+	if (!mac) goto err;
+	if( *mac) OPENSSL_free(*mac);
+
+	if (!pbm) goto err;
+	if (!msg) goto err;
+	if (!secret) goto err;
+
+	*mac = OPENSSL_malloc(EVP_MAX_MD_SIZE);
+
+	OpenSSL_add_all_digests();
+
+	/*
+	 * owf identifies the algorithm and associated parameters used to
+	 * compute the key used in the MAC process.  All implementations MUST
+	 * support SHA-1.
+	 */
+	if (!(m = EVP_get_digestbyobj(pbm->owf->algorithm))) goto err;
+
+	ctx=EVP_MD_CTX_create();
+
+	/* compute the basekey of the salted secret */
+	if (!(EVP_DigestInit_ex(ctx, m, NULL))) goto err;
+	/* first the secret */
+	EVP_DigestUpdate(ctx, secret, secretLen);
+	/* then the salt */
+	EVP_DigestUpdate(ctx, pbm->salt->data, pbm->salt->length);
+	if (!(EVP_DigestFinal_ex(ctx, basekey, &basekeyLen))) goto err;
+
+	/* the first iteration is already done above -> -1 */
+	iterations = ASN1_INTEGER_get(pbm->iterationCount)-1;
+	while( iterations--)
+		{
+		if (!(EVP_DigestInit_ex(ctx, m, NULL))) goto err;
+		EVP_DigestUpdate(ctx, basekey, basekeyLen);
+		if (!(EVP_DigestFinal_ex(ctx, basekey, &basekeyLen))) goto err;
+		}
+
+	/*
+	 * mac identifies the algorithm and associated parameters of the MAC
+	 * function to be used.  All implementations MUST support HMAC-SHA1
+	 * [HMAC].	All implementations SHOULD support DES-MAC and Triple-
+	 * DES-MAC [PKCS11].
+	 */
+	switch (OBJ_obj2nid(pbm->mac->algorithm))
+		{
+		case NID_hmac_sha1:
+			HMAC(EVP_sha1(), basekey, basekeyLen, msg, msgLen, *mac, macLen);
+			break;
+			/* optional TODO: DES-MAC, Triple DES-MAC */
+			/* which NIDs to use for these algorithms??? */
+		default:
+			CRMFerr(CRMF_F_CRMF_PASSWORDBASEDMAC_NEW, CRMF_R_UNSUPPORTED_ALGORITHM);
+			goto err;
+		}
+
+	/* cleanup */
+	EVP_MD_CTX_destroy(ctx);
+
+	return 1;
+err:
+	if( mac && *mac) OPENSSL_free(*mac);
+	CRMFerr(CRMF_F_CRMF_PASSWORDBASEDMAC_NEW, CRMF_R_CRMFERROR);
+	return 0;
+	}
Index: openssl-1.0.1h-cmp/apps/Makefile
===================================================================
--- openssl-1.0.1h-cmp/apps/Makefile	(revision 750)
+++ openssl-1.0.1h-cmp/apps/Makefile	(working copy)
@@ -39,7 +39,8 @@
 	ca crl rsa rsautl dsa dsaparam ec ecparam \
 	x509 genrsa gendsa genpkey s_server s_client speed \
 	s_time version pkcs7 cms crl2pkcs7 sess_id ciphers nseq pkcs12 \
-	pkcs8 pkey pkeyparam pkeyutl spkac smime rand engine ocsp prime ts srp
+	pkcs8 pkey pkeyparam pkeyutl spkac smime rand engine ocsp prime ts srp \
+	cmp
 
 PROGS= $(PROGRAM).c
 
@@ -56,7 +57,7 @@
 	x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o \
 	s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \
 	ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o \
-	spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o
+	spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o cmp.o
 
 E_SRC=	verify.c asn1pars.c req.c dgst.c dh.c enc.c passwd.c gendh.c errstr.c ca.c \
 	pkcs7.c crl2p7.c crl.c \
@@ -64,7 +65,7 @@
 	x509.c genrsa.c gendsa.c genpkey.c s_server.c s_client.c speed.c \
 	s_time.c $(A_SRC) $(S_SRC) $(RAND_SRC) version.c sess_id.c \
 	ciphers.c nseq.c pkcs12.c pkcs8.c pkey.c pkeyparam.c pkeyutl.c \
-	spkac.c smime.c cms.c rand.c engine.c ocsp.c prime.c ts.c srp.c
+	spkac.c smime.c cms.c rand.c engine.c ocsp.c prime.c ts.c srp.c cmp.c
 
 SRC=$(E_SRC)
 
Index: openssl-1.0.1h-cmp/apps/progs.h
===================================================================
--- openssl-1.0.1h-cmp/apps/progs.h	(revision 750)
+++ openssl-1.0.1h-cmp/apps/progs.h	(working copy)
@@ -47,6 +47,7 @@
 extern int prime_main(int argc,char *argv[]);
 extern int ts_main(int argc,char *argv[]);
 extern int srp_main(int argc,char *argv[]);
+extern int cmp_main(int argc,char *argv[]);
 
 #define FUNC_TYPE_GENERAL	1
 #define FUNC_TYPE_MD		2
@@ -151,6 +152,9 @@
 #ifndef OPENSSL_NO_SRP
 	{FUNC_TYPE_GENERAL,"srp",srp_main},
 #endif
+#ifndef OPENSSL_NO_CMP
+	{FUNC_TYPE_GENERAL,"cmp",cmp_main},
+#endif
 #ifndef OPENSSL_NO_MD2
 	{FUNC_TYPE_MD,"md2",dgst_main},
 #endif
Index: openssl-1.0.1h-cmp/apps/cmp.c
===================================================================
--- openssl-1.0.1h-cmp/apps/cmp.c	(revision 0)
+++ openssl-1.0.1h-cmp/apps/cmp.c	(revision 764)
@@ -0,0 +1,747 @@
+/* vim: set cinoptions={1s: */
+/* apps/cmp.c
+ */
+/* ====================================================================
+ * Written by Miikka Viljanen, based on cmpclient by Martin Peylo
+ */
+/* ====================================================================
+ * Copyright (c) 2007-2010 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ */
+/* ====================================================================
+ * Copyright 2012-2014 Nokia Oy. ALL RIGHTS RESERVED.
+ * CMP support in OpenSSL originally developed by 
+ * Nokia for contribution to the OpenSSL project.
+ */
+
+/* ============================== TODO List ============================== 
+ * TODO: actually send the genm for requesting the CKUANN message
+ */
+
+#include <openssl/opensslconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "apps.h"
+
+#define CONFIG_FILE "openssl.cnf"
+#define CMP_SECTION "cmp"
+#undef PROG
+#define PROG	cmp_main
+
+#include <openssl/cmp.h>
+#include <openssl/crmf.h>
+#include <openssl/pem.h>
+
+static CONF *conf=NULL; /* OpenSSL config file context structure */
+static BIO *bio_c_out=NULL; /* OpenSSL BIO for printing to STDOUT */ 
+
+/* the type of cmp command we want to send */
+typedef enum { CMP_IR,
+               CMP_KUR,
+               CMP_CR,
+               CMP_RR,
+               CMP_CKUANN,
+    } cmp_cmd_t;
+
+/* type of a cmdline option.
+ * - OPT_BOOL does not take an additional argument and just
+ *   toggles something on or off
+ * - OPT_NUM takes a number argument and sets that to a variable
+ * - OPT_TXT copies the argument text to a buffer
+ * */
+typedef enum { OPT_BOOL, OPT_NUM, OPT_TXT } opttype_t;
+typedef struct 
+    {
+    const char *name;
+    const char *help;
+    opttype_t type;
+    union {
+        char **txt;
+        long *num;
+        } v;
+    } opt_t;
+
+static char *opt_server=NULL;
+static char *server_address=NULL;
+static long  server_port=0;
+static char *opt_path="/";
+
+static char *opt_cmd_s=NULL;
+static int   opt_cmd=-1;
+static char *opt_user=NULL;
+static char *opt_pass=NULL;
+
+static char *opt_cert=NULL;
+static char *opt_key=NULL;
+static char *opt_keypass=NULL;
+
+static char *opt_certout=NULL;
+static char *opt_newkey=NULL;
+static char *opt_newkeypass=NULL;
+
+static char *opt_srvcert=NULL;
+static char *opt_trusted=NULL;
+static char *opt_untrusted=NULL;
+static char *opt_keyfmt_s="PEM";
+static char *opt_certfmt_s="PEM";
+static int   opt_keyfmt=FORMAT_PEM;
+static int   opt_certfmt=FORMAT_PEM;
+
+static char *opt_extcerts=NULL;
+static char *opt_subject=NULL;
+static char *opt_recipient=NULL;
+
+static char *opt_cacertsout=NULL;
+static char *opt_extracertsout=NULL;
+
+static char *opt_proxy=NULL;
+static int   opt_proxyPort=0;
+
+/* Table of commandline options.
+ * NOTE: this table is also used to parse options from
+ *       openssl's config file (openssl.cnf) !*/
+static opt_t cmp_opts[]={
+    { "server", "The 'ADDRESS:PORT' for the CMP server", OPT_TXT, {&opt_server} },
+    { "path", "Path location inside the server", OPT_TXT, {&opt_path} },
+    { "cmd", "CMP command to execute: ir/kur/cr/rr/ckuann/...", OPT_TXT, {&opt_cmd_s} },
+    { "user", "Username for doing the IR with a pre-shared key", OPT_TXT, {&opt_user} },
+    { "pass", "Password for doing the IR with a pre-shared key", OPT_TXT, {&opt_pass} },
+
+    { "cert", "Client's current certificate", OPT_TXT, {&opt_cert} },
+    { "key", "Key for the client's current certificate", OPT_TXT, {&opt_key} },
+    { "keypass", "Password for the key", OPT_TXT, {&opt_keypass} },
+
+    { "certout", "Where to save the new certificate", OPT_TXT, {&opt_certout} },
+    { "newkey", "Key file to use for the new certificate", OPT_TXT, {&opt_newkey} },
+    { "newkeypass", "Password for the new keyfile", OPT_TXT, {&opt_newkeypass} },
+
+    { "srvcert", "Certificate of the CMP server", OPT_TXT, {&opt_srvcert} },
+    { "trusted", "A file of trusted certificates", OPT_TXT, {&opt_trusted} },
+    { "untrusted", "A file of untrusted certificates", OPT_TXT, {&opt_untrusted} },
+
+    { "keyfmt", "Format to use for key files. Default PEM.", OPT_TXT, {&opt_keyfmt_s} },
+    { "certfmt", "Format to use for certificate files. Default PEM.", OPT_TXT, {&opt_certfmt_s} },
+
+    { "extcerts", "List of certificate files to include in outgoing messages", OPT_TXT, {&opt_extcerts} },
+    { "subject", "X509 subject name to be used in the requested certificate template", OPT_TXT, {&opt_subject} },
+    { "recipient", "X509 name of the recipient", OPT_TXT, {&opt_recipient} },
+    
+    { "extracertsout", "File where to save extra certificates received", OPT_TXT, {&opt_extracertsout} },
+    { "cacertsout", "File where to save received CA certificates (from IR)", OPT_TXT, {&opt_cacertsout} },
+
+    { "proxy", "Address of HTTP proxy server to use for the request", OPT_TXT, {&opt_proxy} },
+    { "proxyport", "Port of the proxy server", OPT_NUM, {&opt_proxyPort} },
+};
+
+/* ########################################################################## *
+ * print out the help text for each commandline option
+ * ########################################################################## */
+static void show_help(void)
+    {
+    const int ALIGN_COL=15;
+    opt_t *o=cmp_opts;
+    int i=0,j=0;
+    
+    BIO_puts(bio_err, "\nusage: cmp args\n");
+    for (i=0; i < sizeof(cmp_opts)/sizeof(cmp_opts[0]); i++,o++)
+        {
+        BIO_printf(bio_err, " -%s", o->name);
+        for (j=ALIGN_COL-strlen(o->name); j > 0; j--)
+            BIO_puts(bio_err, " ");
+        BIO_printf(bio_err, " -%s\n", o->help);
+        }
+    BIO_puts(bio_err, "\n");
+    }
+
+/* ########################################################################## *
+ * use the commandline option table to read values from the [ cmp ] section of 
+ * openssl.cnf.  Defaults are taken from the config file, they can be 
+ * overwritten on the command line
+ * ########################################################################## */
+static void read_config(CONF *conf)
+    {
+    opt_t *opt=cmp_opts;
+    int i=0;
+
+    for (i=0; i < sizeof(cmp_opts)/sizeof(cmp_opts[0]); i++,opt++)
+        {
+        switch(opt->type)
+            {
+            case OPT_BOOL:
+            case OPT_NUM:
+                NCONF_get_number_e(conf, CMP_SECTION, opt->name, opt->v.num);
+                break;
+            case OPT_TXT:
+                *opt->v.txt = NCONF_get_string(conf, CMP_SECTION, opt->name);
+                break;
+            default:
+                break;
+            }
+        }
+
+    ERR_clear_error();
+    }
+
+/* ########################################################################## *
+ * verify that all the necessary options have been set
+ * prints reason for error to bio_err
+ * returns 1 on success, 0 on error
+ * ########################################################################## */
+static int check_options(void)
+    {
+    if (opt_server)
+        {
+        char *p=strrchr(opt_server, ':');
+        size_t addrlen=0;
+        if (p == NULL)
+            {
+            BIO_puts(bio_err, "error: missing server port\n");
+            goto err;
+            }
+        addrlen=(size_t)p - (size_t)opt_server;
+        server_address=OPENSSL_malloc(addrlen+1);
+        if (server_address == NULL)
+            {
+            BIO_puts(bio_err, "error: out of memory\n");
+            goto err;
+            }
+        strncpy(server_address, opt_server, addrlen);
+        server_address[addrlen]=0;
+        server_port=atoi(++p);
+    }
+    else
+        {
+        BIO_puts(bio_err, "error: missing server address\n");
+        goto err;
+        }
+
+    if (opt_cmd_s)
+        {
+        if (!strcmp(opt_cmd_s, "ir")) opt_cmd = CMP_IR;
+        else if (!strcmp(opt_cmd_s, "kur")) opt_cmd = CMP_KUR;
+        else if (!strcmp(opt_cmd_s, "cr")) opt_cmd = CMP_CR;
+        else if (!strcmp(opt_cmd_s, "rr")) opt_cmd = CMP_RR;
+        else if (!strcmp(opt_cmd_s, "ckuann")) opt_cmd = CMP_CKUANN;
+        else
+            {
+            BIO_printf(bio_err, "error: unknown cmp command '%s'\n", opt_cmd_s);
+            goto err;
+            }
+    }
+    else
+        {
+        BIO_puts(bio_err, "error: no cmp command to execute\n");
+        goto err;
+        }
+
+    switch (opt_cmd)
+        {
+        case CMP_IR:
+            if (!(opt_user && opt_pass) && !(opt_cert && opt_key))
+                {
+                BIO_puts(bio_err, "error: missing user/pass or existing certificate and key for ir\n");
+                goto err;
+                }
+
+            if (opt_cert && !(opt_srvcert || opt_trusted))
+                {
+                BIO_puts(bio_err, "error: using client certificate but no server certificate or trusted store set\n");
+                goto err;
+                }
+            break;
+        case CMP_KUR:
+        case CMP_CR:
+        case CMP_RR:
+            if (!(opt_cert && opt_key))
+                {
+                BIO_puts(bio_err, "error: missing certificate and key\n");
+                goto err;
+                }
+
+            if (!opt_srvcert && !opt_trusted)
+                {
+                BIO_puts(bio_err, "error: no server certificate or trusted store set\n");
+                goto err;
+                }
+            break;
+        case CMP_CKUANN:
+            /* TODO: sending the empty GENM to request the CKUANN */
+            break;
+        }
+
+    if (opt_cmd == CMP_IR || opt_cmd == CMP_KUR)
+        {
+        if (!opt_newkey)
+            {
+            BIO_puts(bio_err, "error: missing new key file\n");
+            goto err;
+            }
+        if (!opt_certout)
+            {
+            BIO_puts(bio_err, "error: certout not given, nowhere save certificate\n");
+            goto err;
+            }
+        }
+
+    if (opt_keyfmt_s)
+        opt_keyfmt=str2fmt(opt_keyfmt_s);
+
+    if (opt_certfmt_s)
+        opt_certfmt=str2fmt(opt_certfmt_s);
+
+    return 1;
+
+    err:
+    return 0;
+    }
+
+/* ########################################################################## *
+ * create cert store structure with certificates read from givenfile
+ * returns pointer to created X509_STORE on success, NULL on error
+ * ########################################################################## */
+static X509_STORE *create_cert_store(char *file)
+    {
+    X509_STORE *cert_ctx=NULL;
+    X509_LOOKUP *lookup=NULL;
+
+    cert_ctx=X509_STORE_new();
+    if (cert_ctx == NULL) goto err;
+
+    lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
+    if (lookup == NULL) goto err;
+
+    X509_LOOKUP_load_file(lookup, file,
+        opt_certfmt==FORMAT_ASN1 ? X509_FILETYPE_ASN1 : X509_FILETYPE_PEM);
+
+    return cert_ctx;
+
+err:
+    return NULL;
+    }
+
+/* ########################################################################## *
+ * set up the CMP_CTX structure based on options from config file/CLI
+ * prints reason for error to bio_err
+ * returns 1 on success, 0 on error
+ * ########################################################################## */
+static int setup_ctx(CMP_CTX *ctx)
+    {
+    EVP_PKEY *pkey=NULL;
+    EVP_PKEY *newPkey=NULL;
+    X509 *clcert=NULL;
+    X509 *srvcert=NULL;
+
+    CMP_CTX_set1_serverName(ctx, server_address);
+    CMP_CTX_set1_serverPath(ctx, opt_path);
+    CMP_CTX_set1_serverPort(ctx, server_port);
+    
+    if (opt_user && opt_pass)
+        {
+        CMP_CTX_set1_referenceValue(ctx, (unsigned char*)opt_user, strlen(opt_user));
+        CMP_CTX_set1_secretValue(ctx, (unsigned char*)opt_pass, strlen(opt_pass));
+        }
+    
+    if (opt_key &&
+        !(pkey=load_key(bio_err, opt_key, opt_keyfmt, 0, opt_keypass, NULL, "key")))
+        {
+        BIO_printf(bio_err, "error: unable to load private key '%s'\n", opt_key);
+        goto err;
+        }
+    if (pkey) CMP_CTX_set0_pkey(ctx, pkey);
+
+    if (opt_newkey &&
+        !(newPkey=load_key(bio_err, opt_newkey, opt_keyfmt, 0, opt_newkeypass, NULL, "newkey")))
+        {
+        BIO_printf(bio_err, "error: unable to load private key '%s'\n", opt_newkey);
+        goto err;
+        }
+    if (newPkey) CMP_CTX_set0_newPkey(ctx, newPkey);
+
+    if (opt_cert &&
+        !(clcert=load_cert(bio_err, opt_cert, opt_certfmt, NULL, NULL, "clcert")))
+        {
+        BIO_printf(bio_err, "error: unable to load client certificate '%s'\n", opt_cert);
+        goto err;
+        }
+    if (clcert) CMP_CTX_set1_clCert(ctx, clcert);
+
+    if (opt_srvcert &&
+        !(srvcert=load_cert(bio_err, opt_srvcert, opt_certfmt, NULL, NULL, "cacert")))
+        {
+        BIO_printf(bio_err, "error: unable to load server certificate '%s'\n", opt_srvcert);
+        goto err;
+        }
+    if (srvcert) CMP_CTX_set1_caCert(ctx, srvcert);
+
+    if (opt_trusted && !CMP_CTX_set0_trustedStore(ctx, create_cert_store(opt_trusted)))
+        {
+        BIO_printf(bio_err, "error: unable to load trusted store '%s'\n", opt_trusted);
+        goto err;
+        }
+
+    if (opt_untrusted && !CMP_CTX_set0_untrustedStore(ctx, create_cert_store(opt_untrusted)))
+        {
+        BIO_printf(bio_err, "error: unable to load untrusted store '%s'\n", opt_untrusted);
+        goto err;
+        }
+
+    if (opt_subject)
+        {
+        X509_NAME *n=parse_name(opt_subject, MBSTRING_ASC, 0);
+        if (n == NULL)
+            {
+            BIO_printf(bio_err, "error: unable to parse subject name '%s'\n", opt_subject);
+            goto err;
+            }
+        CMP_CTX_set1_subjectName(ctx, n);
+        }
+
+    if (opt_recipient)
+        {
+        X509_NAME *n=parse_name(opt_recipient, MBSTRING_ASC, 0);
+        if (n == NULL)
+            {
+            BIO_printf(bio_err, "error: unable to parse recipient name '%s'\n", opt_recipient);
+            goto err;
+            }
+        CMP_CTX_set1_recipient(ctx, n);
+        }
+
+    if (opt_proxy)
+        {
+        if (opt_proxyPort != 0)
+            {
+            CMP_CTX_set1_proxyName(ctx, opt_proxy);
+            CMP_CTX_set1_proxyPort(ctx, opt_proxyPort);
+            }
+        else
+            {
+            BIO_printf(bio_err, "error: no port given for proxy at '%s'\n", opt_proxy);
+            goto err;
+            }
+        }
+
+    CMP_CTX_set_HttpTimeOut(ctx, 5*60);
+
+    return 1;
+
+    err:
+    return 0;
+    }
+
+
+/* ########################################################################## *
+ * write out the given certificate to the output specified by bio.
+ * depending on options use either PEM or DER format
+ * returns 1 on success, 0 on error
+ * ########################################################################## */
+static int write_cert(BIO *bio, X509 *cert)
+    {
+        if ( (opt_certfmt == FORMAT_PEM && PEM_write_bio_X509(bio, cert))
+             || (opt_certfmt == FORMAT_ASN1 && i2d_X509_bio(bio, cert)) )
+            return 1;
+        return 0;
+    }
+
+/* ########################################################################## *
+ * writes out the received CA certs to the given file
+ * returns number of written certificates on success, 0 on error
+ * ########################################################################## */
+static int save_capubs(CMP_CTX *cmp_ctx, char *destFile)
+    {
+    X509 *cert = NULL;
+    BIO *bio=NULL;
+    int n = 0;
+
+    if (!destFile || (bio=BIO_new(BIO_s_file())) == NULL ||
+            !BIO_append_filename(bio,(char *)destFile))
+        goto err;
+
+    BIO_printf(bio_c_out, "Received %d CA certificates, saving to %s\n", CMP_CTX_caPubs_num(cmp_ctx), destFile);
+    while ( (cert=CMP_CTX_caPubs_pop(cmp_ctx)) != NULL)
+        {
+        if (write_cert(bio, cert))
+            n++;
+        else
+            BIO_printf(bio_err,"ERROR writing certificate to %s!\n", destFile);
+        }
+    return n;
+
+err:
+    BIO_printf(bio_err, "ERROR: could not open '%s' for writing\n", destFile);
+    return 0;
+    }
+
+/* ########################################################################## *
+ * writes out the received extraCerts to the given file
+ * returns number of written certificates on success, 0 on error
+ * ########################################################################## */
+static int save_extracerts(CMP_CTX *cmp_ctx, char *destFile)
+    {
+    X509 *cert = NULL;
+    BIO *bio=NULL;
+    int n = 0;
+
+    if (!destFile || (bio=BIO_new(BIO_s_file())) == NULL ||
+            !BIO_append_filename(bio,(char *)destFile))
+        goto err;
+
+    BIO_printf(bio_c_out, "Received %d extra certificates, saving to %s\n", CMP_CTX_extraCertsIn_num(cmp_ctx), destFile);
+    while ( (cert=CMP_CTX_extraCertsIn_pop(cmp_ctx)) != NULL)
+        {
+        if (write_cert(bio, cert))
+            n++;
+        else
+            BIO_printf(bio_err,"ERROR writing certificate to %s!\n", destFile);
+        }
+    return n;
+
+err:
+    BIO_printf(bio_err, "ERROR: could not open '%s' for writing\n", destFile);
+    return 0;
+    }
+
+
+/* ########################################################################## *
+ * ########################################################################## */
+int MAIN(int argc, char **argv)
+    {
+    char *configfile=NULL;
+    long errorline=-1;
+    char *tofree=NULL; /* used as getenv returns a direct pointer to the environment setting */
+    int badops=0;
+    int ret=1;
+    CMP_CTX *cmp_ctx;
+    X509 *newcert=NULL;
+
+    if (argc <= 1)
+        {
+        badops=1;
+        goto bad_ops;
+        }
+
+    if (!strcmp(argv[1], "-help"))
+        {
+        show_help();
+        goto err;
+        }
+    
+    apps_startup();
+    ERR_load_crypto_strings();
+    bio_c_out=BIO_new_fp(stdout,BIO_NOCLOSE);
+
+    if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
+    if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
+    if (configfile == NULL)
+        {
+        const char *s=X509_get_default_cert_area();
+        size_t len;
+
+        len = strlen(s)+sizeof(CONFIG_FILE)+1;
+        tofree=OPENSSL_malloc(len);
+        BUF_strlcpy(tofree,s,len);
+        BUF_strlcat(tofree,"/"CONFIG_FILE,len);
+        configfile=tofree;
+        }
+
+	/* read default values for options from openssl.cnf */
+    if (configfile)
+        {
+        BIO_printf(bio_err,"Using configuration from %s\n",configfile);
+        conf = NCONF_new(NULL);
+        if (NCONF_load(conf,configfile,&errorline) <= 0)
+            {
+            if (errorline <= 0)
+                BIO_printf(bio_err,"error loading the config file '%s'\n",
+                        configfile);
+            else
+                BIO_printf(bio_err,"error on line %ld of config file '%s'\n",
+                        errorline,configfile);
+            }
+        else
+            read_config(conf);
+        }
+
+    if(tofree)
+        {
+        OPENSSL_free(tofree);
+        tofree = NULL;
+        }
+
+	/* parse commandline options */
+    while (--argc > 0 && ++argv)
+        {
+        opt_t *opt=cmp_opts;
+        char *arg=*argv;
+        int found,i;
+
+        if (*arg++ != '-' || *arg == 0)
+            {
+            badops=1;
+            break;
+            }
+
+        found=0;
+        for (i=0; i < sizeof(cmp_opts)/sizeof(cmp_opts[0]); i++,opt++)
+            {
+            if (opt->name && !strcmp(arg, opt->name))
+                {
+                if (argc <= 1 && opt->type != OPT_BOOL)
+                    {
+                    BIO_printf(bio_err, "missing argument for '-%s'\n", opt->name);
+                    badops=1;
+                    goto bad_ops;
+                    }
+                switch(opt->type)
+                    {
+                    case OPT_BOOL:
+                        *opt->v.num = 1;
+                        break;
+                    case OPT_NUM:
+                        *opt->v.num = atoi(*++argv);
+                        argc--;
+                        break;
+                    case OPT_TXT:
+                        *opt->v.txt = *++argv;
+                        argc--;
+                        break;
+                    default:
+                        badops=1;
+                        break;
+                    }
+                found=1;
+                }
+            }
+        
+        if (!found)
+            {
+            BIO_printf(bio_err, "unknown argument: '%s'\n", *argv);
+            badops=1;
+            goto bad_ops;
+            }
+        }
+
+    if (!badops)
+        badops = check_options() == 0;
+
+bad_ops:
+    if (badops)
+        {
+        show_help();
+        goto err;
+        }
+
+    if (!(cmp_ctx = CMP_CTX_create()) || !setup_ctx(cmp_ctx))
+        {
+        BIO_puts(bio_err, "error creating new cmp context\n");
+        goto err;
+        }
+
+	/* everything is ready, now connect and preform the command! */
+    switch (opt_cmd)
+        {
+        case CMP_IR:
+            newcert = CMP_doInitialRequestSeq(cmp_ctx);
+            if (!newcert)
+                goto err;
+            if (opt_cacertsout && CMP_CTX_caPubs_num(cmp_ctx) > 0)
+                save_capubs(cmp_ctx, opt_cacertsout);
+            break;
+        case CMP_KUR:
+            newcert = CMP_doKeyUpdateRequestSeq(cmp_ctx);
+            if (!newcert)
+                goto err;
+            break;
+        case CMP_CR:
+            newcert = CMP_doCertificateRequestSeq(cmp_ctx);
+            if (!newcert)
+                goto err;
+            break;
+        case CMP_RR:
+            CMP_doRevocationRequestSeq(cmp_ctx);
+            break;
+        case CMP_CKUANN:
+            /* TODO: sending the empty GENM to request the CKUANN */
+            break;
+        default: break;
+        }
+
+    if (opt_extracertsout && CMP_CTX_extraCertsIn_num(cmp_ctx) > 0)
+        save_extracerts(cmp_ctx, opt_extracertsout);
+
+    if (newcert && opt_certout)
+        {
+        BIO *b = NULL;
+        BIO_printf(bio_c_out, "saving certificate to '%s'...\n", opt_certout);
+        b=BIO_new(BIO_s_file());
+        if (b == NULL || !BIO_write_filename(b, opt_certout))
+            {
+            BIO_printf(bio_err, "error: unable to open file '%s' for writing\n", opt_certout);
+            goto err;
+            }
+        if (opt_certfmt == FORMAT_ASN1)
+            ret = i2d_X509_bio(b, newcert) == 0;
+        else
+            ret = PEM_write_bio_X509(b, newcert)==0;
+
+        if (ret) goto err;
+        }
+    
+    ret=0;
+err:
+    if (ret != 0)
+        ERR_print_errors_fp(stderr);
+
+    OPENSSL_EXIT(ret);
+    }
+
Index: openssl-1.0.1h-cmp/Makefile.org
===================================================================
--- openssl-1.0.1h-cmp/Makefile.org	(revision 750)
+++ openssl-1.0.1h-cmp/Makefile.org	(working copy)
@@ -135,6 +135,10 @@
 
 BASEADDR=
 
+# Curl stuff
+CURL_INCLUDE=
+LIBCURL=
+
 DIRS=   crypto ssl engines apps test tools
 ENGDIRS= ccgost
 SHLIBDIRS= crypto ssl
@@ -147,7 +151,7 @@
 	bn ec rsa dsa ecdsa dh ecdh dso engine \
 	buffer bio stack lhash rand err \
 	evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 \
-	cms pqueue ts jpake srp store cmac
+	cms pqueue ts jpake srp store cmac cmp crmf
 # keep in mind that the above list is adjusted by ./Configure
 # according to no-xxx arguments...
 
@@ -218,6 +222,7 @@
 		SHARED_LDFLAGS='$(SHARED_LDFLAGS)'		\
 		KRB5_INCLUDES='$(KRB5_INCLUDES)' LIBKRB5='$(LIBKRB5)'	\
 		ZLIB_INCLUDE='$(ZLIB_INCLUDE)' LIBZLIB='$(LIBZLIB)'	\
+		CURL_INCLUDE='$(CURL_INCLUDE)' LIBCURL='$(LIBCURL)' \
 		EXE_EXT='$(EXE_EXT)' SHARED_LIBS='$(SHARED_LIBS)'	\
 		SHLIB_EXT='$(SHLIB_EXT)' SHLIB_TARGET='$(SHLIB_TARGET)'	\
 		PEX_LIBS='$(PEX_LIBS)' EX_LIBS='$(EX_LIBS)'	\
Index: openssl-1.0.1h-cmp/doc/crypto/CMP_CTX.pod
===================================================================
--- openssl-1.0.1h-cmp/doc/crypto/CMP_CTX.pod	(revision 0)
+++ openssl-1.0.1h-cmp/doc/crypto/CMP_CTX.pod	(revision 764)
@@ -0,0 +1,354 @@
+=pod
+
+=head1 NAME
+
+ CMP_CTX_create,
+ CMP_CTX_init,
+ CMP_CTX_delete,
+ CMP_CTX_set1_referenceValue,
+ CMP_CTX_set1_secretValue,
+ CMP_CTX_set1_caCert,
+ CMP_CTX_set1_clCert,
+ CMP_CTX_set1_oldClCert,
+ CMP_CTX_set1_subjectName,
+ CMP_CTX_set1_newClCert,
+ CMP_CTX_set0_pkey,
+ CMP_CTX_set0_newPkey,
+ CMP_CTX_set1_pkey,
+ CMP_CTX_set1_newPkey,
+ CMP_CTX_set1_transactionID,
+ CMP_CTX_set1_recipNonce,
+ CMP_CTX_set1_serverName,
+ CMP_CTX_set_option,
+ CMP_CTX_caPubs_pop,
+ CMP_CTX_caPubs_num,
+ CMP_CTX_set1_caPubs,
+ CMP_CTX_policyOID_push1,
+ CMP_CTX_set1_extraCertsOut,
+ CMP_CTX_extraCertsOut_push1, 
+ CMP_CTX_extraCertsOut_num,
+ CMP_CTX_set1_extraCertsIn,
+ CMP_CTX_extraCertsIn_pop,
+ CMP_CTX_extraCertsIn_num,
+ CMP_CTX_set0_trustedStore,
+ CMP_CTX_set0_untrustedStore,
+ CMP_CTX_set_error_callback,
+ CMP_CTX_set_debug_callback
+
+ CMP_CTX_failInfoCode_get
+ CMP_CTX_set1_popoMethod
+ CMP_CTX_set1_proxyName
+ CMP_CTX_set1_proxyPort
+ CMP_CTX_set1_recipient
+ CMP_CTX_set1_serverPath
+ CMP_CTX_set1_serverPort
+ CMP_CTX_set_HttpTimeOut
+ CMP_CTX_set_certConf_callback
+ CMP_CTX_subjectAltName_push1
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ CMP_CTX *CMP_CTX_create();
+ int CMP_CTX_init( CMP_CTX *ctx);
+ void CMP_CTX_delete(CMP_CTX *ctx);
+
+ int CMP_CTX_set1_referenceValue( CMP_CTX *ctx, const unsigned char *ref, size_t len);
+ int CMP_CTX_set1_secretValue( CMP_CTX *ctx, const unsigned char *sec, const size_t len);
+ int CMP_CTX_set1_caCert( CMP_CTX *ctx, const X509 *cert);
+ int CMP_CTX_set1_clCert( CMP_CTX *ctx, const X509 *cert);
+ int CMP_CTX_set1_oldClCert( CMP_CTX *ctx, const X509 *cert);
+ int CMP_CTX_set1_subjectName( CMP_CTX *ctx, const X509_NAME *name);
+ int CMP_CTX_set1_newClCert( CMP_CTX *ctx, const X509 *cert);
+ int CMP_CTX_set0_pkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+ int CMP_CTX_set0_newPkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+ int CMP_CTX_set1_pkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+ int CMP_CTX_set1_newPkey( CMP_CTX *ctx, const EVP_PKEY *pkey);
+ int CMP_CTX_set1_transactionID( CMP_CTX *ctx, const ASN1_OCTET_STRING *id);
+ int CMP_CTX_set1_recipNonce( CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce);
+ int CMP_CTX_set1_serverName( CMP_CTX *ctx, const char *name);
+ int CMP_CTX_set1_serverPort( CMP_CTX *ctx, int port);
+ X509 *CMP_CTX_caPubs_pop( CMP_CTX *ctx);
+ int CMP_CTX_caPubs_num( CMP_CTX *ctx);
+ int CMP_CTX_set1_caPubs( CMP_CTX *ctx, const STACK_OF(X509) *caPubs);
+ int CMP_CTX_policyOID_push1( CMP_CTX *ctx, const char *policyOID);
+
+ int CMP_CTX_set1_extraCertsOut( CMP_CTX *ctx, const STACK_OF(X509) *extraCertsOut);
+ int CMP_CTX_extraCertsOut_push1( CMP_CTX *ctx, const X509 *val);
+ int CMP_CTX_extraCertsOut_num( CMP_CTX *ctx);
+ int CMP_CTX_set1_extraCertsIn( CMP_CTX *ctx, const STACK_OF(X509) *extraCertsIn);
+ X509 *CMP_CTX_extraCertsIn_pop( CMP_CTX *ctx);
+ int CMP_CTX_extraCertsIn_num( CMP_CTX *ctx);
+
+ int CMP_CTX_set0_trustedStore( CMP_CTX *ctx, X509_STORE *store);
+ int CMP_CTX_set0_untrustedStore( CMP_CTX *ctx, X509_STORE *store);
+
+ int CMP_CTX_set_error_callback( CMP_CTX *ctx, cmp_logfn_t cb)
+ int CMP_CTX_set_debug_callback( CMP_CTX *ctx, cmp_logfn_t cb)
+
+ #define CMP_CTX_OPT_UNSET                      0
+ #define CMP_CTX_OPT_SET                        1
+ #define CMP_CTX_OPT_IMPLICITCONFIRM            2
+ #define CMP_CTX_OPT_POPMETHOD                  3
+ #define CMP_CTX_OPT_MAXPOLLTIME                4
+ #define CMP_CTX_PERMIT_TA_IN_EXTRACERTS_FOR_IR 5
+ #define CMP_CTX_SET_SUBJECTALTNAME_CRITICAL    6
+ #define CMP_CTX_USE_TLS                        7
+ int CMP_CTX_set_option( CMP_CTX *ctx, const int opt, const int val);
+
+ unsigned long CMP_CTX_failInfoCode_get(CMP_CTX *ctx);
+ int CMP_CTX_set1_popoMethod( CMP_CTX *ctx, int method);
+ int CMP_CTX_set1_proxyName( CMP_CTX *ctx, const char *name);
+ int CMP_CTX_set1_proxyPort( CMP_CTX *ctx, int port);
+ int CMP_CTX_set1_recipient( CMP_CTX *ctx, const X509_NAME *name);
+ int CMP_CTX_set1_serverPath( CMP_CTX *ctx, const char *path);
+ int CMP_CTX_set1_serverPort( CMP_CTX *ctx, int port);
+ int CMP_CTX_set_HttpTimeOut( CMP_CTX *ctx, int time);
+ int CMP_CTX_set_certConf_callback( CMP_CTX *ctx, cmp_certConfFn_t cb);
+ int CMP_CTX_subjectAltName_push1( CMP_CTX *ctx, const GENERAL_NAME *name);
+
+=head1 DESCRIPTION
+
+This is the context API for using CMP (Certificate Management Protocol) with OpenSSL.
+
+CMP_CTX_create() allocates and initialized an CMP_CTX structure.
+
+CMP_CTX_init() initializes the context to default values. Transport is set to HTTP, 
+proof-of-posession method to POPOSigningKey
+
+CMP_CTX_delete() frees any allocated non-ASN1 fields of CMP_CTX and
+calls the ASN1 defined CMP_CTX_free() function to free the rest.
+
+CMP_CTX_set1_referenceValue() sets the given referenceValue in the given
+CMP_CTX structure.
+
+CMP_CTX_set1_secretValue() sets the given secretValue in the given
+CMP_CTX structure.
+
+CMP_CTX_set1_caCert() sets the given CA Certificate in the given CMP_CTX
+structure.
+
+CMP_CTX_set1_clCert() sets the given Client Certificate in the given
+CMP_CTX structure. The Client Certificate will then be used by the
+functions to set the "sender" field for messages originating from the
+client. The private key belonging to this certificate is then used
+create the protection in case of MSG_SIG_ALG.
+
+CMP_CTX_set1_oldClCert() sets the old certificate that we are updating
+in KUR. If this is not set, clCert will be the one being updated.
+
+CMP_CTX_set1_subjectName() sets the subject name that will be used in
+the CertTemplate structure when requesting a new certificate. Note that
+if clCert is set, the name will be read from them and this will be
+ignored.
+
+CMP_CTX_set1_newClCert() sets the given (newly obtained) Client
+Certificate in the given CMP_CTX structure.
+
+CMP_CTX_set0_pkey() sets the given EVP_PKEY structure, holding the
+private and public keys, belonging to the Client Certificate, in the
+given CMP_CTX structure.
+
+CMP_CTX_set1_pkey() is the same as above, except that it does not
+consume the pointer.
+
+CMP_CTX_set0_newPkey() sets the given EVP_PKEY structure, holding the
+private and public keys, which shall be certified, in the given CMP_CTX
+structure
+
+CMP_CTX_set1_newPkey() is the same as above, except that it does not
+consume the pointer.
+
+CMP_CTX_set1_transactionID() sets the given transaction ID in the given
+CMP_CTX structure.
+
+CMP_CTX_set1_recipNonce() sets the given recip nonce in the given
+CMP_CTX structure.
+
+CMP_CTX_set1_serverName() sets the given server Address (as IP or name)
+in the given CMP_CTX structure.
+
+CMP_CTX_set1_serverPort() sets the port of the CMP server to connect to.
+
+CMP_CTX_set_option() sets the given values to the options
+(e.g. CMP_CTX_OPT_IMPLICITCONFIRM) in the given CMP_CTX structure. The
+values can be CMP_CTX_OPT_UNSET or CMP_CTX_OPT_SET. Options are always
+set to UNSET when the CMP_CTX structure is initialized.
+
+The following options can be set:
+    CMP_CTX_OPT_IMPLICITCONFIRM
+        Request server to enable implicit confirm mode, where the client
+        does not need to send confirmation upon receiving the
+        certificate. If the server does not enable implicit confirmation
+        in the return message, then confirmation is sent anyway.
+
+    CMP_CTX_OPT_POPMETHOD
+	Proof of posession method to use:
+	      CRMF_POPO_SIGNATURE - sign a value with private key
+	      CRMF_POPO_ENCRCERT - decrypt the encrypted certificate
+	      			   ("indirect method")
+
+    CMP_CTX_OPT_MAXPOLLTIME
+	Maximum amount of time, in seconds, to attempt polling for a 
+	response to a message.
+
+    CMP_CTX_PERMIT_TA_IN_EXTRACERTS_FOR_IR
+	Allow retrieving a trust anchor from extraCers and using that
+	to validate the certificate chain of an IP message.
+
+    CMP_CTX_OPT_POPMETHOD
+        Select the proof of posession method to use. Possible values
+        are:
+            CRMF_POPO_SIGNATURE
+            CRMF_POPO_ENCRCERT
+            CRMF_POPO_RAVERIFIED
+
+CMP_CTX_caPubs_num() can be used after an Initial Request or Key Update
+request to check the number of CA certificates that were sent from the
+server.
+
+CMP_CTX_caPubs_pop() pops one CA certificates of the stack of received
+CA certs and returns it
+
+CMP_CTX_set1_caPubs() copies the given caPubs stack to the context so
+that it may be accessed later by CMP_CTX_caPubs_num() and
+CMP_CTX_caPubs_pop().
+
+CMP_CTX_policyOID_push1() adds the certificate policy OID given by the
+string to the X509_EXTENSIONS of the certificate template we are
+requesting.
+
+CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be
+sent to remote.
+
+CMP_CTX_extraCertsOut_push1() adds the given certificate to the outbound
+extraCerts stack, without consuming the pointer.
+ 
+CMP_CTX_extraCertsOut_num() returns the number of certificates in the
+outbound extraCerts stack.
+
+CMP_CTX_set1_extraCertsIn() sets the stack of extraCerts that was
+received from remote.
+
+CMP_CTX_extraCertsIn_pop() pops and returns one certificate off the
+stack of extra certificates received from remote.
+
+CMP_CTX_extraCertsIn_num() returns the number of certificates that were
+received from remote.
+
+CMP_CTX_set0_trustedStore() sets the X509_STORE type certifice store
+containing root CA certificates. This is used for example when
+attempting to validate CA certificate path.
+
+CMP_CTX_set0_untrustedStore() sets the X509_STORE type certifice store
+containing intermediate certificates needed for building our own
+certificate chain and including it in extraCerts.
+
+CMP_CTX_set_error_callback() sets a callback function for receiving
+error messages.
+
+CMP_CTX_set_debug_callback() sets a callback function for receiving
+debug messages.
+
+CMP_CTX_failInfoCode_get() returns the CMP error code from the failInfo
+field. This is a bit field and the flags for it are specified in
+cmp.h. The flags start with CMP_CTX_FAILINFO, for example:
+CMP_CTX_FAILINFO_badAlg.
+
+CMP_CTX_set1_popoMethod() sets the proof-of-posession method to be used
+for ir, kur etc. Possible values are defined in crmf.h:
+
+=over 8
+
+=item * CRMF_POPO_NONE      - ProofOfPossession field omitted, CA/RA uses out-of-band method to verify POP (compare RFC 4211, section 4).
+
+=item * CRMF_POPO_SIGNATURE - POP according to RFC 4211, section 4.1 (only case 3 supported so far) - default after CMP_CTX_init.
+
+=item * CRMF_POPO_ENCRCERT  - POP according to RFC 4211, section 4.2 with the indirect method (subsequentMessage/enccert)
+
+=back
+
+CMP_CTX_set1_proxyName() sets the hostname of the HTTP proxy to be used
+for connecting to the CA server.
+
+CMP_CTX_set1_proxyPort() sets the port of the HTTP proxy.
+
+CMP_CTX_set1_recipient() sets the recipient name that will be set in the
+PKIHeader, i.e. the X509 name of the CA server.
+
+CMP_CTX_set1_serverPath() HTTP path of the CMP server on the host.
+
+CMP_CTX_set1_serverPort() server port to connect to.
+
+CMP_CTX_set_HttpTimeOut() sets the maximum amount of time an the HTTP 
+operation is allowed to take before a timeout error is returned.
+
+CMP_CTX_set_certConf_callback() sets a callback that can be used to
+check the certificate received from the server. If the certificate
+should be accepted the callback must return 1, and 0 if the certificate
+is to be rejected.
+
+CMP_CTX_subjectAltName_push1() adds the given X509 name to the list of
+alternate names on the certificate template request.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+The implementation of CMP for OpenSSL is still work in progress. The API
+might change every release!
+
+=head1 RETURN VALUES
+
+CMP_CTX_create() returns a pointer to an initialized CMP_CTX structure.
+
+All other functions return 0 on error, 1 on success.
+
+=head1 EXAMPLE
+
+The following code does an Initial Request:
+
+	cmp_ctx = CMP_CTX_create();
+	CMP_CTX_set1_serverName( cmp_ctx, opt_serverName);
+	CMP_CTX_set1_referenceValue( cmp_ctx, idString, idStringLen);
+	CMP_CTX_set1_secretValue( cmp_ctx, password, passwordLen);
+	CMP_CTX_set0_pkey( cmp_ctx, initialPkey);
+	CMP_CTX_set1_caCert( cmp_ctx, caCert);
+
+	initialClCert = CMP_doInitialRequestSeq(cmp_ctx);
+
+The following code does an Initial Request with, using an
+external identity certificate (RFC 4210, Appendix E.7):
+
+	cmp_ctx = CMP_CTX_create();
+	CMP_CTX_set1_serverName( cmp_ctx, opt_serverName);
+	CMP_CTX_set1_referenceValue( cmp_ctx, idString, idStringLen);
+	CMP_CTX_set0_pkey( cmp_ctx, initialPkey);
+	CMP_CTX_set1_caCert( cmp_ctx, caCert);
+
+	initialClCert = CMP_doInitialRequestSeq(cmp_ctx);
+
+Here externalCert is an X509 certificate granted to the EE by another CA
+which is trusted by the current CA the code will connect to.
+
+
+The following code does a Key Update Request:
+
+	cmp_ctx = CMP_CTX_create();
+	CMP_CTX_set1_serverName( cmp_ctx, opt_serverName);
+	CMP_CTX_set0_pkey( cmp_ctx, initialPkey);
+	CMP_CTX_set0_newPkey( cmp_ctx, updatedPkey);
+	CMP_CTX_set1_clCert( cmp_ctx, initialClCert);
+	CMP_CTX_set1_caCert( cmp_ctx, caCert);
+
+	updatedClCert = CMP_doKeyUpdateRequestSeq(cmp_ctx);
+
+
+=head1 TODO
+
+A lot!
+
+=head1 SEE ALSO
+
+CMP_sessions, CMP_http
Index: openssl-1.0.1h-cmp/doc/crypto/CMP_http.pod
===================================================================
--- openssl-1.0.1h-cmp/doc/crypto/CMP_http.pod	(revision 0)
+++ openssl-1.0.1h-cmp/doc/crypto/CMP_http.pod	(revision 764)
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+ CMP_PKIMESSAGE_http_perform
+ CMP_get_http_response_code
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ int CMP_PKIMESSAGE_http_perform(const CMP_CTX *ctx, const CMP_PKIMESSAGE *msg, CMP_PKIMESSAGE **out);
+ long CMP_get_http_response_code(const CMP_CTX *ctx);
+
+=head1 DESCRIPTION
+
+This is the API for creating a BIO for CMP (Certificate Management
+Protocol) over HTTP with OpenSSL utilizing cURL.
+
+There are two versions of the HTTP code: the default one uses a minimal
+HTTP implementation adapted from OCSP (crypto/ocsp/ocsp_ht.c), and the
+second one uses libcurl. To enable the libcurl version, one needs to
+give 'curl' as an option when running ./config.
+
+CMP_PKIMESSAGE_http_perform() sends the given pkimessage msg to the CMP server
+specified in ctx, and returns the servers response in out.
+
+CMP_get_http_response_code() returns last http response code from the ctx.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+CMP_get_http_response_code() returns last http response
+code of the given bio, 0 on error. Note: This is not available on the
+non-curl version.
+
+=head1 EXAMPLE
+
+The following code does an Initial Request:
+
+	cmp_ctx = CMP_CTX_create();
+	CMP_CTX_set1_serverName( cmp_ctx, opt_serverName);
+	CMP_CTX_set1_referenceValue( cmp_ctx, idString, idStringLen);
+	CMP_CTX_set1_secretValue( cmp_ctx, password, passwordLen);
+	CMP_CTX_set0_newPkey( cmp_ctx, initialPkey);
+	CMP_CTX_set1_srvCert( cmp_ctx, caCert);
+
+	initialClCert = CMP_doInitialRequestSeq(cmp_ctx);
+
+
+The following code does an Key Update Request:
+
+	cmp_ctx = CMP_CTX_create();
+	CMP_CTX_set1_serverName( cmp_ctx, opt_serverName);
+	CMP_CTX_set0_pkey( cmp_ctx, initialPkey);
+	CMP_CTX_set0_newPkey( cmp_ctx, updatedPkey);
+	CMP_CTX_set1_clCert( cmp_ctx, initialClCert);
+	CMP_CTX_set1_srvCert( cmp_ctx, caCert);
+
+	updatedClCert = CMP_doKeyUpdateRequestSeq(cmp_ctx);
+
+=head1 TODO
+
+=head1 SEE ALSO
+
+CMP_CTX, CMP_session
Index: openssl-1.0.1h-cmp/doc/crypto/CMP_lib.pod
===================================================================
--- openssl-1.0.1h-cmp/doc/crypto/CMP_lib.pod	(revision 0)
+++ openssl-1.0.1h-cmp/doc/crypto/CMP_lib.pod	(revision 764)
@@ -0,0 +1,188 @@
+=pod
+
+=head1 NAME
+
+  CMP_CERTREPMESSAGE_PKIStatus_get,
+  CMP_CERTREPMESSAGE_certResponse_get0,
+  CMP_CERTREPMESSAGE_certType_get,
+  CMP_CERTSTATUS_set_certHash,
+  CMP_ERRORMSGCONTENT_PKIStatus_get_string,
+  CMP_PKIFAILUREINFO_check,
+  CMP_PKIHEADER_generalInfo_item_push0,
+  CMP_PKIHEADER_new_senderNonce,
+  CMP_PKIHEADER_push0_freeText,
+  CMP_PKIHEADER_push1_freeText,
+  CMP_PKIHEADER_init,
+  CMP_PKIHEADER_set1_recipNonce,
+  CMP_PKIHEADER_set1_recipient,
+  CMP_PKIHEADER_set1_sender,
+  CMP_PKIHEADER_set1_senderKID,
+  CMP_PKIHEADER_set1_transactionID,
+  CMP_PKIHEADER_set_messageTime,
+  CMP_PKIHEADER_set_version,
+  CMP_PKIMESSAGE_check_implicitConfirm,
+  CMP_PKIMESSAGE_genm_item_push0,
+  CMP_PKIMESSAGE_get_bodytype,
+  CMP_PKIMESSAGE_parse_error_msg,
+  CMP_PKIMESSAGE_set_bodytype,
+  CMP_PKIMESSAGE_set_implicitConfirm,
+  CMP_PKISTATUSINFO_PKIstatus_get,
+  CMP_get_protectionAlg_pbmac,
+  CMP_protection_new,
+  CMP_CERTREPMESSAGE_PKIStatusString_get0,
+  CMP_ITAV_stack_item_push0
+
+=head1 SYNOPSIS
+
+  #include <openssl/cmp.h>
+
+  long CMP_CERTREPMESSAGE_PKIStatus_get( CMP_CERTREPMESSAGE *certRep, long certReqId);
+  CMP_CERTRESPONSE *CMP_CERTREPMESSAGE_certResponse_get0( CMP_CERTREPMESSAGE *certRep, long certReqId);
+  int CMP_CERTREPMESSAGE_certType_get( CMP_CERTREPMESSAGE *certRep, long certReqId);
+  int CMP_CERTSTATUS_set_certHash( CMP_CERTSTATUS *certStatus, const X509 *cert);
+  char *CMP_ERRORMSGCONTENT_PKIStatus_get_string( CMP_ERRORMSGCONTENT *error);
+  int CMP_PKIFAILUREINFO_check( ASN1_BIT_STRING *failInfo, int codeBit);
+  int CMP_PKIHEADER_generalInfo_item_push0(CMP_PKIHEADER *hdr, const CMP_INFOTYPEANDVALUE *itav);
+  int CMP_PKIHEADER_new_senderNonce(CMP_PKIHEADER *hdr);
+  int CMP_PKIHEADER_push0_freeText( CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
+  int CMP_PKIHEADER_push1_freeText( CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
+  int CMP_PKIHEADER_init(CMP_CTX *ctx, CMP_PKIHEADER *hdr);
+  int CMP_PKIHEADER_set1_recipNonce(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *recipNonce);
+  int CMP_PKIHEADER_set1_recipient(CMP_PKIHEADER *hdr, const X509_NAME *nm);
+  int CMP_PKIHEADER_set1_sender(CMP_PKIHEADER *hdr, const X509_NAME *nm);
+  int CMP_PKIHEADER_set1_senderKID(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *senderKID);
+  int CMP_PKIHEADER_set1_transactionID(CMP_PKIHEADER *hdr, const ASN1_OCTET_STRING *transactionID);
+  int CMP_PKIHEADER_set_version(CMP_PKIHEADER *hdr, int version);
+  int CMP_PKIMESSAGE_check_implicitConfirm(CMP_PKIMESSAGE *msg);
+  int CMP_PKIMESSAGE_genm_item_push0(CMP_PKIMESSAGE *msg, const CMP_INFOTYPEANDVALUE *itav);
+  int CMP_PKIMESSAGE_get_bodytype( CMP_PKIMESSAGE *msg);
+  char *CMP_PKIMESSAGE_parse_error_msg( CMP_PKIMESSAGE *msg, char *errormsg, int bufsize);
+  int CMP_PKIMESSAGE_set_bodytype( CMP_PKIMESSAGE *msg, int type);
+  int CMP_PKIMESSAGE_set_implicitConfirm(CMP_PKIMESSAGE *msg);
+  long CMP_PKISTATUSINFO_PKIstatus_get( CMP_PKISTATUSINFO *statusInfo);
+  X509_ALGOR *CMP_get_protectionAlg_pbmac();
+  ASN1_BIT_STRING *CMP_protection_new(CMP_PKIMESSAGE *pkimessage, const EVP_PKEY *pkey, const ASN1_OCTET_STRING *secret);
+  STACK_OF(ASN1_UTF8STRING)* CMP_CERTREPMESSAGE_PKIStatusString_get0( CMP_CERTREPMESSAGE *certRep, long certReqId);
+  int CMP_ITAV_stack_item_push0(STACK_OF(CMP_INFOTYPEANDVALUE) **itav_sk_p, const CMP_INFOTYPEANDVALUE *itav);
+
+=head1 DESCRIPTION
+
+CMP_CERTREPMESSAGE_PKIStatus_get() returns the PKIStatus of the given
+certReqId inside a CertRepMessage, or -1 on error.
+
+CMP_CERTREPMESSAGE_certResponse_get0() returns a pointer to the
+CertResponse with the given certReqId inside a CertRepMessage. If no
+CertResponse is available or if there's an error, the function returns
+NULL.
+
+CMP_CERTREPMESSAGE_certType_get() returns the type of the certificate
+contained in the certificate response, or -1 on error.
+
+CMP_CERTSTATUS_set_certHash() calculates a hash of the certificate,
+using the same hash algorithm as is used to create and verify the
+certificate signature, and places the has into the certHash field of a
+CMP_CERTSTATUS structure. This is used in the certConf message, for
+example, to confirm that the certificate was received successfully.
+
+CMP_PKIFAILUREINFO_check() checks whether a given bit is set within a
+given PKIFailureInfo.
+
+CMP_PKIHEADER_generalInfo_item_push0() adds the given InfoTypeAndValue
+item to the hdr->generalInfo stack.
+
+CMP_PKIHEADER_new_senderNonce() generates a random value for the
+hdr->senderNonce field, which is used to proetct the PKIMessage against
+replay attacks.
+
+CMP_PKIHEADER_push0_freeText() pushes an ASN1_UTF8STRING to
+hdr->freeText and consume the given pointer.
+
+CMP_PKIHEADER_push1_freeText() does the same as above, but does not
+consume the pointer.
+
+CMP_PKIHEADER_init() initializes a PKIHeader structure based on the
+values in the given CMP_CTX structure.
+
+CMP_PKIHEADER_set1_recipNonce() sets the recpiNonce field in the given
+hdr to the given value.
+
+CMP_PKIHEADER_set1_recipient() sets the recipient field in the given
+PKIHeader to the given X509 Name value, without consuming the pointer.
+
+CMP_PKIHEADER_set1_sender() sets the sender field in the given PKIHeader
+to the given X509 Name value, without consuming the pointer.
+
+CMP_PKIHEADER_set1_senderKID() Sets hdr->senderKID to the given
+string. In IR this is the reference number issued by the CA. In KUR 
+this is set to the public key ID from the previously issued certificate.
+
+CMP_PKIHEADER_set1_transactionID() copies the given transactionID to
+hdr->transactionID. If the transactionID parameter is NULL, a new random
+value is generated for it.
+
+CMP_PKIHEADER_set_version() sets hdr->pvno to the given integer.
+
+CMP_PKIMESSAGE_check_implicitConfirm() returns 1 if implicitConfirm is
+set in the given PKIMessage, 0 if not.
+
+CMP_PKIMESSAGE_genm_item_push0() pushes an InfoTypeAndValue item to the
+stack of general messages (GenMsg).
+
+CMP_PKIMESSAGE_get_bodytype() returns the body type of the given
+PKIMessage.
+
+CMP_PKIMESSAGE_parse_error_msg() reads the error messages from the given
+PKIMessage, and prints out the results in the given errormsg buffer.
+
+CMP_PKIMESSAGE_set_bodytype() sets the type of the message contained in
+the PKIMessage body field.
+
+CMP_PKIMESSAGE_set_implicitConfirm() sets implicitConfirm in the
+generalInfo field of the header.
+
+CMP_PKIMESSAGE_protect() protects the given message deciding on the algorithm
+depending on the available context information:  If there is a secretValue it
+selects PBMAC if not and there is a clCert it selects Signature.  Generates and
+sets the protection to the given pkimessage.
+
+CMP_PKISTATUSINFO_PKIstatus_get() finds the CertResponse with the given
+certReqId inside the given CertRepMessage, and returns the value of
+PKIStatus in that message.
+
+CMP_get_protectionAlg_pbmac() initializes an X509_ALGOR structure for
+Password Based MAC. Creates a CRMF_PBMPARAMETER structure for the
+parameters.
+
+CMP_protection_new() calculates the value of protection field for the
+PKIMessage, either by using Password based MAC or signing it with a
+private key.
+
+CMP_CERTREPMESSAGE_PKIStatusString_get0() gets the CertResponse with the
+given certReqId inside the gven CertReqMessage, and returns the
+status->statuString field contained in it.
+
+CMP_ITAV_stack_item_push0() pushes the given InfoTypeAndValue to the
+given stack, creating a new stack if one does not exist yet.
+
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+The implementation of CMP for OpenSSL is still work in progress. The API
+might change every release!
+
+=head1 RETURN VALUES
+
+
+
+=head1 EXAMPLE
+
+
+=head1 TODO
+
+A lot!
+
+=head1 SEE ALSO
+
+CMP_CTX, CMP_session, CMP_msg, CMP_http
Index: openssl-1.0.1h-cmp/doc/crypto/CMP_msg.pod
===================================================================
--- openssl-1.0.1h-cmp/doc/crypto/CMP_msg.pod	(revision 0)
+++ openssl-1.0.1h-cmp/doc/crypto/CMP_msg.pod	(revision 764)
@@ -0,0 +1,58 @@
+=pod
+
+=head1 NAME
+
+ CMP_certConf_new,
+ CMP_cr_new,
+ CMP_genm_new,
+ CMP_ir_new,
+ CMP_kur_new	
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ CMP_PKIMESSAGE * CMP_ir_new( CMP_CTX *ctx);
+ CMP_PKIMESSAGE * CMP_cr_new( CMP_CTX *ctx);
+ CMP_PKIMESSAGE * CMP_kur_new( CMP_CTX *ctx);
+ CMP_PKIMESSAGE * CMP_certConf_new( CMP_CTX *ctx);
+ CMP_PKIMESSAGE * CMP_genm_new( CMP_CTX *ctx);
+
+=head1 DESCRIPTION
+
+This is the API for creating different CMP related PKIMESSAGES. The
+functions allocate a new message and fill it with the relevant data from
+the given CMP_CTX.
+
+CMP_ir_new() creates an Initial Request message.
+
+CMP_cr_new() creates a Certificate Request message.
+
+CMP_kur_new() creates a Key Update Request message.
+
+CMP_certConf_new() creates a Certificate Confirmation message.
+
+CMP_genm_new() creates a new General Message.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+The implementation of CMP for OpenSSL is still work in progress. The API
+might change every release!
+
+=head1 RETURN VALUES
+
+All of the functions return a new CMP_PKIMESSAGE structure containing
+the generated message.
+
+=head1 EXAMPLE
+
+
+=head1 TODO
+
+A lot!
+
+=head1 SEE ALSO
+
+CMP_CTX, CMP_session, CMP_http
Index: openssl-1.0.1h-cmp/doc/crypto/CMP_ses.pod
===================================================================
--- openssl-1.0.1h-cmp/doc/crypto/CMP_ses.pod	(revision 0)
+++ openssl-1.0.1h-cmp/doc/crypto/CMP_ses.pod	(revision 764)
@@ -0,0 +1,77 @@
+=pod
+
+=head1 NAME
+
+ CMP_doInitialRequestSeq,
+ CMP_doKeyUpdateRequestSeq,
+ CMP_doCertificateRequestSeq,
+ CMP_doGeneralMessageSeq,
+ CMP_doRevocationRequestSeq
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ X509 *CMP_doInitialRequestSeq(CMP_CTX *ctx);
+ X509 *CMP_doKeyUpdateRequestSeq(CMP_CTX *ctx);
+ X509 *CMP_doCertificateRequestSeq(CMP_CTX *ctx);
+ STACK_OF(CMP_INFOTYPEANDVALUE) *CMP_doGeneralMessageSeq(CMP_CTX *ctx, int nid, char *value);
+ int CMP_doRevocationRequestSeq(CMP_CTX *ctx);
+
+=head1 DESCRIPTION
+
+This is the API for doing CMP (Certificate Management Protocol)  client-server
+message sequences using with OpenSSL. The conveying protocol is HTTP.
+
+CMP_doInitialRequestSeq() does the transaction which obtains an initial certificate
+from the CA. A populated CMP_CTX structure has to be given as arguments.
+
+CMP_doKeyUpdateRequestSeq() does the transaction which obains a certificate for an
+updatded key from the CA. A populated CMP_CTX structure has to be given as arguments.
+
+CMP_doCertificateRequestSeq() requests an additional certificate for an existing
+key from the CA. A populated CMP_CTX structure has to be given as arguments.
+
+CMP_doGeneralMessageSeq() sends a general message and returns the Infotype and
+value structures returned by the server.  This can e.g. be used to poll for the
+CRL or CA Key Updates.
+
+CMP_doRevocationRequestSeq() requests the revocation of the used certificate via
+an revocation request sent to the server.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210 (and CRMF in RFC 4211).
+
+=head1 RETURN VALUES
+
+CMP_doInitialRequestSeq(), CMP_doCertificateRequestSeq() and
+CMP_doKeyUpdateRequestSeq() return a pointer the newly obtained X509 certificate
+on success, NULL on error.
+
+=head1 EXAMPLE
+
+See CMP_CTX for examples on how to prepare the context for these
+functions.
+
+=head1 TODO
+
+The functions for IR, CR and KUR do not yet suppurt requesting multiple
+certificates.
+
+The function for sending GENM does not yet directly support sending multiple
+ITAV structures.
+
+The reason for an IP/KUP/CP returning waiting status as optional sent in a
+PKIFreetext structure could be printed/returned to the user.
+
+The function to request revocation of certificates only can revoke the current
+certificate which is also used for signing the messages.  It should be changed
+so that the certificate to revoke is explicitly given.  So far only one
+certificate can be revoked although that could be several.
+
+The message sequences for other CMP operations are missing so far.
+
+=head1 SEE ALSO
+
+CMP_CTX, CMP_http
Index: openssl-1.0.1h-cmp/doc/apps/openssl_cmp.pod
===================================================================
--- openssl-1.0.1h-cmp/doc/apps/openssl_cmp.pod	(revision 0)
+++ openssl-1.0.1h-cmp/doc/apps/openssl_cmp.pod	(revision 764)
@@ -0,0 +1,212 @@
+
+=pod
+
+=head1 NAME
+
+cmp - client for the Certificate Management Protocol (RFC4210)
+
+=head1 SYNOPSIS
+
+B<openssl> B<cmp>
+[B<-server ADDRESS:PORT>]
+[B<-path remote_path>]
+[B<-cmd ir|kur|cr|rr>]
+[B<-user username>]
+[B<-pass password>]
+[B<-cert filename>]
+[B<-key filename>]
+[B<-keypass password>]
+[B<-certout filename>]
+[B<-newkey filename>]
+[B<-newkeypass password>]
+[B<-srvcert filename>]
+[B<-trusted filename>]
+[B<-untrusted filename>]
+[B<-keyfmt DER|PEM>]
+[B<-certfmt DER|PEM>]
+[B<-extcerts filenames>]
+[B<-subject name>]
+[B<-recipient name>]
+[B<-extracertsout directory>]
+[B<-cacertsout directory>]
+
+=head1 DESCRIPTION
+
+The B<cmp> command is a client implementation for the Certificate
+Management Protocol as defined in RFC4210. It can be used to request
+certificates from a CA server, update their keys and request the
+certificates to be revoked and perform other CMP requests.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-server ADDRESS:PORT>
+
+The IP address or hostname and port of the CMP server to connect to.
+
+=item B<-path remote_path>
+
+HTTP path location to use for the CMP server.
+
+=item B<-cmd ir|kur|cr|rr>
+
+CMP command to execute. Currently implemented commands are:
+    ir  - Initial Request
+    kur - Key Update Request
+    cr  - Certificate Request
+    rr  - Revocation Request
+
+=item B<-user username>
+
+Username (reference value) to be used when messages are authenticated
+with pre-shared keys.
+
+=item B<-pass password>
+
+Password (secret value) to be used when messages are authenticated with
+pre-shared keys.
+
+=item B<-cert filename>
+
+The client's currently existing certificate. This will be used for
+signing messages for example in the Key Update Request, or when
+authenticating the IR using an existing certificate (as defined in
+appendix E.7 of the RFC).
+
+=item B<-key filename>
+
+The corresponding private key file for the client's current certificate given in
+the -cert option.
+
+=item B<-keypass password>
+
+Password for the private key given with the -key option.  If not given here, the
+password will be prompted for if needed.
+
+=item B<-certout filename>
+
+The file where the newly received certificate should be saved.
+
+=item B<-newkey filename>
+
+The file containing the key that we will be requesting the new certificate to be
+issued for.  For example in IR, CR or KUR.
+
+=item B<-newkeypass password>
+
+Password of the new key file given with the -newkey option.  If not given here, the 
+password will be prompted for if needed.
+
+=item B<-srvcert filename>
+
+Certificate of the CMP server, to be used if the certificate is available and directly
+trusted.
+
+=item B<-trusted filename>
+
+A file with trusted certificates. The file could contain multiple
+certificates concatenated together.
+
+=item B<-untrusted filename>
+
+A file of untrusted certificates needed for path validation. The file can contain 
+multiple certificates.
+
+=item B<-keyfmt DER|PEM>
+
+Format the key files are stored in. Default value is PEM.
+
+=item B<-certfmt DER|PEM>
+
+Format the certificate files are stored in. Default value is PEM.
+
+=item B<-extcerts filenames>
+
+List of certificate files to include in the extraCerts field of outgoing
+requests.
+
+=item B<-subject name>
+
+X509 subject name to be used in the requested certificate template.
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
+
+=item B<-recipient name>
+
+X509 name of the recipient, i.e. the name of the CA we are sending the
+request to. If no CA certificate is provided, then at least the
+recipient name must be specified in order for the IR to work.
+The argument must be formatted as I</type0=value0/type1=value1/type2=...>,
+characters may be escaped by \ (backslash), no spaces are skipped.
+
+=item B<-extracertsout directory>
+
+Directory where to save any extra certificates received in a response
+message.
+
+=item B<-cacertsout directory>
+
+Directory where to save received CA certificates (from an Initial
+Response message).
+
+=back
+
+=head1 EXAMPLES
+
+=over 4
+
+Note: in these examples the '\' means the example should be all on one
+line.
+
+Sending an initial request message to a CMP server running on the local
+host, using a pre-shared secret key for authentication. In this example
+the client does not have the CA certificate yet, so we specify the CA's
+name with -recipient and save any CA certificates that we may receive
+under the ./cacerts directory.
+
+  openssl genrsa -out cl_key.pem
+  openssl cmp -cmd ir -server 127.0.0.1:8080 -path pkix/ -user 1234 -pass password \
+    -recipient "/CN=CMPserver" -newkey cl_key.pem -subject "/CN=MyName" \
+    -cacertsout capubs.pem -certout cl_cert.pem
+
+Then, when the keys for this certificate need to be updated, the client
+can send a key update request. 
+
+  openssl genrsa -out cl_key_new.pem
+  openssl cmp -cmd kur -server 127.0.0.1:8080 -path pkix/ -cert cl_cert.pem \
+    -key cl_key.pem -srvcert capubs.pem -newkey cl_key_new.pem -certout cl_cert_new.pem
+
+=back
+
+=head1 TODO
+
+=over 4
+
+=item * Option for selecting the OpenSSL engine to use.
+
+=item * Option for printing more verbose information.
+
+=item * Receiving a CKUANN using a CMP general message.  Generally: Sending CMP
+general messages for requesting certain information.
+
+=item * Multiple certificate/revocation requests in one session (functionality not yet
+available in the library).
+
+=item * Revocation of other certificates than the one used for signing
+certificates (functionality not yet available in the library).
+
+=item * Message sequences other than IR/CR/KUR/RR (functionality not yet
+available in the library).
+
+=item * Many optionally available settings from the RFC which are not yet
+available in the library and are probably not supported by any available CMP
+server.
+
+=back
+
+=head1 SEE ALSO
+
+L<genrsa(1)|genrsa(1)>, L<gendsa(1)|gendsa(1)>, L<x509v3_config(5)|x509(1)> 
+
+=cut
Index: openssl-1.0.1h-cmp/Configure
===================================================================
--- openssl-1.0.1h-cmp/Configure	(revision 750)
+++ openssl-1.0.1h-cmp/Configure	(working copy)
@@ -56,6 +56,7 @@
 # [no-]zlib     [don't] compile support for zlib compression.
 # zlib-dynamic	Like "zlib", but the zlib library is expected to be a shared
 #		library and will be loaded in run-time by the OpenSSL library.
+# [no-]curl     [don't] use libcurl for HTTP transport in CMP module
 # sctp          include SCTP support
 # 386           generate 80386 code
 # no-sse2	disables IA-32 SSE2 code, above option implies no-sse2
@@ -672,6 +673,7 @@
 my $zlib=1;      # but "no-zlib" is default
 my $no_krb5=0;   # but "no-krb5" is implied unless "--with-krb5-..." is used
 my $no_rfc3779=1; # but "no-rfc3779" is default
+my $curl=1;      # but no-curl is default
 my $no_asm=0;
 my $no_dso=0;
 my $no_gmp=0;
@@ -721,7 +723,8 @@
 		 "shared"         => "default",
 		 "store"	  => "experimental",
 		 "zlib"           => "default",
-		 "zlib-dynamic"   => "default"
+		 "zlib-dynamic"   => "default",
+		 "curl"           => "default"
 	       );
 my @experimental = ();
 
@@ -789,6 +792,7 @@
 		s /^threads$/enable-threads/;
 		s /^zlib$/enable-zlib/;
 		s /^zlib-dynamic$/enable-zlib-dynamic/;
+		s /^curl$/enable-curl/;
 
 		if (/^no-(.+)$/ || /^disable-(.+)$/)
 			{
@@ -916,6 +920,14 @@
 				{
 				$baseaddr="$1";
 				}
+			elsif (/^--with-curl-lib=(.*)$/)
+				{
+				$withargs{"curl-lib"}=$1;
+				}
+			elsif (/^--with-curl-include=(.*)$/)
+				{
+				$withargs{"curl-include"}="-I$1";
+				}
 			elsif (/^--cross-compile-prefix=(.*)$/)
 				{
 				$cross_compile_prefix=$1;
@@ -1066,6 +1078,8 @@
 		{ $no_shared = 1; }
 	elsif (/^zlib$/)
 		{ $zlib = 0; }
+	elsif (/^curl$/)
+		{ $curl = 0; }
 	elsif (/^static-engine$/)
 		{ }
 	elsif (/^zlib-dynamic$/)
@@ -1365,6 +1379,24 @@
 		}
 	}
 
+if ($curl)
+	{
+	$cflags = "-DHAVE_CURL $cflags";
+
+    if (!($cflags =~ m/-DOPENSSL_NO_CMP_CLIENT/)) {
+	    if (defined($withargs{"curl-lib"}))
+	    	{
+	    	$lflags  = "$lflags -L" . $withargs{"curl-lib"};
+	    	}
+	    $lflags .= " -lcurl -lrt "
+    }
+
+	if (defined($withargs{"curl-include"}))
+		{
+		$cflags=$withargs{"curl-include"}." $cflags";
+		}
+	}
+
 # You will find shlib_mark1 and shlib_mark2 explained in Makefile.org
 my $shared_mark = "";
 if ($shared_target eq "")
@@ -1653,6 +1685,8 @@
 	s/^LIBKRB5=.*/LIBKRB5=$withargs{"krb5-lib"}/;
 	s/^LIBZLIB=.*/LIBZLIB=$withargs{"zlib-lib"}/;
 	s/^ZLIB_INCLUDE=.*/ZLIB_INCLUDE=$withargs{"zlib-include"}/;
+	s/^LIBCURL=.*/LIBCURL=$withargs{"curl-lib"}/;
+	s/^CURL_INCLUDE=.*/CURL_INCLUDE=$withargs{"curl-include"}/;
 
 	s/^FIPSDIR=.*/FIPSDIR=$fipsdir/;
 	s/^FIPSLIBDIR=.*/FIPSLIBDIR=$fipslibdir/;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: cmp.patch.gz
Type: application/octet-stream
Size: 175062 bytes
Desc: not available
URL: <http://mta.openssl.org/pipermail/openssl-dev/attachments/20150717/91131a68/attachment-0001.obj>


More information about the openssl-dev mailing list