1*12720SWyllys.Ingersoll@Sun.COM /*
2*12720SWyllys.Ingersoll@Sun.COM * CDDL HEADER START
3*12720SWyllys.Ingersoll@Sun.COM *
4*12720SWyllys.Ingersoll@Sun.COM * The contents of this file are subject to the terms of the
5*12720SWyllys.Ingersoll@Sun.COM * Common Development and Distribution License (the "License").
6*12720SWyllys.Ingersoll@Sun.COM * You may not use this file except in compliance with the License.
7*12720SWyllys.Ingersoll@Sun.COM *
8*12720SWyllys.Ingersoll@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12720SWyllys.Ingersoll@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*12720SWyllys.Ingersoll@Sun.COM * See the License for the specific language governing permissions
11*12720SWyllys.Ingersoll@Sun.COM * and limitations under the License.
12*12720SWyllys.Ingersoll@Sun.COM *
13*12720SWyllys.Ingersoll@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*12720SWyllys.Ingersoll@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12720SWyllys.Ingersoll@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*12720SWyllys.Ingersoll@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*12720SWyllys.Ingersoll@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*12720SWyllys.Ingersoll@Sun.COM *
19*12720SWyllys.Ingersoll@Sun.COM * CDDL HEADER END
20*12720SWyllys.Ingersoll@Sun.COM */
21*12720SWyllys.Ingersoll@Sun.COM
22*12720SWyllys.Ingersoll@Sun.COM /*
23*12720SWyllys.Ingersoll@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*12720SWyllys.Ingersoll@Sun.COM */
25*12720SWyllys.Ingersoll@Sun.COM
26*12720SWyllys.Ingersoll@Sun.COM /**
27*12720SWyllys.Ingersoll@Sun.COM * \file KMSAgentPKICert.cpp
28*12720SWyllys.Ingersoll@Sun.COM *
29*12720SWyllys.Ingersoll@Sun.COM * This is an implementation of PKICommon.h CCertificate class.
30*12720SWyllys.Ingersoll@Sun.COM */
31*12720SWyllys.Ingersoll@Sun.COM
32*12720SWyllys.Ingersoll@Sun.COM #include <stdio.h>
33*12720SWyllys.Ingersoll@Sun.COM #include <memory.h>
34*12720SWyllys.Ingersoll@Sun.COM #include <time.h>
35*12720SWyllys.Ingersoll@Sun.COM #include <string.h>
36*12720SWyllys.Ingersoll@Sun.COM
37*12720SWyllys.Ingersoll@Sun.COM #ifdef KMSUSERPKCS12
38*12720SWyllys.Ingersoll@Sun.COM #include <openssl/bio.h>
39*12720SWyllys.Ingersoll@Sun.COM #include <openssl/evp.h>
40*12720SWyllys.Ingersoll@Sun.COM #include <openssl/conf.h>
41*12720SWyllys.Ingersoll@Sun.COM #include <openssl/err.h>
42*12720SWyllys.Ingersoll@Sun.COM #include <openssl/asn1.h>
43*12720SWyllys.Ingersoll@Sun.COM #include <openssl/x509.h>
44*12720SWyllys.Ingersoll@Sun.COM #include <openssl/x509v3.h>
45*12720SWyllys.Ingersoll@Sun.COM #include <openssl/objects.h>
46*12720SWyllys.Ingersoll@Sun.COM #include <openssl/pem.h>
47*12720SWyllys.Ingersoll@Sun.COM #include <openssl/pkcs12.h>
48*12720SWyllys.Ingersoll@Sun.COM #endif
49*12720SWyllys.Ingersoll@Sun.COM
50*12720SWyllys.Ingersoll@Sun.COM #include "SYSCommon.h"
51*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentPKICommon.h"
52*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentPKIimpl.h"
53*12720SWyllys.Ingersoll@Sun.COM
54*12720SWyllys.Ingersoll@Sun.COM /////////////////////////////////////////////////////////////////////////
55*12720SWyllys.Ingersoll@Sun.COM // CCertificate
56*12720SWyllys.Ingersoll@Sun.COM //
CCertificate()57*12720SWyllys.Ingersoll@Sun.COM CCertificate::CCertificate()
58*12720SWyllys.Ingersoll@Sun.COM {
59*12720SWyllys.Ingersoll@Sun.COM m_pCertImpl = InitializeCertImpl();
60*12720SWyllys.Ingersoll@Sun.COM
61*12720SWyllys.Ingersoll@Sun.COM FATAL_ASSERT( m_pCertImpl != NULL );
62*12720SWyllys.Ingersoll@Sun.COM }
63*12720SWyllys.Ingersoll@Sun.COM
64*12720SWyllys.Ingersoll@Sun.COM
~CCertificate()65*12720SWyllys.Ingersoll@Sun.COM CCertificate::~CCertificate()
66*12720SWyllys.Ingersoll@Sun.COM {
67*12720SWyllys.Ingersoll@Sun.COM if ( m_pCertImpl != NULL )
68*12720SWyllys.Ingersoll@Sun.COM {
69*12720SWyllys.Ingersoll@Sun.COM FinalizeCertImpl( m_pCertImpl );
70*12720SWyllys.Ingersoll@Sun.COM }
71*12720SWyllys.Ingersoll@Sun.COM }
72*12720SWyllys.Ingersoll@Sun.COM
73*12720SWyllys.Ingersoll@Sun.COM /**
74*12720SWyllys.Ingersoll@Sun.COM * Save - This OVERLOADED method saves the Cert into a file
75*12720SWyllys.Ingersoll@Sun.COM * @param i_pcFileName - filename of file to save into
76*12720SWyllys.Ingersoll@Sun.COM * @param i_iFormat - IGNORED
77*12720SWyllys.Ingersoll@Sun.COM *
78*12720SWyllys.Ingersoll@Sun.COM * @returns bool - success (true = successful)
79*12720SWyllys.Ingersoll@Sun.COM */
Save(const char * const i_pcFileName,int i_iFormat)80*12720SWyllys.Ingersoll@Sun.COM bool CCertificate::Save( const char * const i_pcFileName,
81*12720SWyllys.Ingersoll@Sun.COM int i_iFormat )
82*12720SWyllys.Ingersoll@Sun.COM {
83*12720SWyllys.Ingersoll@Sun.COM return SaveX509CertTofile( m_pCertImpl, i_pcFileName );
84*12720SWyllys.Ingersoll@Sun.COM }
85*12720SWyllys.Ingersoll@Sun.COM
86*12720SWyllys.Ingersoll@Sun.COM /**
87*12720SWyllys.Ingersoll@Sun.COM * Save - This OVERLOADED method saves the Cert into a buffer
88*12720SWyllys.Ingersoll@Sun.COM * @param i_pcBuffer - buffer to save into
89*12720SWyllys.Ingersoll@Sun.COM * @param i_BufferLength - length of buffer to save
90*12720SWyllys.Ingersoll@Sun.COM * @param o_pActualLength - length of buffer saved
91*12720SWyllys.Ingersoll@Sun.COM * @param i_iFormat - IGNORED
92*12720SWyllys.Ingersoll@Sun.COM *
93*12720SWyllys.Ingersoll@Sun.COM * @returns bool - success (true = successful)
94*12720SWyllys.Ingersoll@Sun.COM */
Save(unsigned char * const i_pcBuffer,int i_iBufferLength,int * const o_pActualLength,int i_iFormat)95*12720SWyllys.Ingersoll@Sun.COM bool CCertificate::Save( unsigned char * const i_pcBuffer,
96*12720SWyllys.Ingersoll@Sun.COM int i_iBufferLength,
97*12720SWyllys.Ingersoll@Sun.COM int * const o_pActualLength,
98*12720SWyllys.Ingersoll@Sun.COM int i_iFormat )
99*12720SWyllys.Ingersoll@Sun.COM {
100*12720SWyllys.Ingersoll@Sun.COM return SaveX509CertToBuffer( m_pCertImpl,
101*12720SWyllys.Ingersoll@Sun.COM i_pcBuffer,
102*12720SWyllys.Ingersoll@Sun.COM i_iBufferLength,
103*12720SWyllys.Ingersoll@Sun.COM o_pActualLength );
104*12720SWyllys.Ingersoll@Sun.COM }
105*12720SWyllys.Ingersoll@Sun.COM
106*12720SWyllys.Ingersoll@Sun.COM /**
107*12720SWyllys.Ingersoll@Sun.COM * Load
108*12720SWyllys.Ingersoll@Sun.COM * This OVERLOADED method loads the Cert from a FILE
109*12720SWyllys.Ingersoll@Sun.COM * @param i_pcFileName - name of file to load from
110*12720SWyllys.Ingersoll@Sun.COM * @param i_iFormat - IGNORED
111*12720SWyllys.Ingersoll@Sun.COM *
112*12720SWyllys.Ingersoll@Sun.COM * @returns bool - success (true = successful)
113*12720SWyllys.Ingersoll@Sun.COM */
114*12720SWyllys.Ingersoll@Sun.COM
Load(const char * const i_pcFileName,int i_iFormat)115*12720SWyllys.Ingersoll@Sun.COM bool CCertificate::Load( const char * const i_pcFileName,
116*12720SWyllys.Ingersoll@Sun.COM int i_iFormat )
117*12720SWyllys.Ingersoll@Sun.COM {
118*12720SWyllys.Ingersoll@Sun.COM return LoadX509CertFromFile( m_pCertImpl, i_pcFileName );
119*12720SWyllys.Ingersoll@Sun.COM }
120*12720SWyllys.Ingersoll@Sun.COM
121*12720SWyllys.Ingersoll@Sun.COM /**
122*12720SWyllys.Ingersoll@Sun.COM * Load
123*12720SWyllys.Ingersoll@Sun.COM * This OVERLOADED method loads the Cert from a buffer
124*12720SWyllys.Ingersoll@Sun.COM * @param i_pcBuffer - buffer to load from
125*12720SWyllys.Ingersoll@Sun.COM * @param i_iLength - amount to load from buffer
126*12720SWyllys.Ingersoll@Sun.COM * @param i_iFormat - IGNORED
127*12720SWyllys.Ingersoll@Sun.COM *
128*12720SWyllys.Ingersoll@Sun.COM * @returns bool - success (true = successful)
129*12720SWyllys.Ingersoll@Sun.COM */
Load(unsigned char * const i_pcBuffer,int i_iLength,int i_iFormat)130*12720SWyllys.Ingersoll@Sun.COM bool CCertificate::Load( unsigned char * const i_pcBuffer,
131*12720SWyllys.Ingersoll@Sun.COM int i_iLength,
132*12720SWyllys.Ingersoll@Sun.COM int i_iFormat )
133*12720SWyllys.Ingersoll@Sun.COM {
134*12720SWyllys.Ingersoll@Sun.COM return LoadX509CertFromBuffer( m_pCertImpl, i_pcBuffer, i_iLength );
135*12720SWyllys.Ingersoll@Sun.COM }
136*12720SWyllys.Ingersoll@Sun.COM
137*12720SWyllys.Ingersoll@Sun.COM /**
138*12720SWyllys.Ingersoll@Sun.COM * Dump
139*12720SWyllys.Ingersoll@Sun.COM * dump the readable format to standard output
140*12720SWyllys.Ingersoll@Sun.COM * @returns bool - success (true = successful)
141*12720SWyllys.Ingersoll@Sun.COM */
Dump()142*12720SWyllys.Ingersoll@Sun.COM bool CCertificate::Dump()
143*12720SWyllys.Ingersoll@Sun.COM {
144*12720SWyllys.Ingersoll@Sun.COM return PrintX509Cert( m_pCertImpl );
145*12720SWyllys.Ingersoll@Sun.COM }
146*12720SWyllys.Ingersoll@Sun.COM
147*12720SWyllys.Ingersoll@Sun.COM #ifdef KMSUSERPKCS12
148*12720SWyllys.Ingersoll@Sun.COM bool
LoadPKCS12CertAndKey(char * filename,int i_iFormat,CPrivateKey * i_pPrivateKey,char * i_pPassphrase)149*12720SWyllys.Ingersoll@Sun.COM CCertificate::LoadPKCS12CertAndKey(
150*12720SWyllys.Ingersoll@Sun.COM char *filename,
151*12720SWyllys.Ingersoll@Sun.COM int i_iFormat,
152*12720SWyllys.Ingersoll@Sun.COM CPrivateKey *i_pPrivateKey,
153*12720SWyllys.Ingersoll@Sun.COM char *i_pPassphrase)
154*12720SWyllys.Ingersoll@Sun.COM {
155*12720SWyllys.Ingersoll@Sun.COM BIO *pFileBio= NULL;
156*12720SWyllys.Ingersoll@Sun.COM X509 *pRequest =NULL;
157*12720SWyllys.Ingersoll@Sun.COM
158*12720SWyllys.Ingersoll@Sun.COM pFileBio = BIO_new(BIO_s_file());
159*12720SWyllys.Ingersoll@Sun.COM if (pFileBio == NULL)
160*12720SWyllys.Ingersoll@Sun.COM return false;
161*12720SWyllys.Ingersoll@Sun.COM if (!BIO_read_filename(pFileBio, filename)) {
162*12720SWyllys.Ingersoll@Sun.COM BIO_free(pFileBio);
163*12720SWyllys.Ingersoll@Sun.COM return (false);
164*12720SWyllys.Ingersoll@Sun.COM }
165*12720SWyllys.Ingersoll@Sun.COM
166*12720SWyllys.Ingersoll@Sun.COM switch( i_iFormat ) {
167*12720SWyllys.Ingersoll@Sun.COM case FILE_FORMAT_DER:
168*12720SWyllys.Ingersoll@Sun.COM
169*12720SWyllys.Ingersoll@Sun.COM pRequest=d2i_X509_bio(pFileBio, NULL);
170*12720SWyllys.Ingersoll@Sun.COM if (pRequest == NULL) {
171*12720SWyllys.Ingersoll@Sun.COM // fixme: log: invalid certificate format
172*12720SWyllys.Ingersoll@Sun.COM return false;
173*12720SWyllys.Ingersoll@Sun.COM }
174*12720SWyllys.Ingersoll@Sun.COM break;
175*12720SWyllys.Ingersoll@Sun.COM
176*12720SWyllys.Ingersoll@Sun.COM case FILE_FORMAT_PEM:
177*12720SWyllys.Ingersoll@Sun.COM
178*12720SWyllys.Ingersoll@Sun.COM pRequest=PEM_read_bio_X509(pFileBio, NULL, NULL, NULL);
179*12720SWyllys.Ingersoll@Sun.COM if (pRequest == NULL) {
180*12720SWyllys.Ingersoll@Sun.COM // fixme: log: invalid certificate format
181*12720SWyllys.Ingersoll@Sun.COM return false;
182*12720SWyllys.Ingersoll@Sun.COM }
183*12720SWyllys.Ingersoll@Sun.COM break;
184*12720SWyllys.Ingersoll@Sun.COM
185*12720SWyllys.Ingersoll@Sun.COM case FILE_FORMAT_PKCS12:
186*12720SWyllys.Ingersoll@Sun.COM PKCS12* pPKCS12Request = d2i_PKCS12_bio(pFileBio, NULL);
187*12720SWyllys.Ingersoll@Sun.COM if (pPKCS12Request == NULL) {
188*12720SWyllys.Ingersoll@Sun.COM // fixme: log: invalid certificate format
189*12720SWyllys.Ingersoll@Sun.COM return false;
190*12720SWyllys.Ingersoll@Sun.COM }
191*12720SWyllys.Ingersoll@Sun.COM
192*12720SWyllys.Ingersoll@Sun.COM // convert PKCS12 to X509
193*12720SWyllys.Ingersoll@Sun.COM EVP_PKEY *pKeyTemp = NULL;
194*12720SWyllys.Ingersoll@Sun.COM if (!PKCS12_parse(pPKCS12Request, i_pPassphrase,
195*12720SWyllys.Ingersoll@Sun.COM &pKeyTemp, &pRequest, NULL)) {
196*12720SWyllys.Ingersoll@Sun.COM // fixme: log: invalid certificate format or passphrase
197*12720SWyllys.Ingersoll@Sun.COM PKCS12_free(pPKCS12Request);
198*12720SWyllys.Ingersoll@Sun.COM return false;
199*12720SWyllys.Ingersoll@Sun.COM }
200*12720SWyllys.Ingersoll@Sun.COM
201*12720SWyllys.Ingersoll@Sun.COM if (pKeyTemp && i_pPrivateKey) {
202*12720SWyllys.Ingersoll@Sun.COM i_pPrivateKey->SetNative((void *)pKeyTemp);
203*12720SWyllys.Ingersoll@Sun.COM } else if (pKeyTemp)
204*12720SWyllys.Ingersoll@Sun.COM EVP_PKEY_free(pKeyTemp);
205*12720SWyllys.Ingersoll@Sun.COM
206*12720SWyllys.Ingersoll@Sun.COM PKCS12_free(pPKCS12Request);
207*12720SWyllys.Ingersoll@Sun.COM break;
208*12720SWyllys.Ingersoll@Sun.COM }
209*12720SWyllys.Ingersoll@Sun.COM if (pRequest != NULL) {
210*12720SWyllys.Ingersoll@Sun.COM SetCert(m_pCertImpl, (void *)pRequest);
211*12720SWyllys.Ingersoll@Sun.COM }
212*12720SWyllys.Ingersoll@Sun.COM
213*12720SWyllys.Ingersoll@Sun.COM return (true);
214*12720SWyllys.Ingersoll@Sun.COM }
215*12720SWyllys.Ingersoll@Sun.COM
216*12720SWyllys.Ingersoll@Sun.COM void *
SaveCertToPKCS12MemoryBIO(CPrivateKey * i_pPrivateKey,char * i_sPassphrase)217*12720SWyllys.Ingersoll@Sun.COM CCertificate::SaveCertToPKCS12MemoryBIO(
218*12720SWyllys.Ingersoll@Sun.COM CPrivateKey* i_pPrivateKey,
219*12720SWyllys.Ingersoll@Sun.COM char *i_sPassphrase)
220*12720SWyllys.Ingersoll@Sun.COM {
221*12720SWyllys.Ingersoll@Sun.COM BIO *pMemBio = NULL;
222*12720SWyllys.Ingersoll@Sun.COM int iReturn;
223*12720SWyllys.Ingersoll@Sun.COM
224*12720SWyllys.Ingersoll@Sun.COM // create memory BIO
225*12720SWyllys.Ingersoll@Sun.COM pMemBio = BIO_new(BIO_s_mem());
226*12720SWyllys.Ingersoll@Sun.COM
227*12720SWyllys.Ingersoll@Sun.COM if(pMemBio == NULL)
228*12720SWyllys.Ingersoll@Sun.COM {
229*12720SWyllys.Ingersoll@Sun.COM //fixme: log -- no memory
230*12720SWyllys.Ingersoll@Sun.COM return NULL;
231*12720SWyllys.Ingersoll@Sun.COM }
232*12720SWyllys.Ingersoll@Sun.COM
233*12720SWyllys.Ingersoll@Sun.COM PKCS12 *p12 = PKCS12_create(i_sPassphrase,
234*12720SWyllys.Ingersoll@Sun.COM NULL,
235*12720SWyllys.Ingersoll@Sun.COM (EVP_PKEY *)i_pPrivateKey->GetNative(),
236*12720SWyllys.Ingersoll@Sun.COM (X509 *)GetCert(m_pCertImpl),
237*12720SWyllys.Ingersoll@Sun.COM NULL,
238*12720SWyllys.Ingersoll@Sun.COM 0,
239*12720SWyllys.Ingersoll@Sun.COM 0,
240*12720SWyllys.Ingersoll@Sun.COM 0,
241*12720SWyllys.Ingersoll@Sun.COM 0,
242*12720SWyllys.Ingersoll@Sun.COM 0);
243*12720SWyllys.Ingersoll@Sun.COM if ( ! p12 )
244*12720SWyllys.Ingersoll@Sun.COM {
245*12720SWyllys.Ingersoll@Sun.COM return NULL;
246*12720SWyllys.Ingersoll@Sun.COM }
247*12720SWyllys.Ingersoll@Sun.COM
248*12720SWyllys.Ingersoll@Sun.COM // now pMemBIO != NULL, remember to free it before exiting
249*12720SWyllys.Ingersoll@Sun.COM iReturn = i2d_PKCS12_bio(pMemBio, p12);
250*12720SWyllys.Ingersoll@Sun.COM
251*12720SWyllys.Ingersoll@Sun.COM if(!iReturn) // return 0: means error occurs
252*12720SWyllys.Ingersoll@Sun.COM {
253*12720SWyllys.Ingersoll@Sun.COM //fixme: log -- could not export private key
254*12720SWyllys.Ingersoll@Sun.COM BIO_free(pMemBio);
255*12720SWyllys.Ingersoll@Sun.COM return NULL;
256*12720SWyllys.Ingersoll@Sun.COM }
257*12720SWyllys.Ingersoll@Sun.COM
258*12720SWyllys.Ingersoll@Sun.COM return (void *)pMemBio;
259*12720SWyllys.Ingersoll@Sun.COM }
260*12720SWyllys.Ingersoll@Sun.COM
261*12720SWyllys.Ingersoll@Sun.COM bool
SavePKCS12(unsigned char * i_pcBuffer,int i_iBufferLength,int * o_pActualLength,CPrivateKey * i_pPrivateKey,char * i_sPassphrase)262*12720SWyllys.Ingersoll@Sun.COM CCertificate::SavePKCS12(
263*12720SWyllys.Ingersoll@Sun.COM unsigned char *i_pcBuffer,
264*12720SWyllys.Ingersoll@Sun.COM int i_iBufferLength,
265*12720SWyllys.Ingersoll@Sun.COM int *o_pActualLength,
266*12720SWyllys.Ingersoll@Sun.COM CPrivateKey* i_pPrivateKey,
267*12720SWyllys.Ingersoll@Sun.COM char* i_sPassphrase )
268*12720SWyllys.Ingersoll@Sun.COM {
269*12720SWyllys.Ingersoll@Sun.COM BIO *pMemBio = NULL;
270*12720SWyllys.Ingersoll@Sun.COM char *pData = NULL;
271*12720SWyllys.Ingersoll@Sun.COM int iLength;
272*12720SWyllys.Ingersoll@Sun.COM
273*12720SWyllys.Ingersoll@Sun.COM // sanity check
274*12720SWyllys.Ingersoll@Sun.COM if(i_pcBuffer == NULL) return false;
275*12720SWyllys.Ingersoll@Sun.COM if(i_iBufferLength <= 0) return false;
276*12720SWyllys.Ingersoll@Sun.COM if(o_pActualLength == NULL) return false;
277*12720SWyllys.Ingersoll@Sun.COM
278*12720SWyllys.Ingersoll@Sun.COM // create memory BIO
279*12720SWyllys.Ingersoll@Sun.COM pMemBio = (BIO *)SaveCertToPKCS12MemoryBIO(i_pPrivateKey, i_sPassphrase);
280*12720SWyllys.Ingersoll@Sun.COM
281*12720SWyllys.Ingersoll@Sun.COM if(pMemBio == NULL)
282*12720SWyllys.Ingersoll@Sun.COM {
283*12720SWyllys.Ingersoll@Sun.COM //fixme: log -- no memory
284*12720SWyllys.Ingersoll@Sun.COM return false;
285*12720SWyllys.Ingersoll@Sun.COM }
286*12720SWyllys.Ingersoll@Sun.COM
287*12720SWyllys.Ingersoll@Sun.COM iLength = BIO_get_mem_data(pMemBio, &pData);
288*12720SWyllys.Ingersoll@Sun.COM
289*12720SWyllys.Ingersoll@Sun.COM // If the output buffer is a string, it needs to be NULL terminated
290*12720SWyllys.Ingersoll@Sun.COM // So always append a NULL to the output
291*12720SWyllys.Ingersoll@Sun.COM if(iLength + 1 > i_iBufferLength)
292*12720SWyllys.Ingersoll@Sun.COM {
293*12720SWyllys.Ingersoll@Sun.COM //fixme: log -- buffer too small
294*12720SWyllys.Ingersoll@Sun.COM BIO_free(pMemBio);
295*12720SWyllys.Ingersoll@Sun.COM return false;
296*12720SWyllys.Ingersoll@Sun.COM }
297*12720SWyllys.Ingersoll@Sun.COM // copy the data to given buffer
298*12720SWyllys.Ingersoll@Sun.COM memcpy(i_pcBuffer, pData, iLength);
299*12720SWyllys.Ingersoll@Sun.COM // NULL terminate the string
300*12720SWyllys.Ingersoll@Sun.COM i_pcBuffer[iLength] = '\0';
301*12720SWyllys.Ingersoll@Sun.COM *o_pActualLength = iLength;
302*12720SWyllys.Ingersoll@Sun.COM
303*12720SWyllys.Ingersoll@Sun.COM // free memory
304*12720SWyllys.Ingersoll@Sun.COM BIO_free(pMemBio);
305*12720SWyllys.Ingersoll@Sun.COM
306*12720SWyllys.Ingersoll@Sun.COM return true;
307*12720SWyllys.Ingersoll@Sun.COM }
308*12720SWyllys.Ingersoll@Sun.COM #endif /* PKCS12 */
309