summaryrefslogtreecommitdiff
path: root/usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp
diff options
context:
space:
mode:
authorWyllys Ingersoll <Wyllys.Ingersoll@Sun.COM>2010-06-28 16:04:11 -0700
committerWyllys Ingersoll <Wyllys.Ingersoll@Sun.COM>2010-06-28 16:04:11 -0700
commit4f14b0f29aa144cc03efdde5508ae126ae197acf (patch)
tree5292d99c7ec8374d412d58116e7bbc7279e72067 /usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp
parent1e49577a7fcde812700ded04431b49d67cc57d6d (diff)
downloadillumos-gate-4f14b0f29aa144cc03efdde5508ae126ae197acf.tar.gz
PSARC 2010/195 PKCS11 KMS Provider
6944296 Solaris needs a PKCS#11 provider to allow access to KMS keystore functionality
Diffstat (limited to 'usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp')
-rw-r--r--usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp412
1 files changed, 412 insertions, 0 deletions
diff --git a/usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp b/usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp
new file mode 100644
index 0000000000..d66f185296
--- /dev/null
+++ b/usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp
@@ -0,0 +1,412 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/**
+ * \file KMSAgentPKIKeyOpenSSL.cpp
+ */
+
+#include <stdio.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+#include "SYSCommon.h"
+#include "KMSAgentPKIimpl.h"
+
+typedef struct PKeyControl
+{
+ EVP_PKEY* pPKey;
+} PKeyControl;
+
+void * InitializePKeyImpl()
+{
+ PKeyControl *pPKeyControl =
+ (PKeyControl *) malloc(sizeof(PKeyControl));
+
+ if ( pPKeyControl != NULL )
+ {
+ pPKeyControl->pPKey = NULL;
+ }
+
+ return pPKeyControl;
+}
+
+void FinalizePKeyImpl( void * i_pPKeyImpl )
+{
+ if ( i_pPKeyImpl != NULL )
+ {
+ free(i_pPKeyImpl);
+ }
+}
+
+#ifdef KMSUSERPKCS12
+void *GetPKey(void *i_pPKeyImpl) {
+ PKeyControl* pPKeyControl = (PKeyControl*) i_pPKeyImpl;
+ return ((void *)pPKeyControl->pPKey);
+}
+
+void SetPKey(void *i_pPKeyImpl, void *pKey) {
+ PKeyControl* pPKeyControl = (PKeyControl*) i_pPKeyImpl;
+ pPKeyControl->pPKey = (EVP_PKEY *)pKey;
+ return;
+}
+#endif
+
+/**
+ * export the private key to a memory BIO, if error, return NULL
+ */
+BIO* SavePrivateKeyToMemoryBIO(PKeyControl* const i_pPKeyControl,
+ const char * const i_pPassphrase)
+{
+ BIO *pMemBio = NULL;
+ const EVP_CIPHER *pCipher = NULL;
+ int iReturn;
+
+ // set cipher, if passphrase is not empty
+ if(i_pPassphrase != NULL)
+ {
+ pCipher= EVP_des_ede3_cbc(); //NULL means no password protection
+ }
+
+ // create memory BIO
+ pMemBio = BIO_new(BIO_s_mem());
+
+ if(pMemBio == NULL)
+ {
+ //fixme: log -- no memory
+ return NULL;
+ }
+
+ iReturn = PEM_write_bio_PrivateKey
+ (pMemBio,
+ i_pPKeyControl->pPKey,
+ pCipher,
+ NULL,0,NULL, (char*) i_pPassphrase);
+
+ if(!iReturn) // return 0: means error occurs
+ {
+ //fixme: log -- could not export private key
+ BIO_free(pMemBio);
+ return NULL;
+ }
+
+ return pMemBio;
+}
+
+bool SavePrivateKeyToBuffer(
+ void * const i_pPKeyImpl,
+ unsigned char * const i_pcBuffer,
+ int i_iBufferLength,
+ int * const o_pActualLength,
+ const char * const i_pPassphrase,
+ int i_iFormat)
+{
+ PKeyControl* pPKeyControl = (PKeyControl*) i_pPKeyImpl;
+
+ FATAL_ASSERT( pPKeyControl &&
+ i_pcBuffer &&
+ i_iBufferLength > 0 &&
+ o_pActualLength );
+
+ BIO *pMemBio = NULL;
+ char *pData = NULL;
+ int iLength;
+
+ // create memory BIO
+ pMemBio = SavePrivateKeyToMemoryBIO( pPKeyControl, i_pPassphrase );
+
+ if(pMemBio == NULL)
+ {
+ //fixme: log -- no memory
+ return false;
+ }
+
+ iLength = BIO_get_mem_data(pMemBio, &pData);
+
+ // If the output buffer is a string, it needs to be NULL terminated
+ // So always append a NULL to the output
+ if(iLength + 1 > i_iBufferLength)
+ {
+ //fixme: log -- buffer too small
+ BIO_free(pMemBio);
+ return false;
+ }
+ // copy the data to given buffer
+ memcpy(i_pcBuffer, pData, iLength);
+ // NULL terminate the string
+ i_pcBuffer[iLength] = '\0';
+ *o_pActualLength = iLength;
+
+ // free memory
+ BIO_free(pMemBio);
+
+ return true;
+}
+
+/**
+ * import the private key from a BIO, if error, return NULL
+ */
+bool LoadPrivateKeyFromBIO(PKeyControl* const io_pPKeyControl,
+ BIO *i_pBio,
+ char *i_pPassphrase )
+{
+ if (io_pPKeyControl == NULL)
+ {
+ return false;
+ }
+
+ EVP_PKEY *pKey = NULL;
+
+ if(i_pBio == NULL)
+ {
+ return false;
+ }
+
+ if ( io_pPKeyControl != NULL && io_pPKeyControl->pPKey != NULL )
+ {
+ return false; // do not allow overwrite
+ }
+
+ pKey=PEM_read_bio_PrivateKey(i_pBio,NULL,NULL,i_pPassphrase);
+ if (pKey == NULL)
+ {
+ // fixme: log: invalid private key format or passphrase
+ return false;
+ }
+
+ io_pPKeyControl->pPKey = pKey;
+
+ return true;
+}
+
+bool LoadPrivateKeyFromBuffer(
+ void * const i_pPKeyImpl,
+ unsigned char * i_pcBuffer,
+ int i_iLength,
+ const char * const i_pPassphrase,
+ int i_iFormat)
+{
+ PKeyControl* const pPKeyControl = (PKeyControl*) i_pPKeyImpl;
+
+ FATAL_ASSERT( i_pPKeyImpl && i_pcBuffer );
+
+ bool bReturn;
+ BIO *pMemBio;
+ // create a mem bio from the given buffer
+ // Note that BIO_new_mem_buf() creates a BIO which never
+ // destroy the memory attached to it.
+ pMemBio = BIO_new_mem_buf(i_pcBuffer, i_iLength);
+ if (pMemBio == NULL)
+ {
+ //fixme: log -- no memory
+ return false;
+ }
+ bReturn = LoadPrivateKeyFromBIO( pPKeyControl,
+ pMemBio, (char *)i_pPassphrase );
+
+ BIO_free(pMemBio);
+
+ return bReturn;
+}
+
+/**
+ * export the public key to a memory BIO, if error, return NULL
+ */
+BIO* SavePublicKeyToMemoryBIO(PKeyControl* const i_pPublicKeyControl )
+{
+ BIO *pMemBio = NULL;
+
+ int iReturn;
+
+ // create memory BIO
+ pMemBio = BIO_new(BIO_s_mem());
+
+ if(pMemBio == NULL)
+ {
+ //fixme: log -- no memory
+ return NULL;
+ }
+
+ iReturn = PEM_write_bio_PUBKEY(pMemBio,
+ i_pPublicKeyControl->pPKey );
+
+ if(!iReturn) // return 0: means error occurs
+ {
+ //fixme: log -- could not export private key
+ BIO_free(pMemBio);
+ return NULL;
+ }
+
+ return pMemBio;
+}
+
+bool SavePublicKeyToBuffer(
+ void * const i_pPKeyImpl,
+ unsigned char * const i_pcBuffer,
+ int i_iBufferLength,
+ int * const o_pActualLength,
+ int i_iFormat)
+{
+ PKeyControl* pPublicKeyControl = (PKeyControl*) i_pPKeyImpl;
+
+ FATAL_ASSERT( pPublicKeyControl &&
+ i_pcBuffer &&
+ i_iBufferLength > 0 &&
+ o_pActualLength );
+
+ BIO *pMemBio = NULL;
+ char *pData = NULL;
+ int iLength;
+
+ // create memory BIO
+ pMemBio = SavePublicKeyToMemoryBIO( pPublicKeyControl );
+
+ if(pMemBio == NULL)
+ {
+ return false;
+ }
+
+ iLength = BIO_get_mem_data(pMemBio, &pData);
+
+ // If the output buffer is a string, it needs to be NULL terminated
+ // So always append a NULL to the output
+ if(iLength + 1 > i_iBufferLength)
+ {
+ BIO_free(pMemBio);
+ return false;
+ }
+ // copy the data to given buffer
+ memcpy(i_pcBuffer, pData, iLength);
+ // NULL terminate the string
+ i_pcBuffer[iLength] = '\0';
+ *o_pActualLength = iLength;
+
+ // free memory
+ BIO_free(pMemBio);
+
+ return true;
+}
+
+/**
+ * import the public key from a BIO, if error, return NULL
+ */
+bool LoadPublicKeyFromBIO(PKeyControl* const io_pPublicKeyControl,
+ BIO *i_pBio )
+{
+ EVP_PKEY *pKey = NULL;
+
+ if(io_pPublicKeyControl == NULL)
+ {
+ return false;
+ }
+
+ if(i_pBio == NULL)
+ {
+ return false;
+ }
+
+ if ( io_pPublicKeyControl != NULL && io_pPublicKeyControl->pPKey != NULL )
+ {
+ return false; // do not allow overwrite
+ }
+
+ pKey = PEM_read_bio_PUBKEY(i_pBio, NULL, NULL, NULL);
+ if (pKey == NULL)
+ {
+ // fixme: log: invalid public key format or passphrase
+ return false;
+ }
+
+ io_pPublicKeyControl->pPKey = pKey;
+
+ return true;
+}
+
+bool LoadPublicKeyFromBuffer(
+ void * const i_pPublicKeyImpl,
+ unsigned char * i_pcBuffer,
+ int i_iLength,
+ int i_iFormat)
+{
+ PKeyControl* const pPublicKeyControl = (PKeyControl*) i_pPublicKeyImpl;
+
+ FATAL_ASSERT( i_pPublicKeyImpl && i_pcBuffer );
+
+ bool bReturn;
+ BIO *pMemBio;
+ // create a mem bio from the given buffer
+ // Note that BIO_new_mem_buf() creates a BIO which never
+ // destroy the memory attached to it.
+ pMemBio = BIO_new_mem_buf(i_pcBuffer, i_iLength);
+ if (pMemBio == NULL)
+ {
+ //fixme: log -- no memory
+ return false;
+ }
+ bReturn = LoadPublicKeyFromBIO( pPublicKeyControl,
+ pMemBio );
+
+ BIO_free(pMemBio);
+
+ return bReturn;
+}
+
+bool PublicKeyEncrypt (int i_iLength,
+ const unsigned char * const i_pcPlainText,
+ unsigned char * const o_pcCypherText,
+ int * const o_pActualLength,
+ void * pPKeyControl )
+{
+ FATAL_ASSERT( i_pcPlainText );
+ FATAL_ASSERT( o_pcCypherText );
+ FATAL_ASSERT( o_pActualLength );
+ FATAL_ASSERT( pPKeyControl );
+
+ PKeyControl *pKeyControl = (PKeyControl *)pPKeyControl;
+ EVP_PKEY * pEVP_PKEY = pKeyControl->pPKey;
+ RSA * pRSAPublicKey = pEVP_PKEY->pkey.rsa;
+
+//#if defined(DEBUG)
+// RSA_print_fp(stdout, pRSAPublicKey, 0);
+// printf("PublicKeyEncrypt(): RSA_size()=%d, cyphertextLen=%d\n",
+// RSA_size(pRSAPublicKey),
+// i_iLength);
+//#endif
+
+ *o_pActualLength = RSA_public_encrypt(i_iLength,
+ i_pcPlainText,
+ o_pcCypherText,
+ pRSAPublicKey,
+ RSA_PKCS1_PADDING);
+
+ if ( *o_pActualLength < 0 )
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}