Mercurial > illumos > illumos-gate
view usr/src/lib/libkmsagent/common/KMSAgentPKICert.cpp @ 12720:3db6e0082404
PSARC 2010/195 PKCS11 KMS Provider
6944296 Solaris needs a PKCS#11 provider to allow access to KMS keystore functionality
author | Wyllys Ingersoll <Wyllys.Ingersoll@Sun.COM> |
---|---|
date | Mon, 28 Jun 2010 16:04:11 -0700 |
parents | |
children |
line wrap: on
line source
/* * 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 KMSAgentPKICert.cpp * * This is an implementation of PKICommon.h CCertificate class. */ #include <stdio.h> #include <memory.h> #include <time.h> #include <string.h> #ifdef KMSUSERPKCS12 #include <openssl/bio.h> #include <openssl/evp.h> #include <openssl/conf.h> #include <openssl/err.h> #include <openssl/asn1.h> #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/objects.h> #include <openssl/pem.h> #include <openssl/pkcs12.h> #endif #include "SYSCommon.h" #include "KMSAgentPKICommon.h" #include "KMSAgentPKIimpl.h" ///////////////////////////////////////////////////////////////////////// // CCertificate // CCertificate::CCertificate() { m_pCertImpl = InitializeCertImpl(); FATAL_ASSERT( m_pCertImpl != NULL ); } CCertificate::~CCertificate() { if ( m_pCertImpl != NULL ) { FinalizeCertImpl( m_pCertImpl ); } } /** * Save - This OVERLOADED method saves the Cert into a file * @param i_pcFileName - filename of file to save into * @param i_iFormat - IGNORED * * @returns bool - success (true = successful) */ bool CCertificate::Save( const char * const i_pcFileName, int i_iFormat ) { return SaveX509CertTofile( m_pCertImpl, i_pcFileName ); } /** * Save - This OVERLOADED method saves the Cert into a buffer * @param i_pcBuffer - buffer to save into * @param i_BufferLength - length of buffer to save * @param o_pActualLength - length of buffer saved * @param i_iFormat - IGNORED * * @returns bool - success (true = successful) */ bool CCertificate::Save( unsigned char * const i_pcBuffer, int i_iBufferLength, int * const o_pActualLength, int i_iFormat ) { return SaveX509CertToBuffer( m_pCertImpl, i_pcBuffer, i_iBufferLength, o_pActualLength ); } /** * Load * This OVERLOADED method loads the Cert from a FILE * @param i_pcFileName - name of file to load from * @param i_iFormat - IGNORED * * @returns bool - success (true = successful) */ bool CCertificate::Load( const char * const i_pcFileName, int i_iFormat ) { return LoadX509CertFromFile( m_pCertImpl, i_pcFileName ); } /** * Load * This OVERLOADED method loads the Cert from a buffer * @param i_pcBuffer - buffer to load from * @param i_iLength - amount to load from buffer * @param i_iFormat - IGNORED * * @returns bool - success (true = successful) */ bool CCertificate::Load( unsigned char * const i_pcBuffer, int i_iLength, int i_iFormat ) { return LoadX509CertFromBuffer( m_pCertImpl, i_pcBuffer, i_iLength ); } /** * Dump * dump the readable format to standard output * @returns bool - success (true = successful) */ bool CCertificate::Dump() { return PrintX509Cert( m_pCertImpl ); } #ifdef KMSUSERPKCS12 bool CCertificate::LoadPKCS12CertAndKey( char *filename, int i_iFormat, CPrivateKey *i_pPrivateKey, char *i_pPassphrase) { BIO *pFileBio= NULL; X509 *pRequest =NULL; pFileBio = BIO_new(BIO_s_file()); if (pFileBio == NULL) return false; if (!BIO_read_filename(pFileBio, filename)) { BIO_free(pFileBio); return (false); } switch( i_iFormat ) { case FILE_FORMAT_DER: pRequest=d2i_X509_bio(pFileBio, NULL); if (pRequest == NULL) { // fixme: log: invalid certificate format return false; } break; case FILE_FORMAT_PEM: pRequest=PEM_read_bio_X509(pFileBio, NULL, NULL, NULL); if (pRequest == NULL) { // fixme: log: invalid certificate format return false; } break; case FILE_FORMAT_PKCS12: PKCS12* pPKCS12Request = d2i_PKCS12_bio(pFileBio, NULL); if (pPKCS12Request == NULL) { // fixme: log: invalid certificate format return false; } // convert PKCS12 to X509 EVP_PKEY *pKeyTemp = NULL; if (!PKCS12_parse(pPKCS12Request, i_pPassphrase, &pKeyTemp, &pRequest, NULL)) { // fixme: log: invalid certificate format or passphrase PKCS12_free(pPKCS12Request); return false; } if (pKeyTemp && i_pPrivateKey) { i_pPrivateKey->SetNative((void *)pKeyTemp); } else if (pKeyTemp) EVP_PKEY_free(pKeyTemp); PKCS12_free(pPKCS12Request); break; } if (pRequest != NULL) { SetCert(m_pCertImpl, (void *)pRequest); } return (true); } void * CCertificate::SaveCertToPKCS12MemoryBIO( CPrivateKey* i_pPrivateKey, char *i_sPassphrase) { BIO *pMemBio = NULL; int iReturn; // create memory BIO pMemBio = BIO_new(BIO_s_mem()); if(pMemBio == NULL) { //fixme: log -- no memory return NULL; } PKCS12 *p12 = PKCS12_create(i_sPassphrase, NULL, (EVP_PKEY *)i_pPrivateKey->GetNative(), (X509 *)GetCert(m_pCertImpl), NULL, 0, 0, 0, 0, 0); if ( ! p12 ) { return NULL; } // now pMemBIO != NULL, remember to free it before exiting iReturn = i2d_PKCS12_bio(pMemBio, p12); if(!iReturn) // return 0: means error occurs { //fixme: log -- could not export private key BIO_free(pMemBio); return NULL; } return (void *)pMemBio; } bool CCertificate::SavePKCS12( unsigned char *i_pcBuffer, int i_iBufferLength, int *o_pActualLength, CPrivateKey* i_pPrivateKey, char* i_sPassphrase ) { BIO *pMemBio = NULL; char *pData = NULL; int iLength; // sanity check if(i_pcBuffer == NULL) return false; if(i_iBufferLength <= 0) return false; if(o_pActualLength == NULL) return false; // create memory BIO pMemBio = (BIO *)SaveCertToPKCS12MemoryBIO(i_pPrivateKey, i_sPassphrase); 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; } #endif /* PKCS12 */