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 KMSAgentPKICertOpenSSL.cpp
28  */
29 
30 #include <stdio.h>
31 #include <openssl/bio.h>
32 #include <openssl/pem.h>
33 
34 #include "SYSCommon.h"
35 #include "KMSAgentPKIimpl.h"
36 
37 typedef struct X509control
38 {
39     X509*   pX509;
40 } X509control;
41 
InitializeCertImpl()42 void * InitializeCertImpl()
43 {
44     X509control *pX509Control = (X509control *) malloc(sizeof(X509control));
45 
46     if ( pX509Control != NULL )
47     {
48         pX509Control->pX509 = NULL;
49     }
50 
51     return pX509Control;
52 }
53 
54 /**
55  * export the Cert to a memory BIO, if error, return NULL
56  */
SaveCertToMemoryBIO(X509control * i_pX509control)57 BIO* SaveCertToMemoryBIO( X509control* i_pX509control )
58 {
59     BIO *pMemBio = NULL;
60     int iReturn;
61 
62     // create memory BIO
63     pMemBio = BIO_new(BIO_s_mem());
64 
65     if(pMemBio == NULL)
66     {
67         //fixme: log -- no memory
68         return NULL;
69     }
70 
71     //iReturn = PEM_write_bio_X509(pMemBio, m_pNative);
72     iReturn = PEM_write_bio_X509(pMemBio, i_pX509control->pX509);
73 
74     if(!iReturn) // return 0: means error occurs
75     {
76         //fixme: log -- could not export private key
77         BIO_free(pMemBio);
78         return NULL;
79     }
80 
81     return pMemBio;
82 }
83 
SaveX509CertTofile(void * const i_pImplResource,const char * const i_pcFileName)84 bool SaveX509CertTofile(
85                         void* const i_pImplResource,
86                         const char * const i_pcFileName )
87 {
88     FATAL_ASSERT( i_pImplResource != NULL && i_pcFileName );
89 
90     X509control* pX509control = (X509control*)i_pImplResource;
91     // the BIO for output, need cleanup when exiting
92     BIO *pMemBio = NULL;
93     int iLength;
94     unsigned char *pData;
95     FILE *fp;
96 
97     // create memory BIO
98     pMemBio = SaveCertToMemoryBIO( pX509control );
99 
100     if(pMemBio == NULL)
101     {
102         return false;
103     }
104 
105     // now pMemBIO != NULL, remember to free it before exiting
106     iLength = BIO_get_mem_data(pMemBio, &pData);
107 
108     // open the file
109     fp = fopen(i_pcFileName, "wb");
110     if(fp == NULL)
111     {
112         //fixme: log -- could not open file for exporting Cert
113         BIO_free(pMemBio);
114         return false;
115     }
116 
117     fwrite(pData, 1, iLength, fp);
118     fclose(fp);
119 
120     BIO_free(pMemBio); // BIO_free close the file and clean the BIO
121     return true;
122 }
123 
SaveX509CertToBuffer(void * const i_pImplResource,unsigned char * const i_pcBuffer,int i_iBufferLength,int * const o_pActualLength)124 bool SaveX509CertToBuffer(
125                         void* const             i_pImplResource,
126                         unsigned char * const   i_pcBuffer,
127                         int                     i_iBufferLength,
128                         int * const             o_pActualLength )
129 {
130     FATAL_ASSERT( i_pImplResource != NULL &&
131                   i_pcBuffer &&
132                   o_pActualLength &&
133                   i_iBufferLength > 0 );
134 
135     X509control* pX509control = (X509control*)i_pImplResource;
136 
137     BIO *pMemBio = NULL;
138     char *pData = NULL;
139     int iLength;
140 
141     // create memory BIO
142     pMemBio = SaveCertToMemoryBIO( pX509control );
143 
144     if( pMemBio == NULL )
145     {
146         //fixme: log -- no memory
147         return false;
148     }
149 
150     iLength = BIO_get_mem_data( pMemBio, &pData );
151 
152     // If the output buffer is a string, it needs to be NULL terminated
153     // So always append a NULL to the output
154     if(iLength + 1 > i_iBufferLength)
155     {
156         //fixme: log -- buffer too small
157         BIO_free(pMemBio);
158         return false;
159     }
160     // copy the data to given buffer
161     memcpy(i_pcBuffer, pData, iLength);
162     // NULL terminate the string
163     i_pcBuffer[iLength] = '\0';
164     *o_pActualLength = iLength;
165 
166     // free memory
167     BIO_free(pMemBio);
168 
169     return true;
170 }
171 
172 /**
173  * import the Cert from a BIO, if error, return NULL
174  */
LoadCertFromBIO(X509control * i_pX509control,BIO * i_pBio)175 bool LoadCertFromBIO(X509control* i_pX509control, BIO *i_pBio)
176 {
177     X509 *pRequest = NULL;
178 
179     if (i_pX509control == NULL) return false;
180 
181     if(i_pBio == NULL) return false;
182 
183     //if(m_pNative != NULL) return false; // do not allow overwrite
184     if (i_pX509control->pX509 != NULL ) return false;
185 
186     pRequest=PEM_read_bio_X509(i_pBio, NULL, NULL, NULL);
187 
188     if (pRequest == NULL)
189     {
190         // fixme: log: invalid certificate format
191         return false;
192     }
193     //m_pNative = pRequest;
194     i_pX509control->pX509 = pRequest;
195 
196     return true;
197 }
198 
LoadX509CertFromFile(void * const i_pImplResource,const char * const i_pcFileName)199 bool LoadX509CertFromFile(
200                             void* const i_pImplResource,
201                             const char * const i_pcFileName )
202 
203 {
204     X509control* pX509control = (X509control*) i_pImplResource;
205     if (pX509control == NULL)
206     {
207         return false;
208     }
209 
210     BIO *pFileBio=NULL;
211     bool bReturn;
212 
213     pFileBio=BIO_new(BIO_s_file());
214     if (pFileBio == NULL)
215     {
216         //fixme: log -- no memory
217         return false;
218     }
219 
220     if (!BIO_read_filename(pFileBio,i_pcFileName))
221     {
222         //fixme log -- could not open file
223         BIO_free(pFileBio);
224         return false;
225     }
226 
227     bReturn = LoadCertFromBIO(pX509control, pFileBio);
228 
229     BIO_free(pFileBio);
230 
231     return bReturn;
232 }
233 
234 
LoadX509CertFromBuffer(void * const i_pImplResource,void * const i_pX509Cert,int i_iLength)235 bool LoadX509CertFromBuffer(
236                            void* const i_pImplResource,
237                            void* const i_pX509Cert,
238                            int         i_iLength)
239  {
240     X509control* pX509control = (X509control*)i_pImplResource;
241 
242     if(pX509control == NULL)
243     {
244         return false;
245     }
246 
247     BIO *pMemBio;
248     bool bReturn;
249     // create a mem bio from the given buffer
250     // Note that BIO_new_mem_buf() creates a BIO which never destroy the memory
251     //    attached to it.
252     pMemBio = BIO_new_mem_buf(i_pX509Cert, i_iLength);
253     if (pMemBio == NULL)
254     {
255         //fixme: log -- no memory
256         return false;
257     }
258     bReturn = LoadCertFromBIO(pX509control, pMemBio);
259 
260     BIO_free(pMemBio);
261 
262     return bReturn;
263 }
264 
FinalizeCertImpl(void * i_pImplResource)265 void FinalizeCertImpl( void* i_pImplResource )
266 {
267     if ( i_pImplResource != NULL )
268     {
269         free(i_pImplResource);
270     }
271 }
272 
PrintX509Cert(void * const i_pImplResource)273 bool PrintX509Cert( void* const i_pImplResource )
274 {
275     BIO *pMemBio;
276     char *pData;
277     int iLength,i;
278     X509control* pX509control = (X509control*)i_pImplResource;
279     pMemBio = BIO_new(BIO_s_mem());
280     if(pMemBio == NULL)
281     {
282         return false;
283     }
284 
285     //X509_print(pMemBio,m_pNative);
286     X509_print(pMemBio, pX509control->pX509);
287 
288     iLength = BIO_get_mem_data(pMemBio, &pData);
289 
290     for(i = 0; i < iLength; i++)
291     {
292         printf("%c", pData[i]);
293     }
294 
295     BIO_free(pMemBio);
296 
297     return true;
298 
299 }
300 #ifdef K_SOLARIS_PLATFORM
GetCert(void * i_pImplResource)301 void *GetCert(void* i_pImplResource )
302 {
303 	X509control* pX509control = (X509control*)i_pImplResource;
304 	return ((void *)pX509control->pX509);
305 }
306 
SetCert(void * i_pImplResource,void * cert)307 void SetCert(void* i_pImplResource, void *cert)
308 {
309 	X509control* pX509control = (X509control*)i_pImplResource;
310 	pX509control->pX509 = (X509 *)cert;
311 	return;
312 }
313 #endif
314