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