diff options
author | Wyllys Ingersoll <Wyllys.Ingersoll@Sun.COM> | 2010-06-28 16:04:11 -0700 |
---|---|---|
committer | Wyllys Ingersoll <Wyllys.Ingersoll@Sun.COM> | 2010-06-28 16:04:11 -0700 |
commit | 4f14b0f29aa144cc03efdde5508ae126ae197acf (patch) | |
tree | 5292d99c7ec8374d412d58116e7bbc7279e72067 /usr/src/lib/libkmsagent/common/KMSAgentPKIKeyOpenSSL.cpp | |
parent | 1e49577a7fcde812700ded04431b49d67cc57d6d (diff) | |
download | illumos-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.cpp | 412 |
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; + } +} |