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
37typedef struct X509control
38{
39    X509*   pX509;
40} X509control;
41
42void * 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 */
57BIO* 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
84bool 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
124bool 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 */
175bool 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
199bool 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
235bool 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
265void FinalizeCertImpl( void* i_pImplResource )
266{
267    if ( i_pImplResource != NULL )
268    {
269        free(i_pImplResource);
270    }
271}
272
273bool 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
301void *GetCert(void* i_pImplResource )
302{
303	X509control* pX509control = (X509control*)i_pImplResource;
304	return ((void *)pX509control->pX509);
305}
306
307void SetCert(void* i_pImplResource, void *cert)
308{
309	X509control* pX509control = (X509control*)i_pImplResource;
310	pX509control->pX509 = (X509 *)cert;
311	return;
312}
313#endif
314