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 KMSAgentPKIKeyOpenSSL.cpp
28*12720SWyllys.Ingersoll@Sun.COM  */
29*12720SWyllys.Ingersoll@Sun.COM 
30*12720SWyllys.Ingersoll@Sun.COM #include <stdio.h>
31*12720SWyllys.Ingersoll@Sun.COM #include <openssl/bio.h>
32*12720SWyllys.Ingersoll@Sun.COM #include <openssl/pem.h>
33*12720SWyllys.Ingersoll@Sun.COM #include <openssl/rsa.h>
34*12720SWyllys.Ingersoll@Sun.COM 
35*12720SWyllys.Ingersoll@Sun.COM #include "SYSCommon.h"
36*12720SWyllys.Ingersoll@Sun.COM #include "KMSAgentPKIimpl.h"
37*12720SWyllys.Ingersoll@Sun.COM 
38*12720SWyllys.Ingersoll@Sun.COM typedef struct PKeyControl
39*12720SWyllys.Ingersoll@Sun.COM {
40*12720SWyllys.Ingersoll@Sun.COM     EVP_PKEY*   pPKey;
41*12720SWyllys.Ingersoll@Sun.COM } PKeyControl;
42*12720SWyllys.Ingersoll@Sun.COM 
InitializePKeyImpl()43*12720SWyllys.Ingersoll@Sun.COM void * InitializePKeyImpl()
44*12720SWyllys.Ingersoll@Sun.COM {
45*12720SWyllys.Ingersoll@Sun.COM     PKeyControl *pPKeyControl =
46*12720SWyllys.Ingersoll@Sun.COM        (PKeyControl *) malloc(sizeof(PKeyControl));
47*12720SWyllys.Ingersoll@Sun.COM 
48*12720SWyllys.Ingersoll@Sun.COM     if ( pPKeyControl != NULL )
49*12720SWyllys.Ingersoll@Sun.COM     {
50*12720SWyllys.Ingersoll@Sun.COM         pPKeyControl->pPKey = NULL;
51*12720SWyllys.Ingersoll@Sun.COM     }
52*12720SWyllys.Ingersoll@Sun.COM 
53*12720SWyllys.Ingersoll@Sun.COM     return pPKeyControl;
54*12720SWyllys.Ingersoll@Sun.COM }
55*12720SWyllys.Ingersoll@Sun.COM 
FinalizePKeyImpl(void * i_pPKeyImpl)56*12720SWyllys.Ingersoll@Sun.COM void FinalizePKeyImpl( void * i_pPKeyImpl )
57*12720SWyllys.Ingersoll@Sun.COM {
58*12720SWyllys.Ingersoll@Sun.COM     if ( i_pPKeyImpl != NULL )
59*12720SWyllys.Ingersoll@Sun.COM     {
60*12720SWyllys.Ingersoll@Sun.COM         free(i_pPKeyImpl);
61*12720SWyllys.Ingersoll@Sun.COM     }
62*12720SWyllys.Ingersoll@Sun.COM }
63*12720SWyllys.Ingersoll@Sun.COM 
64*12720SWyllys.Ingersoll@Sun.COM #ifdef KMSUSERPKCS12
GetPKey(void * i_pPKeyImpl)65*12720SWyllys.Ingersoll@Sun.COM void *GetPKey(void *i_pPKeyImpl) {
66*12720SWyllys.Ingersoll@Sun.COM 	PKeyControl* pPKeyControl = (PKeyControl*) i_pPKeyImpl;
67*12720SWyllys.Ingersoll@Sun.COM 	return ((void *)pPKeyControl->pPKey);
68*12720SWyllys.Ingersoll@Sun.COM }
69*12720SWyllys.Ingersoll@Sun.COM 
SetPKey(void * i_pPKeyImpl,void * pKey)70*12720SWyllys.Ingersoll@Sun.COM void SetPKey(void *i_pPKeyImpl, void *pKey) {
71*12720SWyllys.Ingersoll@Sun.COM 	PKeyControl* pPKeyControl = (PKeyControl*) i_pPKeyImpl;
72*12720SWyllys.Ingersoll@Sun.COM 	pPKeyControl->pPKey = (EVP_PKEY *)pKey;
73*12720SWyllys.Ingersoll@Sun.COM 	return;
74*12720SWyllys.Ingersoll@Sun.COM }
75*12720SWyllys.Ingersoll@Sun.COM #endif
76*12720SWyllys.Ingersoll@Sun.COM 
77*12720SWyllys.Ingersoll@Sun.COM /**
78*12720SWyllys.Ingersoll@Sun.COM  * export the private key to a memory BIO, if error, return NULL
79*12720SWyllys.Ingersoll@Sun.COM  */
SavePrivateKeyToMemoryBIO(PKeyControl * const i_pPKeyControl,const char * const i_pPassphrase)80*12720SWyllys.Ingersoll@Sun.COM BIO* SavePrivateKeyToMemoryBIO(PKeyControl* const i_pPKeyControl,
81*12720SWyllys.Ingersoll@Sun.COM                                const char * const i_pPassphrase)
82*12720SWyllys.Ingersoll@Sun.COM {
83*12720SWyllys.Ingersoll@Sun.COM    BIO *pMemBio = NULL;
84*12720SWyllys.Ingersoll@Sun.COM    const EVP_CIPHER *pCipher = NULL;
85*12720SWyllys.Ingersoll@Sun.COM    int iReturn;
86*12720SWyllys.Ingersoll@Sun.COM 
87*12720SWyllys.Ingersoll@Sun.COM    // set cipher, if passphrase is not empty
88*12720SWyllys.Ingersoll@Sun.COM    if(i_pPassphrase != NULL)
89*12720SWyllys.Ingersoll@Sun.COM    {
90*12720SWyllys.Ingersoll@Sun.COM       pCipher= EVP_des_ede3_cbc(); //NULL means no password protection
91*12720SWyllys.Ingersoll@Sun.COM    }
92*12720SWyllys.Ingersoll@Sun.COM 
93*12720SWyllys.Ingersoll@Sun.COM    // create memory BIO
94*12720SWyllys.Ingersoll@Sun.COM    pMemBio = BIO_new(BIO_s_mem());
95*12720SWyllys.Ingersoll@Sun.COM 
96*12720SWyllys.Ingersoll@Sun.COM    if(pMemBio == NULL)
97*12720SWyllys.Ingersoll@Sun.COM    {
98*12720SWyllys.Ingersoll@Sun.COM       //fixme: log -- no memory
99*12720SWyllys.Ingersoll@Sun.COM       return NULL;
100*12720SWyllys.Ingersoll@Sun.COM    }
101*12720SWyllys.Ingersoll@Sun.COM 
102*12720SWyllys.Ingersoll@Sun.COM   iReturn = PEM_write_bio_PrivateKey
103*12720SWyllys.Ingersoll@Sun.COM      (pMemBio,
104*12720SWyllys.Ingersoll@Sun.COM       i_pPKeyControl->pPKey,
105*12720SWyllys.Ingersoll@Sun.COM       pCipher,
106*12720SWyllys.Ingersoll@Sun.COM       NULL,0,NULL, (char*) i_pPassphrase);
107*12720SWyllys.Ingersoll@Sun.COM 
108*12720SWyllys.Ingersoll@Sun.COM    if(!iReturn) // return 0: means error occurs
109*12720SWyllys.Ingersoll@Sun.COM    {
110*12720SWyllys.Ingersoll@Sun.COM       //fixme: log -- could not export private key
111*12720SWyllys.Ingersoll@Sun.COM       BIO_free(pMemBio);
112*12720SWyllys.Ingersoll@Sun.COM       return NULL;
113*12720SWyllys.Ingersoll@Sun.COM    }
114*12720SWyllys.Ingersoll@Sun.COM 
115*12720SWyllys.Ingersoll@Sun.COM    return pMemBio;
116*12720SWyllys.Ingersoll@Sun.COM }
117*12720SWyllys.Ingersoll@Sun.COM 
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)118*12720SWyllys.Ingersoll@Sun.COM bool SavePrivateKeyToBuffer(
119*12720SWyllys.Ingersoll@Sun.COM    void * const          i_pPKeyImpl,
120*12720SWyllys.Ingersoll@Sun.COM    unsigned char * const i_pcBuffer,
121*12720SWyllys.Ingersoll@Sun.COM    int                   i_iBufferLength,
122*12720SWyllys.Ingersoll@Sun.COM    int * const           o_pActualLength,
123*12720SWyllys.Ingersoll@Sun.COM    const char * const    i_pPassphrase,
124*12720SWyllys.Ingersoll@Sun.COM    int                   i_iFormat)
125*12720SWyllys.Ingersoll@Sun.COM {
126*12720SWyllys.Ingersoll@Sun.COM     PKeyControl* pPKeyControl = (PKeyControl*) i_pPKeyImpl;
127*12720SWyllys.Ingersoll@Sun.COM 
128*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( pPKeyControl &&
129*12720SWyllys.Ingersoll@Sun.COM         i_pcBuffer &&
130*12720SWyllys.Ingersoll@Sun.COM         i_iBufferLength > 0 &&
131*12720SWyllys.Ingersoll@Sun.COM         o_pActualLength );
132*12720SWyllys.Ingersoll@Sun.COM 
133*12720SWyllys.Ingersoll@Sun.COM     BIO *pMemBio = NULL;
134*12720SWyllys.Ingersoll@Sun.COM 	char *pData = NULL;
135*12720SWyllys.Ingersoll@Sun.COM 	int iLength;
136*12720SWyllys.Ingersoll@Sun.COM 
137*12720SWyllys.Ingersoll@Sun.COM 	// create memory BIO
138*12720SWyllys.Ingersoll@Sun.COM 	pMemBio = SavePrivateKeyToMemoryBIO( pPKeyControl, i_pPassphrase );
139*12720SWyllys.Ingersoll@Sun.COM 
140*12720SWyllys.Ingersoll@Sun.COM 	if(pMemBio == NULL)
141*12720SWyllys.Ingersoll@Sun.COM 	{
142*12720SWyllys.Ingersoll@Sun.COM 		//fixme: log -- no memory
143*12720SWyllys.Ingersoll@Sun.COM 		return false;
144*12720SWyllys.Ingersoll@Sun.COM 	}
145*12720SWyllys.Ingersoll@Sun.COM 
146*12720SWyllys.Ingersoll@Sun.COM 	iLength = BIO_get_mem_data(pMemBio, &pData);
147*12720SWyllys.Ingersoll@Sun.COM 
148*12720SWyllys.Ingersoll@Sun.COM     // If the output buffer is a string, it needs to be NULL terminated
149*12720SWyllys.Ingersoll@Sun.COM     // So always append a NULL to the output
150*12720SWyllys.Ingersoll@Sun.COM     if(iLength + 1 > i_iBufferLength)
151*12720SWyllys.Ingersoll@Sun.COM 	{
152*12720SWyllys.Ingersoll@Sun.COM 		//fixme: log -- buffer too small
153*12720SWyllys.Ingersoll@Sun.COM 		BIO_free(pMemBio);
154*12720SWyllys.Ingersoll@Sun.COM 		return false;
155*12720SWyllys.Ingersoll@Sun.COM 	}
156*12720SWyllys.Ingersoll@Sun.COM 	// copy the data to given buffer
157*12720SWyllys.Ingersoll@Sun.COM 	memcpy(i_pcBuffer, pData, iLength);
158*12720SWyllys.Ingersoll@Sun.COM     // NULL terminate the string
159*12720SWyllys.Ingersoll@Sun.COM     i_pcBuffer[iLength] = '\0';
160*12720SWyllys.Ingersoll@Sun.COM 	*o_pActualLength = iLength;
161*12720SWyllys.Ingersoll@Sun.COM 
162*12720SWyllys.Ingersoll@Sun.COM 	// free memory
163*12720SWyllys.Ingersoll@Sun.COM 	BIO_free(pMemBio);
164*12720SWyllys.Ingersoll@Sun.COM 
165*12720SWyllys.Ingersoll@Sun.COM 	return true;
166*12720SWyllys.Ingersoll@Sun.COM }
167*12720SWyllys.Ingersoll@Sun.COM 
168*12720SWyllys.Ingersoll@Sun.COM /**
169*12720SWyllys.Ingersoll@Sun.COM  * import the private key from a BIO, if error, return NULL
170*12720SWyllys.Ingersoll@Sun.COM  */
LoadPrivateKeyFromBIO(PKeyControl * const io_pPKeyControl,BIO * i_pBio,char * i_pPassphrase)171*12720SWyllys.Ingersoll@Sun.COM bool LoadPrivateKeyFromBIO(PKeyControl* const io_pPKeyControl,
172*12720SWyllys.Ingersoll@Sun.COM                            BIO *i_pBio,
173*12720SWyllys.Ingersoll@Sun.COM                            char *i_pPassphrase )
174*12720SWyllys.Ingersoll@Sun.COM {
175*12720SWyllys.Ingersoll@Sun.COM     if (io_pPKeyControl == NULL)
176*12720SWyllys.Ingersoll@Sun.COM     {
177*12720SWyllys.Ingersoll@Sun.COM         return false;
178*12720SWyllys.Ingersoll@Sun.COM     }
179*12720SWyllys.Ingersoll@Sun.COM 
180*12720SWyllys.Ingersoll@Sun.COM     EVP_PKEY *pKey = NULL;
181*12720SWyllys.Ingersoll@Sun.COM 
182*12720SWyllys.Ingersoll@Sun.COM 	if(i_pBio == NULL)
183*12720SWyllys.Ingersoll@Sun.COM     {
184*12720SWyllys.Ingersoll@Sun.COM         return false;
185*12720SWyllys.Ingersoll@Sun.COM     }
186*12720SWyllys.Ingersoll@Sun.COM 
187*12720SWyllys.Ingersoll@Sun.COM     if ( io_pPKeyControl != NULL && io_pPKeyControl->pPKey != NULL )
188*12720SWyllys.Ingersoll@Sun.COM     {
189*12720SWyllys.Ingersoll@Sun.COM         return false; // do not allow overwrite
190*12720SWyllys.Ingersoll@Sun.COM     }
191*12720SWyllys.Ingersoll@Sun.COM 
192*12720SWyllys.Ingersoll@Sun.COM 	pKey=PEM_read_bio_PrivateKey(i_pBio,NULL,NULL,i_pPassphrase);
193*12720SWyllys.Ingersoll@Sun.COM 	if (pKey == NULL)
194*12720SWyllys.Ingersoll@Sun.COM 	{
195*12720SWyllys.Ingersoll@Sun.COM 		// fixme: log: invalid private key format or passphrase
196*12720SWyllys.Ingersoll@Sun.COM 		return false;
197*12720SWyllys.Ingersoll@Sun.COM 	}
198*12720SWyllys.Ingersoll@Sun.COM 
199*12720SWyllys.Ingersoll@Sun.COM     io_pPKeyControl->pPKey = pKey;
200*12720SWyllys.Ingersoll@Sun.COM 
201*12720SWyllys.Ingersoll@Sun.COM 	return true;
202*12720SWyllys.Ingersoll@Sun.COM }
203*12720SWyllys.Ingersoll@Sun.COM 
LoadPrivateKeyFromBuffer(void * const i_pPKeyImpl,unsigned char * i_pcBuffer,int i_iLength,const char * const i_pPassphrase,int i_iFormat)204*12720SWyllys.Ingersoll@Sun.COM bool LoadPrivateKeyFromBuffer(
205*12720SWyllys.Ingersoll@Sun.COM    void * const        i_pPKeyImpl,
206*12720SWyllys.Ingersoll@Sun.COM    unsigned char *     i_pcBuffer,
207*12720SWyllys.Ingersoll@Sun.COM    int                 i_iLength,
208*12720SWyllys.Ingersoll@Sun.COM    const char * const  i_pPassphrase,
209*12720SWyllys.Ingersoll@Sun.COM    int                 i_iFormat)
210*12720SWyllys.Ingersoll@Sun.COM {
211*12720SWyllys.Ingersoll@Sun.COM     PKeyControl* const pPKeyControl = (PKeyControl*) i_pPKeyImpl;
212*12720SWyllys.Ingersoll@Sun.COM 
213*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( i_pPKeyImpl && i_pcBuffer );
214*12720SWyllys.Ingersoll@Sun.COM 
215*12720SWyllys.Ingersoll@Sun.COM     bool bReturn;
216*12720SWyllys.Ingersoll@Sun.COM 	BIO *pMemBio;
217*12720SWyllys.Ingersoll@Sun.COM 	// create a mem bio from the given buffer
218*12720SWyllys.Ingersoll@Sun.COM 	// Note that BIO_new_mem_buf() creates a BIO which never
219*12720SWyllys.Ingersoll@Sun.COM         // destroy the memory attached to it.
220*12720SWyllys.Ingersoll@Sun.COM 	pMemBio = BIO_new_mem_buf(i_pcBuffer, i_iLength);
221*12720SWyllys.Ingersoll@Sun.COM 	if (pMemBio == NULL)
222*12720SWyllys.Ingersoll@Sun.COM 	{
223*12720SWyllys.Ingersoll@Sun.COM 		//fixme: log -- no memory
224*12720SWyllys.Ingersoll@Sun.COM 		return false;
225*12720SWyllys.Ingersoll@Sun.COM 	}
226*12720SWyllys.Ingersoll@Sun.COM 	bReturn = LoadPrivateKeyFromBIO( pPKeyControl,
227*12720SWyllys.Ingersoll@Sun.COM                     pMemBio, (char *)i_pPassphrase );
228*12720SWyllys.Ingersoll@Sun.COM 
229*12720SWyllys.Ingersoll@Sun.COM 	BIO_free(pMemBio);
230*12720SWyllys.Ingersoll@Sun.COM 
231*12720SWyllys.Ingersoll@Sun.COM 	return bReturn;
232*12720SWyllys.Ingersoll@Sun.COM }
233*12720SWyllys.Ingersoll@Sun.COM 
234*12720SWyllys.Ingersoll@Sun.COM /**
235*12720SWyllys.Ingersoll@Sun.COM  * export the public key to a memory BIO, if error, return NULL
236*12720SWyllys.Ingersoll@Sun.COM  */
SavePublicKeyToMemoryBIO(PKeyControl * const i_pPublicKeyControl)237*12720SWyllys.Ingersoll@Sun.COM BIO* SavePublicKeyToMemoryBIO(PKeyControl* const i_pPublicKeyControl )
238*12720SWyllys.Ingersoll@Sun.COM {
239*12720SWyllys.Ingersoll@Sun.COM    BIO *pMemBio = NULL;
240*12720SWyllys.Ingersoll@Sun.COM 
241*12720SWyllys.Ingersoll@Sun.COM    int iReturn;
242*12720SWyllys.Ingersoll@Sun.COM 
243*12720SWyllys.Ingersoll@Sun.COM    // create memory BIO
244*12720SWyllys.Ingersoll@Sun.COM    pMemBio = BIO_new(BIO_s_mem());
245*12720SWyllys.Ingersoll@Sun.COM 
246*12720SWyllys.Ingersoll@Sun.COM    if(pMemBio == NULL)
247*12720SWyllys.Ingersoll@Sun.COM    {
248*12720SWyllys.Ingersoll@Sun.COM       //fixme: log -- no memory
249*12720SWyllys.Ingersoll@Sun.COM       return NULL;
250*12720SWyllys.Ingersoll@Sun.COM    }
251*12720SWyllys.Ingersoll@Sun.COM 
252*12720SWyllys.Ingersoll@Sun.COM    iReturn = PEM_write_bio_PUBKEY(pMemBio,
253*12720SWyllys.Ingersoll@Sun.COM                         i_pPublicKeyControl->pPKey );
254*12720SWyllys.Ingersoll@Sun.COM 
255*12720SWyllys.Ingersoll@Sun.COM    if(!iReturn) // return 0: means error occurs
256*12720SWyllys.Ingersoll@Sun.COM    {
257*12720SWyllys.Ingersoll@Sun.COM       //fixme: log -- could not export private key
258*12720SWyllys.Ingersoll@Sun.COM       BIO_free(pMemBio);
259*12720SWyllys.Ingersoll@Sun.COM       return NULL;
260*12720SWyllys.Ingersoll@Sun.COM    }
261*12720SWyllys.Ingersoll@Sun.COM 
262*12720SWyllys.Ingersoll@Sun.COM    return pMemBio;
263*12720SWyllys.Ingersoll@Sun.COM }
264*12720SWyllys.Ingersoll@Sun.COM 
SavePublicKeyToBuffer(void * const i_pPKeyImpl,unsigned char * const i_pcBuffer,int i_iBufferLength,int * const o_pActualLength,int i_iFormat)265*12720SWyllys.Ingersoll@Sun.COM bool SavePublicKeyToBuffer(
266*12720SWyllys.Ingersoll@Sun.COM    void * const          i_pPKeyImpl,
267*12720SWyllys.Ingersoll@Sun.COM    unsigned char * const i_pcBuffer,
268*12720SWyllys.Ingersoll@Sun.COM    int                   i_iBufferLength,
269*12720SWyllys.Ingersoll@Sun.COM    int * const           o_pActualLength,
270*12720SWyllys.Ingersoll@Sun.COM    int                   i_iFormat)
271*12720SWyllys.Ingersoll@Sun.COM {
272*12720SWyllys.Ingersoll@Sun.COM     PKeyControl* pPublicKeyControl = (PKeyControl*) i_pPKeyImpl;
273*12720SWyllys.Ingersoll@Sun.COM 
274*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( pPublicKeyControl &&
275*12720SWyllys.Ingersoll@Sun.COM         i_pcBuffer &&
276*12720SWyllys.Ingersoll@Sun.COM         i_iBufferLength > 0 &&
277*12720SWyllys.Ingersoll@Sun.COM         o_pActualLength );
278*12720SWyllys.Ingersoll@Sun.COM 
279*12720SWyllys.Ingersoll@Sun.COM     BIO *pMemBio = NULL;
280*12720SWyllys.Ingersoll@Sun.COM 	char *pData = NULL;
281*12720SWyllys.Ingersoll@Sun.COM 	int iLength;
282*12720SWyllys.Ingersoll@Sun.COM 
283*12720SWyllys.Ingersoll@Sun.COM 	// create memory BIO
284*12720SWyllys.Ingersoll@Sun.COM 	pMemBio = SavePublicKeyToMemoryBIO( pPublicKeyControl );
285*12720SWyllys.Ingersoll@Sun.COM 
286*12720SWyllys.Ingersoll@Sun.COM 	if(pMemBio == NULL)
287*12720SWyllys.Ingersoll@Sun.COM 	{
288*12720SWyllys.Ingersoll@Sun.COM 		return false;
289*12720SWyllys.Ingersoll@Sun.COM 	}
290*12720SWyllys.Ingersoll@Sun.COM 
291*12720SWyllys.Ingersoll@Sun.COM 	iLength = BIO_get_mem_data(pMemBio, &pData);
292*12720SWyllys.Ingersoll@Sun.COM 
293*12720SWyllys.Ingersoll@Sun.COM     // If the output buffer is a string, it needs to be NULL terminated
294*12720SWyllys.Ingersoll@Sun.COM     // So always append a NULL to the output
295*12720SWyllys.Ingersoll@Sun.COM     if(iLength + 1 > i_iBufferLength)
296*12720SWyllys.Ingersoll@Sun.COM 	{
297*12720SWyllys.Ingersoll@Sun.COM 		BIO_free(pMemBio);
298*12720SWyllys.Ingersoll@Sun.COM 		return false;
299*12720SWyllys.Ingersoll@Sun.COM 	}
300*12720SWyllys.Ingersoll@Sun.COM 	// copy the data to given buffer
301*12720SWyllys.Ingersoll@Sun.COM 	memcpy(i_pcBuffer, pData, iLength);
302*12720SWyllys.Ingersoll@Sun.COM     // NULL terminate the string
303*12720SWyllys.Ingersoll@Sun.COM     i_pcBuffer[iLength] = '\0';
304*12720SWyllys.Ingersoll@Sun.COM 	*o_pActualLength = iLength;
305*12720SWyllys.Ingersoll@Sun.COM 
306*12720SWyllys.Ingersoll@Sun.COM 	// free memory
307*12720SWyllys.Ingersoll@Sun.COM 	BIO_free(pMemBio);
308*12720SWyllys.Ingersoll@Sun.COM 
309*12720SWyllys.Ingersoll@Sun.COM 	return true;
310*12720SWyllys.Ingersoll@Sun.COM }
311*12720SWyllys.Ingersoll@Sun.COM 
312*12720SWyllys.Ingersoll@Sun.COM /**
313*12720SWyllys.Ingersoll@Sun.COM  * import the public key from a BIO, if error, return NULL
314*12720SWyllys.Ingersoll@Sun.COM  */
LoadPublicKeyFromBIO(PKeyControl * const io_pPublicKeyControl,BIO * i_pBio)315*12720SWyllys.Ingersoll@Sun.COM bool LoadPublicKeyFromBIO(PKeyControl* const io_pPublicKeyControl,
316*12720SWyllys.Ingersoll@Sun.COM                            BIO *i_pBio )
317*12720SWyllys.Ingersoll@Sun.COM {
318*12720SWyllys.Ingersoll@Sun.COM 	EVP_PKEY *pKey = NULL;
319*12720SWyllys.Ingersoll@Sun.COM 
320*12720SWyllys.Ingersoll@Sun.COM     if(io_pPublicKeyControl == NULL)
321*12720SWyllys.Ingersoll@Sun.COM     {
322*12720SWyllys.Ingersoll@Sun.COM         return false;
323*12720SWyllys.Ingersoll@Sun.COM     }
324*12720SWyllys.Ingersoll@Sun.COM 
325*12720SWyllys.Ingersoll@Sun.COM     if(i_pBio == NULL)
326*12720SWyllys.Ingersoll@Sun.COM     {
327*12720SWyllys.Ingersoll@Sun.COM         return false;
328*12720SWyllys.Ingersoll@Sun.COM     }
329*12720SWyllys.Ingersoll@Sun.COM 
330*12720SWyllys.Ingersoll@Sun.COM     if ( io_pPublicKeyControl != NULL && io_pPublicKeyControl->pPKey != NULL )
331*12720SWyllys.Ingersoll@Sun.COM     {
332*12720SWyllys.Ingersoll@Sun.COM         return false; // do not allow overwrite
333*12720SWyllys.Ingersoll@Sun.COM     }
334*12720SWyllys.Ingersoll@Sun.COM 
335*12720SWyllys.Ingersoll@Sun.COM     pKey = PEM_read_bio_PUBKEY(i_pBio, NULL, NULL, NULL);
336*12720SWyllys.Ingersoll@Sun.COM     if (pKey == NULL)
337*12720SWyllys.Ingersoll@Sun.COM     {
338*12720SWyllys.Ingersoll@Sun.COM         // fixme: log: invalid public key format or passphrase
339*12720SWyllys.Ingersoll@Sun.COM         return false;
340*12720SWyllys.Ingersoll@Sun.COM     }
341*12720SWyllys.Ingersoll@Sun.COM 
342*12720SWyllys.Ingersoll@Sun.COM     io_pPublicKeyControl->pPKey = pKey;
343*12720SWyllys.Ingersoll@Sun.COM 
344*12720SWyllys.Ingersoll@Sun.COM 	return true;
345*12720SWyllys.Ingersoll@Sun.COM }
346*12720SWyllys.Ingersoll@Sun.COM 
LoadPublicKeyFromBuffer(void * const i_pPublicKeyImpl,unsigned char * i_pcBuffer,int i_iLength,int i_iFormat)347*12720SWyllys.Ingersoll@Sun.COM bool LoadPublicKeyFromBuffer(
348*12720SWyllys.Ingersoll@Sun.COM    void * const        i_pPublicKeyImpl,
349*12720SWyllys.Ingersoll@Sun.COM    unsigned char *     i_pcBuffer,
350*12720SWyllys.Ingersoll@Sun.COM    int                 i_iLength,
351*12720SWyllys.Ingersoll@Sun.COM    int                 i_iFormat)
352*12720SWyllys.Ingersoll@Sun.COM {
353*12720SWyllys.Ingersoll@Sun.COM     PKeyControl* const pPublicKeyControl = (PKeyControl*) i_pPublicKeyImpl;
354*12720SWyllys.Ingersoll@Sun.COM 
355*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( i_pPublicKeyImpl && i_pcBuffer );
356*12720SWyllys.Ingersoll@Sun.COM 
357*12720SWyllys.Ingersoll@Sun.COM     bool bReturn;
358*12720SWyllys.Ingersoll@Sun.COM 	BIO *pMemBio;
359*12720SWyllys.Ingersoll@Sun.COM 	// create a mem bio from the given buffer
360*12720SWyllys.Ingersoll@Sun.COM 	// Note that BIO_new_mem_buf() creates a BIO which never
361*12720SWyllys.Ingersoll@Sun.COM         // destroy the memory attached to it.
362*12720SWyllys.Ingersoll@Sun.COM 	pMemBio = BIO_new_mem_buf(i_pcBuffer, i_iLength);
363*12720SWyllys.Ingersoll@Sun.COM 	if (pMemBio == NULL)
364*12720SWyllys.Ingersoll@Sun.COM 	{
365*12720SWyllys.Ingersoll@Sun.COM 		//fixme: log -- no memory
366*12720SWyllys.Ingersoll@Sun.COM 		return false;
367*12720SWyllys.Ingersoll@Sun.COM 	}
368*12720SWyllys.Ingersoll@Sun.COM 	bReturn = LoadPublicKeyFromBIO( pPublicKeyControl,
369*12720SWyllys.Ingersoll@Sun.COM                     pMemBio );
370*12720SWyllys.Ingersoll@Sun.COM 
371*12720SWyllys.Ingersoll@Sun.COM 	BIO_free(pMemBio);
372*12720SWyllys.Ingersoll@Sun.COM 
373*12720SWyllys.Ingersoll@Sun.COM 	return bReturn;
374*12720SWyllys.Ingersoll@Sun.COM }
375*12720SWyllys.Ingersoll@Sun.COM 
PublicKeyEncrypt(int i_iLength,const unsigned char * const i_pcPlainText,unsigned char * const o_pcCypherText,int * const o_pActualLength,void * pPKeyControl)376*12720SWyllys.Ingersoll@Sun.COM bool PublicKeyEncrypt (int i_iLength,
377*12720SWyllys.Ingersoll@Sun.COM                        const unsigned char * const i_pcPlainText,
378*12720SWyllys.Ingersoll@Sun.COM                        unsigned char * const o_pcCypherText,
379*12720SWyllys.Ingersoll@Sun.COM                        int * const o_pActualLength,
380*12720SWyllys.Ingersoll@Sun.COM                        void * pPKeyControl )
381*12720SWyllys.Ingersoll@Sun.COM {
382*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( i_pcPlainText );
383*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( o_pcCypherText );
384*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( o_pActualLength );
385*12720SWyllys.Ingersoll@Sun.COM     FATAL_ASSERT( pPKeyControl );
386*12720SWyllys.Ingersoll@Sun.COM 
387*12720SWyllys.Ingersoll@Sun.COM     PKeyControl *pKeyControl = (PKeyControl *)pPKeyControl;
388*12720SWyllys.Ingersoll@Sun.COM     EVP_PKEY * pEVP_PKEY = pKeyControl->pPKey;
389*12720SWyllys.Ingersoll@Sun.COM     RSA * pRSAPublicKey = pEVP_PKEY->pkey.rsa;
390*12720SWyllys.Ingersoll@Sun.COM 
391*12720SWyllys.Ingersoll@Sun.COM //#if defined(DEBUG)
392*12720SWyllys.Ingersoll@Sun.COM //    RSA_print_fp(stdout, pRSAPublicKey, 0);
393*12720SWyllys.Ingersoll@Sun.COM //    printf("PublicKeyEncrypt(): RSA_size()=%d, cyphertextLen=%d\n",
394*12720SWyllys.Ingersoll@Sun.COM //            RSA_size(pRSAPublicKey),
395*12720SWyllys.Ingersoll@Sun.COM //            i_iLength);
396*12720SWyllys.Ingersoll@Sun.COM //#endif
397*12720SWyllys.Ingersoll@Sun.COM 
398*12720SWyllys.Ingersoll@Sun.COM     *o_pActualLength = RSA_public_encrypt(i_iLength,
399*12720SWyllys.Ingersoll@Sun.COM                                           i_pcPlainText,
400*12720SWyllys.Ingersoll@Sun.COM                                           o_pcCypherText,
401*12720SWyllys.Ingersoll@Sun.COM                                           pRSAPublicKey,
402*12720SWyllys.Ingersoll@Sun.COM                                           RSA_PKCS1_PADDING);
403*12720SWyllys.Ingersoll@Sun.COM 
404*12720SWyllys.Ingersoll@Sun.COM     if ( *o_pActualLength < 0 )
405*12720SWyllys.Ingersoll@Sun.COM     {
406*12720SWyllys.Ingersoll@Sun.COM         return false;
407*12720SWyllys.Ingersoll@Sun.COM     }
408*12720SWyllys.Ingersoll@Sun.COM     else
409*12720SWyllys.Ingersoll@Sun.COM     {
410*12720SWyllys.Ingersoll@Sun.COM         return true;
411*12720SWyllys.Ingersoll@Sun.COM     }
412*12720SWyllys.Ingersoll@Sun.COM }
413