make use of C++ error in C API
[platform/core/security/key-manager.git] / src / manager / client-capi / ckmc-type.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  *
16  *
17  * @file        ckmc-type.h
18  * @author      Yuseok Jeon(yuseok.jeon@samsung.com)
19  * @version     1.0
20  * @brief       new and free methods for the struct of CAPI
21  */
22
23
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ckmc/ckmc-type.h>
27 #include <ckmc/ckmc-error.h>
28 #include <openssl/x509v3.h>
29 #include <openssl/pkcs12.h>
30 #include <openssl/evp.h>
31 #include <openssl/pem.h>
32
33 int _ckm_load_cert_from_x509(X509 *xCert, ckm_cert **cert);
34
35
36 KEY_MANAGER_CAPI
37 ckm_key *ckm_key_new(unsigned char *raw_key, unsigned int key_size, ckm_key_type key_type, char *password)
38 {
39         ckm_key *pkey = new ckm_key;
40         if(pkey == NULL)
41                 return NULL;
42
43         pkey->raw_key = reinterpret_cast<unsigned char*>(malloc(key_size));
44         if(pkey->raw_key == NULL) {
45                 free(pkey);
46                 return NULL;
47         }
48         memcpy(pkey->raw_key, raw_key, key_size);
49
50         pkey->key_size = key_size;
51         pkey->key_type = key_type;
52
53         if(password != NULL) {
54                 pkey->password = reinterpret_cast<char*>(malloc(strlen(password) +1));
55                 if(pkey->password == NULL) {
56                         free(pkey);
57                         free(pkey->raw_key);
58                         return NULL;
59                 }
60                 memset(pkey->password, 0, strlen(password) +1);
61                 strncpy(pkey->password, password, strlen(password));
62         }else {
63                 pkey->password = NULL;
64         }
65
66         return pkey;
67 }
68
69 KEY_MANAGER_CAPI
70 void ckm_key_free(ckm_key *key)
71 {
72         if(key == NULL)
73                 return;
74
75         if(key->password != NULL)
76                 free(key->password);
77         if(key->raw_key != NULL)
78                 free(key->raw_key);
79
80         free(key);
81 }
82
83 KEY_MANAGER_CAPI
84 ckm_raw_buffer * ckm_buffer_new(unsigned char *data, unsigned int size)
85 {
86         ckm_raw_buffer *pbuff = new ckm_raw_buffer;
87         if(pbuff == NULL)
88                         return NULL;
89
90         pbuff->data = reinterpret_cast<unsigned char*>(malloc(size));
91         if(pbuff->data == NULL) {
92                 free(pbuff);
93                 return NULL;
94         }
95         memcpy(pbuff->data, data, size);
96
97         pbuff->size = size;
98
99         return pbuff;
100 }
101
102 KEY_MANAGER_CAPI
103 void ckm_buffer_free(ckm_raw_buffer *buffer)
104 {
105         if(buffer == NULL)
106                 return;
107
108         if(buffer->data != NULL)
109                 free(buffer->data);
110         free(buffer);
111 }
112
113 KEY_MANAGER_CAPI
114 ckm_cert *ckm_cert_new(unsigned char *raw_cert, unsigned int cert_size, ckm_cert_form data_format)
115 {
116         ckm_cert *pcert = new ckm_cert;
117         if(pcert == NULL)
118                 return NULL;
119
120         pcert->raw_cert = reinterpret_cast<unsigned char*>(malloc(cert_size));
121         if(pcert->raw_cert == NULL) {
122                 free(pcert);
123                 return NULL;
124         }
125         memcpy(pcert->raw_cert, raw_cert, cert_size);
126
127         pcert->cert_size = cert_size;
128         pcert->data_format = data_format;
129
130         return pcert;
131 }
132
133 KEY_MANAGER_CAPI
134 int ckm_load_cert_from_file(const char *file_path, ckm_cert **cert)
135 {
136         OpenSSL_add_all_algorithms();
137
138         FILE *fp = fopen(file_path, "r");
139         if(fp == NULL)
140                 return CKM_API_ERROR_FILE_ACCESS_DENIED;
141         X509 *pcert = NULL;
142         if(!(pcert = d2i_X509_fp(fp, NULL))) {
143                 fseek(fp, 0, SEEK_SET);
144                 pcert = PEM_read_X509(fp, NULL, NULL, NULL);
145         }
146         fclose(fp);
147         if(pcert == NULL) {
148                 return CKM_API_ERROR_INVALID_FORMAT;
149         }
150
151         int ret = _ckm_load_cert_from_x509(pcert, cert);
152         if(ret != CKM_API_SUCCESS) {
153                 X509_free(pcert);
154         }
155         return ret;
156 }
157
158 KEY_MANAGER_CAPI
159 int ckm_load_from_pkcs12_file(const char *file_path, const char *passphrase, ckm_key **private_key, ckm_cert **ckmcert, ckm_cert_list **ca_cert_list)
160 {
161         class Pkcs12Converter {
162         private:
163                 FILE* fp_in;
164                 PKCS12* p12;
165                 EVP_PKEY* pkey;
166                 X509* x509Cert;
167                 STACK_OF(X509)* ca;
168
169         public:
170                 int ret;
171                 ckm_key *retPrivateKey;
172                 ckm_cert *retCkmCert;
173                 ckm_cert_list *retCaCertList;
174
175                 Pkcs12Converter(){
176                         fp_in = NULL;
177                         p12 = NULL;
178                         pkey = NULL;
179                         x509Cert = NULL;
180                         ca = NULL;
181                         ret = CKM_API_SUCCESS;
182                         retPrivateKey = NULL;
183                         retCkmCert = NULL;
184                         retCaCertList = NULL;
185                 };
186                 ~Pkcs12Converter(){
187                         if(fp_in != NULL)
188                                 fclose(fp_in);
189                         if(p12 != NULL)
190                                 PKCS12_free(p12);
191                         if(x509Cert != NULL)
192                                 X509_free(x509Cert);
193                         if(pkey != NULL)
194                                 EVP_PKEY_free(pkey);
195                         if(ca != NULL)
196                                 sk_X509_pop_free(ca, X509_free);
197                         EVP_cleanup();
198
199                         if(ret != CKM_API_SUCCESS) {
200                                 if(retPrivateKey != NULL)
201                                         ckm_key_free(retPrivateKey);
202                                 if(retCkmCert != NULL)
203                                         ckm_cert_free(retCkmCert);
204                                 if(retCaCertList != NULL)
205                                         ckm_cert_list_free(retCaCertList);
206                         }
207                 };
208
209                 int parsePkcs12(const char *filePath, const char *pass) {
210                         fp_in = NULL;
211                         if(!(fp_in = fopen(filePath, "rb"))) {
212                                 return CKM_API_ERROR_FILE_ACCESS_DENIED;
213                         }
214
215                         if(!(p12 = d2i_PKCS12_fp(fp_in, NULL))) {
216                                 return CKM_API_ERROR_INVALID_FORMAT;
217                         }
218
219                         /* parse PKCS#12 certificate */
220                         if((ret = PKCS12_parse(p12, pass, &pkey, &x509Cert, &ca)) != 1) {
221                                 return CKM_API_ERROR_INVALID_FORMAT;
222                         }
223                         return CKM_API_SUCCESS;
224                 }
225
226                 int toCkmCert() {
227                         if( (ret =_ckm_load_cert_from_x509(x509Cert,&retCkmCert)) != CKM_API_SUCCESS) {
228                                 return ret;
229                         }
230                         return CKM_API_SUCCESS;
231                 }
232
233                 int toCkmKey() {
234                         int prikeyLen = 0;
235                         if((prikeyLen = i2d_PrivateKey(pkey, NULL)) < 0) {
236                                 return CKM_API_ERROR_OUT_OF_MEMORY;
237                         }
238                         unsigned char arrayPrikey[sizeof(unsigned char) * prikeyLen];
239                         unsigned char *pPrikey = arrayPrikey;
240                         if((prikeyLen = i2d_PrivateKey(pkey, &pPrikey)) < 0) {
241                                 return CKM_API_ERROR_OUT_OF_MEMORY;
242                         }
243
244                         int type = EVP_PKEY_type(pkey->type);
245                         ckm_key_type key_type = CKM_KEY_NONE;
246                         switch(type) {
247                         case EVP_PKEY_RSA :
248                                 key_type = CKM_KEY_RSA_PRIVATE;
249                                 break;
250                         case EVP_PKEY_EC :
251                                 key_type = CKM_KEY_ECDSA_PRIVATE;
252                                 break;
253                         }
254                         if(key_type == CKM_KEY_NONE) {
255                                 return CKM_API_ERROR_INVALID_FORMAT;
256                         }
257
258                         char *nullPassword = NULL;
259                         retPrivateKey = ckm_key_new(pPrikey, sizeof(unsigned char) * prikeyLen, key_type, nullPassword);
260
261                         return CKM_API_SUCCESS;
262                 }
263
264                 int toCaCkmCertList() {
265                         X509* popedCert = NULL;
266                         ckm_cert *popedCkmCert = NULL;
267                         ckm_cert_list *tmpCertList = NULL;
268                         retCaCertList = tmpCertList;
269                         while((popedCert = sk_X509_pop(ca)) != NULL) {
270                                 if( (ret =_ckm_load_cert_from_x509(popedCert, &popedCkmCert)) != CKM_API_SUCCESS) {
271                                         return CKM_API_ERROR_OUT_OF_MEMORY;
272                                 }
273                                 tmpCertList = ckm_cert_list_add(tmpCertList, popedCkmCert);
274                         }
275                         return CKM_API_SUCCESS;
276                 }
277
278         };
279
280         int ret = CKM_API_SUCCESS;
281
282         Pkcs12Converter converter;
283         if((ret = converter.parsePkcs12(file_path, passphrase)) != CKM_API_SUCCESS) {
284                 return ret;
285         }
286         if((ret = converter.toCkmCert()) != CKM_API_SUCCESS) {
287                 return ret;
288         }
289         if((ret = converter.toCkmKey()) != CKM_API_SUCCESS) {
290                 return ret;
291         }
292         if((ret = converter.toCaCkmCertList()) != CKM_API_SUCCESS) {
293                 return ret;
294         }
295         *private_key = converter.retPrivateKey;
296         *ckmcert = converter.retCkmCert;
297         *ca_cert_list = converter.retCaCertList;
298
299         return CKM_API_SUCCESS;
300 }
301
302 KEY_MANAGER_CAPI
303 void ckm_cert_free(ckm_cert *cert)
304 {
305         if(cert == NULL)
306                 return;
307
308         if(cert->raw_cert != NULL)
309                 free(cert->raw_cert);
310         free(cert);
311 }
312
313 KEY_MANAGER_CAPI
314 ckm_alias_list *ckm_alias_list_new(char *alias)
315 {
316         ckm_alias_list *previous = NULL;
317         return ckm_alias_list_add(previous, alias);
318 }
319
320 KEY_MANAGER_CAPI
321 ckm_alias_list *ckm_alias_list_add(ckm_alias_list *previous, char *alias)
322 {
323         ckm_alias_list *plist = new ckm_alias_list;
324
325         plist->alias = alias;
326         plist->next = NULL;
327
328         if(previous != NULL)
329                 previous->next = plist;
330
331         return plist;
332 }
333
334 KEY_MANAGER_CAPI
335 void ckm_alias_list_free(ckm_alias_list *first)
336 {
337         if(first == NULL)
338                 return;
339
340         ckm_alias_list *current = NULL;
341         ckm_alias_list *next = first;
342         do {
343                 current = next;
344                 next = current->next;
345                 free(current);
346         }while(next != NULL);
347 }
348
349 KEY_MANAGER_CAPI
350 void ckm_alias_list_all_free(ckm_alias_list *first)
351 {
352         if(first == NULL)
353                 return;
354
355         ckm_alias_list *current = NULL;
356         ckm_alias_list *next = first;
357         do {
358                 current = next;
359                 next = current->next;
360                 if((current->alias)!=NULL) {
361                         free(current->alias);
362                 }
363                 free(current);
364         }while(next != NULL);
365 }
366
367 KEY_MANAGER_CAPI
368 ckm_cert_list *ckm_cert_list_new(ckm_cert *cert)
369 {
370         ckm_cert_list *previous = NULL;
371         return ckm_cert_list_add(previous, cert);
372 }
373
374 KEY_MANAGER_CAPI
375 ckm_cert_list *ckm_cert_list_add(ckm_cert_list *previous, ckm_cert *cert)
376 {
377         ckm_cert_list *plist = new ckm_cert_list;
378
379         plist->cert = cert;
380         plist->next = NULL;
381
382         if(previous != NULL)
383                 previous->next = plist;
384
385         return plist;
386 }
387
388 KEY_MANAGER_CAPI
389 void ckm_cert_list_free(ckm_cert_list *first)
390 {
391         if(first == NULL)
392                 return;
393
394         ckm_cert_list *current = NULL;
395         ckm_cert_list *next = first;
396         do {
397                 current = next;
398                 next = current->next;
399                 free(current);
400         }while(next != NULL);
401 }
402
403 KEY_MANAGER_CAPI
404 void ckm_cert_list_all_free(ckm_cert_list *first)
405 {
406         if(first == NULL)
407                 return;
408
409         ckm_cert_list *current = NULL;
410         ckm_cert_list *next = first;
411         do {
412                 current = next;
413                 next = current->next;
414                 if((current->cert)!=NULL) {
415                         ckm_cert_free(current->cert);
416                 }
417                 free(current);
418         }while(next != NULL);
419 }
420
421 int _ckm_load_cert_from_x509(X509 *xCert, ckm_cert **cert)
422 {
423         int certLen;
424         unsigned char* bufCert = NULL;
425
426         if(xCert == NULL) {
427                 return CKM_API_ERROR_INVALID_FORMAT;
428         }
429
430         /* load certificate into buffer */
431         if((certLen = i2d_X509(xCert, NULL)) < 0) {
432                 return CKM_API_ERROR_INVALID_FORMAT;
433         }
434         unsigned char arrayCert[sizeof(unsigned char) * certLen];
435         bufCert = arrayCert;
436         i2d_X509(xCert, &bufCert);
437
438         *cert = ckm_cert_new(bufCert, certLen, CKM_CERT_FORM_DER);
439
440         return CKM_API_SUCCESS;
441 }