changed to tizen compatible error type
[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 <stdio.h>
26 #include <stdlib.h>
27 #include <ckm/ckm-type.h>
28 #include <ckmc/ckmc-type.h>
29 #include <ckmc/ckmc-error.h>
30 #include <ckmc-type-converter.h>
31 #include <openssl/x509v3.h>
32 #include <openssl/pkcs12.h>
33 #include <openssl/evp.h>
34 #include <openssl/pem.h>
35
36 int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert);
37
38 KEY_MANAGER_CAPI
39 int ckmc_key_new(unsigned char *raw_key, size_t key_size, ckmc_key_type_e key_type, char *password, ckmc_key_s **ppkey)
40 {
41         ckmc_key_s *pkey;
42
43         if(raw_key == NULL || key_size <= 0 || ppkey == NULL) {
44                 return CKMC_ERROR_INPUT_PARAM;
45         }
46
47         pkey = new ckmc_key_s;
48         if(pkey == NULL) {
49                 return CKMC_ERROR_OUT_OF_MEMORY;
50         }
51         pkey->raw_key = reinterpret_cast<unsigned char*>(malloc(key_size));
52         if(pkey->raw_key == NULL) {
53                 free(pkey);
54                 return CKMC_ERROR_OUT_OF_MEMORY;
55         }
56         memcpy(pkey->raw_key, raw_key, key_size);
57
58         pkey->key_size = key_size;
59         pkey->key_type = key_type;
60
61         if(password != NULL) {
62                 pkey->password = reinterpret_cast<char*>(malloc(strlen(password) +1));
63                 if(pkey->password == NULL) {
64                         free(pkey);
65                         free(pkey->raw_key);
66                         return CKMC_ERROR_OUT_OF_MEMORY;
67                 }
68                 memset(pkey->password, 0, strlen(password) +1);
69                 strncpy(pkey->password, password, strlen(password));
70         }else {
71                 pkey->password = NULL;
72         }
73
74         *ppkey = pkey;
75
76         return CKMC_SUCCESS;
77 }
78
79 KEY_MANAGER_CAPI
80 void ckmc_key_free(ckmc_key_s *key)
81 {
82         if(key == NULL)
83                 return;
84
85         if(key->password != NULL)
86                 free(key->password);
87         if(key->raw_key != NULL) {
88                 memset(key->raw_key, 0, key->key_size);
89                 free(key->raw_key);
90         }
91
92         free(key);
93 }
94
95 KEY_MANAGER_CAPI
96 int ckmc_buffer_new(unsigned char *data, size_t size,ckmc_raw_buffer_s **ppbuffer)
97 {
98         ckmc_raw_buffer_s *pbuff;
99
100         if(data == NULL || size <= 0 || ppbuffer == NULL) {
101                 return CKMC_ERROR_INPUT_PARAM;
102         }
103
104         pbuff = new ckmc_raw_buffer_s;
105         if(pbuff == NULL)
106                         return CKMC_ERROR_OUT_OF_MEMORY;
107
108         pbuff->data = reinterpret_cast<unsigned char*>(malloc(size));
109         if(pbuff->data == NULL) {
110                 free(pbuff);
111                 return CKMC_ERROR_OUT_OF_MEMORY;
112         }
113         memcpy(pbuff->data, data, size);
114
115         pbuff->size = size;
116         *ppbuffer = pbuff;
117
118         return CKMC_SUCCESS;
119 }
120
121 KEY_MANAGER_CAPI
122 void ckmc_buffer_free(ckmc_raw_buffer_s *buffer)
123 {
124         if(buffer == NULL)
125                 return;
126
127         if(buffer->data != NULL) {
128                 memset(buffer->data, 0, buffer->size);
129                 free(buffer->data);
130         }
131         free(buffer);
132 }
133
134 KEY_MANAGER_CAPI
135 int ckmc_cert_new(unsigned char *raw_cert, size_t cert_size, ckmc_data_format_e data_format, ckmc_cert_s **ppcert)
136 {
137         ckmc_cert_s *pcert;
138
139         if(raw_cert == NULL || cert_size <= 0 || ppcert == NULL) {
140                 return CKMC_ERROR_INPUT_PARAM;
141         }
142
143         pcert = new ckmc_cert_s;
144         if(pcert == NULL) {
145                 return CKMC_ERROR_OUT_OF_MEMORY;
146         }
147         pcert->raw_cert = reinterpret_cast<unsigned char*>(malloc(cert_size));
148         if(pcert->raw_cert == NULL) {
149                 free(pcert);
150                 return CKMC_ERROR_OUT_OF_MEMORY;
151         }
152         memcpy(pcert->raw_cert, raw_cert, cert_size);
153
154         pcert->cert_size = cert_size;
155         pcert->data_format = data_format;
156
157         *ppcert = pcert;
158         return CKMC_SUCCESS;
159 }
160
161 KEY_MANAGER_CAPI
162 int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert)
163 {
164         OpenSSL_add_all_algorithms();
165
166         FILE *fp = fopen(file_path, "r");
167         if(fp == NULL)
168                 return CKMC_ERROR_FILE_ACCESS_DENIED;
169         X509 *pcert = NULL;
170         if(!(pcert = d2i_X509_fp(fp, NULL))) {
171                 fseek(fp, 0, SEEK_SET);
172                 pcert = PEM_read_X509(fp, NULL, NULL, NULL);
173         }
174         fclose(fp);
175         if(pcert == NULL) {
176                 return CKMC_ERROR_INVALID_FORMAT;
177         }
178
179         int ret = _ckmc_load_cert_from_x509(pcert, cert);
180         if(ret != CKMC_SUCCESS) {
181                 X509_free(pcert);
182         }
183         return ret;
184 }
185
186 KEY_MANAGER_CAPI
187 int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase, ckmc_key_s **private_key, ckmc_cert_s **ckmcert, ckmc_cert_list_s **ca_cert_list)
188 {
189         class Pkcs12Converter {
190         private:
191                 FILE* fp_in;
192                 PKCS12* p12;
193                 EVP_PKEY* pkey;
194                 X509* x509Cert;
195                 STACK_OF(X509)* ca;
196
197                 int ret;
198         public:
199                 ckmc_key_s *retPrivateKey;
200                 ckmc_cert_s *retCkmCert;
201                 ckmc_cert_list_s *retCaCertList;
202
203                 Pkcs12Converter(){
204                         fp_in = NULL;
205                         p12 = NULL;
206                         pkey = NULL;
207                         x509Cert = NULL;
208                         ca = NULL;
209                         ret = CKMC_SUCCESS;
210                         retPrivateKey = NULL;
211                         retCkmCert = NULL;
212                         retCaCertList = NULL;
213                 };
214                 ~Pkcs12Converter(){
215                         if(fp_in != NULL)
216                                 fclose(fp_in);
217                         if(p12 != NULL)
218                                 PKCS12_free(p12);
219                         if(x509Cert != NULL)
220                                 X509_free(x509Cert);
221                         if(pkey != NULL)
222                                 EVP_PKEY_free(pkey);
223                         if(ca != NULL)
224                                 sk_X509_pop_free(ca, X509_free);
225                         EVP_cleanup();
226
227                         if(ret != CKMC_SUCCESS) {
228                                 if(retPrivateKey != NULL){
229                                         ckmc_key_free(retPrivateKey);
230                                         retPrivateKey = NULL;
231                                 }
232                                 if(retCkmCert != NULL) {
233                                         ckmc_cert_free(retCkmCert);
234                                         retCkmCert = NULL;
235                                 }
236                                 if(retCaCertList != NULL) {
237                                         ckmc_cert_list_all_free(retCaCertList);
238                                         retCaCertList = NULL;
239                                 }
240                         }
241                 };
242
243                 int parsePkcs12(const char *filePath, const char *pass) {
244                         fp_in = NULL;
245                         if(!(fp_in = fopen(filePath, "rb"))) {
246                                 return CKMC_ERROR_FILE_ACCESS_DENIED;
247                         }
248
249                         if(!(p12 = d2i_PKCS12_fp(fp_in, NULL))) {
250                                 return CKMC_ERROR_INVALID_FORMAT;
251                         }
252
253                         /* parse PKCS#12 certificate */
254                         if((ret = PKCS12_parse(p12, pass, &pkey, &x509Cert, &ca)) != 1) {
255                                 return CKMC_ERROR_INVALID_FORMAT;
256                         }
257                         return CKMC_SUCCESS;
258                 }
259
260                 int toCkmCert() {
261                         if( (ret =_ckmc_load_cert_from_x509(x509Cert,&retCkmCert)) != CKMC_SUCCESS) {
262                                 return ret;
263                         }
264                         return CKMC_SUCCESS;
265                 }
266
267                 int toCkmKey() {
268                         BIO *bkey = BIO_new(BIO_s_mem());
269
270                         i2d_PrivateKey_bio(bkey, pkey);
271
272                     CKM::RawBuffer output(8196);
273                     int size = BIO_read(bkey, output.data(), output.size());
274                         BIO_free_all(bkey);
275                     if (size <= 0) {
276                         return CKMC_ERROR_INVALID_FORMAT;
277                     }
278                     output.resize(size);
279
280                         int type = EVP_PKEY_type(pkey->type);
281                         ckmc_key_type_e key_type = CKMC_KEY_NONE;
282                         switch(type) {
283                         case EVP_PKEY_RSA :
284                                 key_type = CKMC_KEY_RSA_PRIVATE;
285                                 break;
286                         case EVP_PKEY_EC :
287                                 key_type = CKMC_KEY_ECDSA_PRIVATE;
288                                 break;
289                         }
290                         if(key_type == CKMC_KEY_NONE) {
291                                 return CKMC_ERROR_INVALID_FORMAT;
292                         }
293
294                         char *nullPassword = NULL;
295
296                         return ckmc_key_new(output.data(), size, key_type, nullPassword, &retPrivateKey);
297                 }
298
299                 int toCaCkmCertList() {
300                         int tmpRet;
301                         X509* popedCert = NULL;
302                         ckmc_cert_s *popedCkmCert = NULL;
303                         ckmc_cert_list_s *tmpCertList = NULL;
304                         while((popedCert = sk_X509_pop(ca)) != NULL) {
305                                 if( (tmpRet =_ckmc_load_cert_from_x509(popedCert, &popedCkmCert)) != CKMC_SUCCESS) {
306                                         return CKMC_ERROR_OUT_OF_MEMORY;
307                                 }
308                                 if(tmpCertList == NULL) { // first
309                                         tmpRet = ckmc_cert_list_new(popedCkmCert, &tmpCertList);
310                                         retCaCertList = tmpCertList;
311                                 }else {
312                                         tmpRet = ckmc_cert_list_add(tmpCertList, popedCkmCert, &tmpCertList);
313                                 }
314                                 if(tmpRet != CKMC_SUCCESS) {
315                                         ckmc_cert_list_all_free(retCaCertList);
316                                         retCaCertList = NULL;
317                                         return tmpRet;
318                                 }
319                         }
320                         return CKMC_SUCCESS;
321                 }
322
323         };
324
325         int ret = CKMC_SUCCESS;
326
327         Pkcs12Converter converter;
328         if((ret = converter.parsePkcs12(file_path, passphrase)) != CKMC_SUCCESS) {
329                 return ret;
330         }
331         if((ret = converter.toCkmCert()) != CKMC_SUCCESS) {
332                 return ret;
333         }
334         if((ret = converter.toCkmKey()) != CKMC_SUCCESS) {
335                 return ret;
336         }
337         if((ret = converter.toCaCkmCertList()) != CKMC_SUCCESS) {
338                 return ret;
339         }
340
341         *private_key = converter.retPrivateKey;
342         *ckmcert = converter.retCkmCert;
343         *ca_cert_list = converter.retCaCertList;
344
345         return CKMC_SUCCESS;
346 }
347
348 KEY_MANAGER_CAPI
349 void ckmc_cert_free(ckmc_cert_s *cert)
350 {
351         if(cert == NULL)
352                 return;
353
354         if(cert->raw_cert != NULL) {
355                 memset(cert->raw_cert, 0, cert->cert_size);
356                 free(cert->raw_cert);
357         }
358         free(cert);
359 }
360
361 KEY_MANAGER_CAPI
362 int ckmc_alias_list_new(char *alias, ckmc_alias_list_s **ppalias_list)
363 {
364         ckmc_alias_list_s *previous = NULL;
365         return ckmc_alias_list_add(previous, alias, ppalias_list);
366 }
367
368 KEY_MANAGER_CAPI
369 int ckmc_alias_list_add(ckmc_alias_list_s *previous, char *alias, ckmc_alias_list_s **pplast)
370 {
371         ckmc_alias_list_s *plist;
372
373         if(alias == NULL || pplast == NULL) {
374                 return CKMC_ERROR_INPUT_PARAM;
375         }
376
377         plist = new ckmc_alias_list_s;
378         if(plist == NULL) {
379                 return CKMC_ERROR_OUT_OF_MEMORY;
380         }
381
382         plist->alias = alias;
383         plist->next = NULL;
384
385         if(previous != NULL) {
386                 previous->next = plist;
387         }
388         *pplast = plist;
389
390         return CKMC_SUCCESS;
391 }
392
393 KEY_MANAGER_CAPI
394 void ckmc_alias_list_free(ckmc_alias_list_s *first)
395 {
396         if(first == NULL)
397                 return;
398
399         ckmc_alias_list_s *current = NULL;
400         ckmc_alias_list_s *next = first;
401         do {
402                 current = next;
403                 next = current->next;
404                 free(current);
405         }while(next != NULL);
406 }
407
408 KEY_MANAGER_CAPI
409 void ckmc_alias_list_all_free(ckmc_alias_list_s *first)
410 {
411         if(first == NULL)
412                 return;
413         ckmc_alias_list_s *current = NULL;
414         ckmc_alias_list_s *next = first;
415         do {
416                 current = next;
417                 next = current->next;
418                 if((current->alias)!=NULL) {
419                         free(current->alias);
420                 }
421                 free(current);
422         }while(next != NULL);
423 }
424
425 KEY_MANAGER_CAPI
426 int ckmc_cert_list_new(ckmc_cert_s *cert, ckmc_cert_list_s **ppalias_list)
427 {
428         ckmc_cert_list_s *previous = NULL;
429         return ckmc_cert_list_add(previous, cert, ppalias_list);
430 }
431
432 KEY_MANAGER_CAPI
433 int ckmc_cert_list_add(ckmc_cert_list_s *previous, ckmc_cert_s *cert, ckmc_cert_list_s **pplast)
434 {
435         ckmc_cert_list_s *plist;
436
437         if(cert == NULL || pplast == NULL) {
438                 return CKMC_ERROR_INPUT_PARAM;
439         }
440
441         plist = new ckmc_cert_list_s;
442         if(plist == NULL) {
443                 return CKMC_ERROR_OUT_OF_MEMORY;
444         }
445         plist->cert = cert;
446         plist->next = NULL;
447
448         if(previous != NULL) {
449                 previous->next = plist;
450         }
451
452         *pplast = plist;
453
454         return CKMC_SUCCESS;
455 }
456
457 KEY_MANAGER_CAPI
458 void ckmc_cert_list_free(ckmc_cert_list_s *first)
459 {
460         if(first == NULL)
461                 return;
462
463         ckmc_cert_list_s *current = NULL;
464         ckmc_cert_list_s *next = first;
465         do {
466                 current = next;
467                 next = current->next;
468                 free(current);
469         }while(next != NULL);
470 }
471
472 KEY_MANAGER_CAPI
473 void ckmc_cert_list_all_free(ckmc_cert_list_s *first)
474 {
475         if(first == NULL)
476                 return;
477
478         ckmc_cert_list_s *current = NULL;
479         ckmc_cert_list_s *next = first;
480         do {
481                 current = next;
482                 next = current->next;
483                 if((current->cert)!=NULL) {
484                         ckmc_cert_free(current->cert);
485                 }
486                 free(current);
487         }while(next != NULL);
488 }
489
490 int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert)
491 {
492         if(xCert == NULL) {
493                 return CKMC_ERROR_INVALID_FORMAT;
494         }
495
496         BIO *bcert = BIO_new(BIO_s_mem());
497
498         i2d_X509_bio(bcert, xCert);
499
500     CKM::RawBuffer output(8196);
501     int size = BIO_read(bcert, output.data(), output.size());
502         BIO_free_all(bcert);
503     if (size <= 0) {
504         return CKMC_ERROR_INVALID_FORMAT;
505     }
506     output.resize(size);
507
508         return ckmc_cert_new(output.data(), output.size(), CKMC_FORM_DER, cert);
509 }
510
511 int to_ckmc_error(int ckm_error) {
512         switch(ckm_error) {
513         case CKM_API_SUCCESS:                     return CKMC_SUCCESS;
514         case CKM_API_ERROR_SOCKET:                return CKMC_ERROR_SOCKET;
515         case CKM_API_ERROR_BAD_REQUEST:           return CKMC_ERROR_BAD_REQUEST;
516         case CKM_API_ERROR_BAD_RESPONSE:          return CKMC_ERROR_BAD_RESPONSE;
517         case CKM_API_ERROR_SEND_FAILED:           return CKMC_ERROR_SEND_FAILED;
518         case CKM_API_ERROR_RECV_FAILED:           return CKMC_ERROR_RECV_FAILED;
519         case CKM_API_ERROR_AUTHENTICATION_FAILED: return CKMC_ERROR_AUTHENTICATION_FAILED;
520         case CKM_API_ERROR_INPUT_PARAM:           return CKMC_ERROR_INPUT_PARAM;
521         case CKM_API_ERROR_BUFFER_TOO_SMALL:      return CKMC_ERROR_BUFFER_TOO_SMALL;
522         case CKM_API_ERROR_OUT_OF_MEMORY:         return CKMC_ERROR_OUT_OF_MEMORY;
523         case CKM_API_ERROR_ACCESS_DENIED:         return CKMC_ERROR_ACCESS_DENIED;
524         case CKM_API_ERROR_SERVER_ERROR:          return CKMC_ERROR_SERVER_ERROR;
525         case CKM_API_ERROR_DB_LOCKED:             return CKMC_ERROR_DB_LOCKED;
526         case CKM_API_ERROR_DB_ERROR:              return CKMC_ERROR_DB_ERROR;
527         case CKM_API_ERROR_DB_ALIAS_EXISTS:       return CKMC_ERROR_DB_ALIAS_EXISTS;
528         case CKM_API_ERROR_DB_ALIAS_UNKNOWN:      return CKMC_ERROR_DB_ALIAS_UNKNOWN;
529         case CKM_API_ERROR_VERIFICATION_FAILED:   return CKMC_ERROR_VERIFICATION_FAILED;
530         case CKM_API_ERROR_INVALID_FORMAT:        return CKMC_ERROR_INVALID_FORMAT;
531         case CKM_API_ERROR_FILE_ACCESS_DENIED:    return CKMC_ERROR_FILE_ACCESS_DENIED;
532         case CKM_API_ERROR_UNKNOWN:               return CKMC_ERROR_UNKNOWN;
533         }
534         return CKMC_ERROR_UNKNOWN;
535 }