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