2 * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
18 * @author Yuseok Jeon(yuseok.jeon@samsung.com)
20 * @brief new and free methods for the struct of CAPI
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 <client-common.h>
32 #include <protocols.h>
33 #include <openssl/x509v3.h>
34 #include <openssl/pkcs12.h>
35 #include <openssl/evp.h>
36 #include <openssl/pem.h>
38 #include <crypto-init.h>
39 #include <dpl/log/log.h>
40 #include <dpl/errno_string.h>
44 const size_t DEFAULT_IV_LEN = 16;
45 const size_t DEFAULT_IV_LEN_BITS = 8 * DEFAULT_IV_LEN;
46 const size_t DEFAULT_KEY_LEN_BITS = 4096;
48 int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert)
51 return CKMC_ERROR_INVALID_FORMAT;
53 BIO *bcert = BIO_new(BIO_s_mem());
55 i2d_X509_bio(bcert, xCert);
57 CKM::RawBuffer output(8196);
58 int size = BIO_read(bcert, output.data(), output.size());
62 return CKMC_ERROR_INVALID_FORMAT;
66 return ckmc_cert_new(output.data(), output.size(), CKMC_FORM_DER, cert);
69 void _ckmc_alias_info_free(ckmc_alias_info_s *info)
77 } // namespace anonymous
79 const char *const ckmc_label_name_separator = CKM::ALIAS_SEPARATOR;
80 const char *const ckmc_owner_id_separator = CKM::ALIAS_SEPARATOR;
81 const char *const ckmc_owner_id_system = CKM::CLIENT_ID_SYSTEM;
84 int ckmc_alias_new(const char *owner_id, const char *alias, char **full_alias)
86 if (owner_id == NULL || alias == NULL || full_alias == NULL)
87 return CKMC_ERROR_INVALID_PARAMETER;
89 size_t len = strlen(owner_id) + strlen(alias) + strlen(ckmc_owner_id_separator);
90 char *_full_alias = static_cast<char *>(malloc(len + 1));
92 if (_full_alias == NULL)
93 return CKMC_ERROR_OUT_OF_MEMORY;
95 strncpy(_full_alias, owner_id, len + 1);
96 strncat(_full_alias, ckmc_owner_id_separator, len - strlen(_full_alias));
97 strncat(_full_alias, alias, len - strlen(_full_alias));
99 *full_alias = _full_alias;
101 return CKMC_ERROR_NONE;
105 int ckmc_key_new(unsigned char *raw_key, size_t key_size,
106 ckmc_key_type_e key_type, char *password, ckmc_key_s **ppkey)
110 if (raw_key == NULL || key_size == 0 || ppkey == NULL)
111 return CKMC_ERROR_INVALID_PARAMETER;
113 pkey = static_cast<ckmc_key_s *>(malloc(sizeof(ckmc_key_s)));
116 return CKMC_ERROR_OUT_OF_MEMORY;
118 pkey->raw_key = reinterpret_cast<unsigned char *>(malloc(key_size));
120 if (pkey->raw_key == NULL) {
122 return CKMC_ERROR_OUT_OF_MEMORY;
125 memcpy(pkey->raw_key, raw_key, key_size);
127 pkey->key_size = key_size;
128 pkey->key_type = key_type;
130 if (password != NULL) {
131 pkey->password = strdup(password);
132 if (pkey->password == NULL) {
135 return CKMC_ERROR_OUT_OF_MEMORY;
138 pkey->password = NULL;
143 return CKMC_ERROR_NONE;
147 void ckmc_key_free(ckmc_key_s *key)
152 if (key->password != NULL)
155 if (key->raw_key != NULL) {
156 memset(key->raw_key, 0, key->key_size);
164 int ckmc_buffer_new(unsigned char *data, size_t size,
165 ckmc_raw_buffer_s **ppbuffer)
167 ckmc_raw_buffer_s *pbuff;
169 if (data == NULL || size == 0 || ppbuffer == NULL)
170 return CKMC_ERROR_INVALID_PARAMETER;
172 pbuff = static_cast<ckmc_raw_buffer_s *>(malloc(sizeof(ckmc_raw_buffer_s)));
175 return CKMC_ERROR_OUT_OF_MEMORY;
177 pbuff->data = reinterpret_cast<unsigned char *>(malloc(size));
179 if (pbuff->data == NULL) {
181 return CKMC_ERROR_OUT_OF_MEMORY;
184 memcpy(pbuff->data, data, size);
189 return CKMC_ERROR_NONE;
193 void ckmc_buffer_free(ckmc_raw_buffer_s *buffer)
198 if (buffer->data != NULL) {
199 memset(buffer->data, 0, buffer->size);
207 int ckmc_cert_new(unsigned char *raw_cert, size_t cert_size,
208 ckmc_data_format_e data_format, ckmc_cert_s **ppcert)
212 if (raw_cert == NULL || cert_size == 0 || ppcert == NULL)
213 return CKMC_ERROR_INVALID_PARAMETER;
215 pcert = static_cast<ckmc_cert_s *>(malloc(sizeof(ckmc_cert_s)));
218 return CKMC_ERROR_OUT_OF_MEMORY;
220 pcert->raw_cert = reinterpret_cast<unsigned char *>(malloc(cert_size));
222 if (pcert->raw_cert == NULL) {
224 return CKMC_ERROR_OUT_OF_MEMORY;
227 memcpy(pcert->raw_cert, raw_cert, cert_size);
229 pcert->cert_size = cert_size;
230 pcert->data_format = data_format;
233 return CKMC_ERROR_NONE;
237 int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert)
239 CKM::initOpenSslOnce();
241 FILE *fp = fopen(file_path, "r");
244 return CKMC_ERROR_FILE_ACCESS_DENIED;
248 if (!(pcert = d2i_X509_fp(fp, NULL))) {
249 if (-1 == fseek(fp, 0, SEEK_SET)) {
250 LogError("fseek() failed: " << CKM::GetErrnoString(errno));
252 return CKMC_ERROR_UNKNOWN;
255 pcert = PEM_read_X509(fp, NULL, NULL, NULL);
261 return CKMC_ERROR_INVALID_FORMAT;
263 int ret = _ckmc_load_cert_from_x509(pcert, cert);
271 void ckmc_cert_free(ckmc_cert_s *cert)
276 if (cert->raw_cert != NULL) {
277 memset(cert->raw_cert, 0, cert->cert_size);
278 free(cert->raw_cert);
285 int ckmc_pkcs12_new(ckmc_key_s *private_key, ckmc_cert_s *cert,
286 ckmc_cert_list_s *ca_cert_list, ckmc_pkcs12_s **pkcs12_bundle)
288 ckmc_pkcs12_s *pkcs12;
290 if (!pkcs12_bundle ||
291 (private_key == NULL && cert == NULL && (ca_cert_list == NULL ||
292 ca_cert_list->cert == NULL)))
293 return CKMC_ERROR_INVALID_PARAMETER;
295 pkcs12 = static_cast<ckmc_pkcs12_s *>(malloc(sizeof(ckmc_pkcs12_s)));
298 return CKMC_ERROR_OUT_OF_MEMORY;
300 // ownership is transferred into pkcs12 - mentioned in the docs
301 pkcs12->priv_key = private_key;
303 pkcs12->ca_chain = ca_cert_list;
305 *pkcs12_bundle = pkcs12;
306 return CKMC_ERROR_NONE;
310 int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase,
311 ckmc_key_s **private_key, ckmc_cert_s **ckmcert,
312 ckmc_cert_list_s **ca_cert_list)
314 class Pkcs12Converter {
325 ckmc_key_s *retPrivateKey;
326 ckmc_cert_s *retCkmCert;
327 ckmc_cert_list_s *retCaCertList;
336 ret = CKMC_ERROR_NONE;
337 retPrivateKey = NULL;
339 retCaCertList = NULL;
350 if (x509Cert != NULL)
357 sk_X509_pop_free(ca, X509_free);
359 if (ret != CKMC_ERROR_NONE) {
360 if (retPrivateKey != NULL) {
361 ckmc_key_free(retPrivateKey);
362 retPrivateKey = NULL;
365 if (retCkmCert != NULL) {
366 ckmc_cert_free(retCkmCert);
370 if (retCaCertList != NULL) {
371 ckmc_cert_list_all_free(retCaCertList);
372 retCaCertList = NULL;
377 int parsePkcs12(const char *filePath, const char *pass)
381 if (!(fp_in = fopen(filePath, "rb")))
382 return CKMC_ERROR_FILE_ACCESS_DENIED;
384 if (!(p12 = d2i_PKCS12_fp(fp_in, NULL)))
385 return CKMC_ERROR_INVALID_FORMAT;
387 /* parse PKCS#12 certificate */
388 if ((ret = PKCS12_parse(p12, pass, &pkey, &x509Cert, &ca)) != 1)
389 return CKMC_ERROR_INVALID_FORMAT;
391 return CKMC_ERROR_NONE;
396 if ((ret = _ckmc_load_cert_from_x509(x509Cert, &retCkmCert)) != CKMC_ERROR_NONE)
399 return CKMC_ERROR_NONE;
404 BIO *bkey = BIO_new(BIO_s_mem());
406 i2d_PrivateKey_bio(bkey, pkey);
408 CKM::RawBuffer output(8196);
409 int size = BIO_read(bkey, output.data(), output.size());
413 return CKMC_ERROR_INVALID_FORMAT;
417 int type = EVP_PKEY_type(pkey->type);
418 ckmc_key_type_e key_type = CKMC_KEY_NONE;
422 key_type = CKMC_KEY_RSA_PRIVATE;
426 key_type = CKMC_KEY_DSA_PRIVATE;
430 key_type = CKMC_KEY_ECDSA_PRIVATE;
434 if (key_type == CKMC_KEY_NONE)
435 return CKMC_ERROR_INVALID_FORMAT;
437 char *nullPassword = NULL;
439 return ckmc_key_new(output.data(), size, key_type, nullPassword,
443 int toCaCkmCertList()
446 X509 *popedCert = NULL;
447 ckmc_cert_s *popedCkmCert = NULL;
448 ckmc_cert_list_s *tmpCertList = NULL;
450 while ((popedCert = sk_X509_pop(ca)) != NULL) {
451 tmpRet = _ckmc_load_cert_from_x509(popedCert, &popedCkmCert);
452 X509_free(popedCert);
453 if (tmpRet != CKMC_ERROR_NONE)
454 return CKMC_ERROR_OUT_OF_MEMORY;
456 if (tmpCertList == NULL) { // first
457 tmpRet = ckmc_cert_list_new(popedCkmCert, &tmpCertList);
458 retCaCertList = tmpCertList;
460 tmpRet = ckmc_cert_list_add(tmpCertList, popedCkmCert, &tmpCertList);
463 if (tmpRet != CKMC_ERROR_NONE) {
464 ckmc_cert_list_all_free(retCaCertList);
465 retCaCertList = NULL;
470 return CKMC_ERROR_NONE;
474 LogWarning("DEPRECATION WARNING: " << __func__ << "() is deprecated and will be "
475 "removed from next release. Use ckmc_pkcs12_load() instead.");
477 CKM::initOpenSslOnce();
479 int ret = CKMC_ERROR_NONE;
481 Pkcs12Converter converter;
483 if ((ret = converter.parsePkcs12(file_path, passphrase)) != CKMC_ERROR_NONE)
486 if ((ret = converter.toCkmCert()) != CKMC_ERROR_NONE)
489 if ((ret = converter.toCkmKey()) != CKMC_ERROR_NONE)
492 if ((ret = converter.toCaCkmCertList()) != CKMC_ERROR_NONE)
495 *private_key = converter.retPrivateKey;
496 *ckmcert = converter.retCkmCert;
497 *ca_cert_list = converter.retCaCertList;
499 return CKMC_ERROR_NONE;
503 int ckmc_pkcs12_load(const char *file_path, const char *passphrase,
504 ckmc_pkcs12_s **pkcs12_bundle)
507 ckmc_key_s *private_key = 0;
508 ckmc_cert_s *cert = 0;
509 ckmc_cert_list_s *ca_cert_list = 0;
511 if (!file_path || !pkcs12_bundle)
512 return CKMC_ERROR_INVALID_PARAMETER;
514 ec = ckmc_load_from_pkcs12_file(file_path, passphrase, &private_key, &cert,
517 if (ec != CKMC_ERROR_NONE)
520 ec = ckmc_pkcs12_new(private_key, cert, ca_cert_list, pkcs12_bundle);
522 if (ec != CKMC_ERROR_NONE) {
523 ckmc_key_free(private_key);
524 ckmc_cert_free(cert);
525 ckmc_cert_list_free(ca_cert_list);
529 return CKMC_ERROR_NONE;
533 void ckmc_pkcs12_free(ckmc_pkcs12_s *pkcs12)
538 ckmc_key_free(pkcs12->priv_key);
539 ckmc_cert_free(pkcs12->cert);
540 ckmc_cert_list_all_free(pkcs12->ca_chain);
545 int ckmc_alias_list_new(char *alias, ckmc_alias_list_s **ppalias_list)
547 ckmc_alias_list_s *previous = NULL;
548 return ckmc_alias_list_add(previous, alias, ppalias_list);
552 int ckmc_alias_list_add(ckmc_alias_list_s *previous, char *alias,
553 ckmc_alias_list_s **pplast)
555 ckmc_alias_list_s *plist;
557 if (alias == NULL || pplast == NULL)
558 return CKMC_ERROR_INVALID_PARAMETER;
560 plist = static_cast<ckmc_alias_list_s *>(malloc(sizeof(ckmc_alias_list_s)));
563 return CKMC_ERROR_OUT_OF_MEMORY;
565 plist->alias = alias;
568 if (previous != NULL)
569 previous->next = plist;
573 return CKMC_ERROR_NONE;
577 void ckmc_alias_list_free(ckmc_alias_list_s *first)
579 ckmc_alias_list_s *next = first;
582 ckmc_alias_list_s *current = next;
583 next = current->next;
589 void ckmc_alias_list_all_free(ckmc_alias_list_s *first)
591 ckmc_alias_list_s *next = first;
594 ckmc_alias_list_s *current = next;
595 next = current->next;
596 free(current->alias);
602 int ckmc_alias_info_get_alias(const ckmc_alias_info_s* info, char** alias)
604 if (info == NULL || alias == NULL)
605 return CKMC_ERROR_INVALID_PARAMETER;
607 *alias = info->alias;
608 return CKMC_ERROR_NONE;
612 int ckmc_alias_info_is_password_protected(const ckmc_alias_info_s* info, bool* is_password_protected)
614 if (info == NULL || is_password_protected == NULL)
615 return CKMC_ERROR_INVALID_PARAMETER;
617 *is_password_protected = info->is_password_protected;
618 return CKMC_ERROR_NONE;
623 void ckmc_alias_info_list_all_free(ckmc_alias_info_list_s *first)
625 ckmc_alias_info_list_s *next = first;
628 ckmc_alias_info_list_s *current = next;
629 next = current->next;
630 _ckmc_alias_info_free(current->info);
636 int ckmc_cert_list_new(ckmc_cert_s *cert, ckmc_cert_list_s **ppalias_list)
638 ckmc_cert_list_s *previous = NULL;
639 return ckmc_cert_list_add(previous, cert, ppalias_list);
643 int ckmc_cert_list_add(ckmc_cert_list_s *previous, ckmc_cert_s *cert,
644 ckmc_cert_list_s **pplast)
646 ckmc_cert_list_s *plist;
648 if (cert == NULL || pplast == NULL)
649 return CKMC_ERROR_INVALID_PARAMETER;
651 plist = static_cast<ckmc_cert_list_s *>(malloc(sizeof(ckmc_cert_list_s)));
654 return CKMC_ERROR_OUT_OF_MEMORY;
659 if (previous != NULL)
660 previous->next = plist;
664 return CKMC_ERROR_NONE;
668 void ckmc_cert_list_free(ckmc_cert_list_s *first)
670 ckmc_cert_list_s *next = first;
673 ckmc_cert_list_s *current = next;
674 next = current->next;
680 void ckmc_cert_list_all_free(ckmc_cert_list_s *first)
682 ckmc_cert_list_s *next = first;
685 ckmc_cert_list_s *current = next;
686 next = current->next;
687 ckmc_cert_free(current->cert);
693 int ckmc_param_list_new(ckmc_param_list_h *pparams)
696 return CKMC_ERROR_INVALID_PARAMETER;
698 *pparams = reinterpret_cast<ckmc_param_list_h>(new(std::nothrow)(
699 CKM::CryptoAlgorithm));
702 return CKMC_ERROR_OUT_OF_MEMORY;
704 return CKMC_ERROR_NONE;
708 int ckmc_param_list_set_integer(ckmc_param_list_h params,
709 ckmc_param_name_e name,
713 return CKMC_ERROR_INVALID_PARAMETER;
715 CKM::CryptoAlgorithm *algo = reinterpret_cast<CKM::CryptoAlgorithm *>(params);
716 bool ret = algo->setParam(static_cast<CKM::ParamName>(name), value);
717 return (ret ? CKMC_ERROR_NONE : CKMC_ERROR_INVALID_PARAMETER);
721 int ckmc_param_list_set_buffer(ckmc_param_list_h params,
722 ckmc_param_name_e name,
723 const ckmc_raw_buffer_s *buffer)
725 if (!params || !buffer || !buffer->data || buffer->size == 0)
726 return CKMC_ERROR_INVALID_PARAMETER;
728 CKM::CryptoAlgorithm *algo = reinterpret_cast<CKM::CryptoAlgorithm *>(params);
729 CKM::RawBuffer b(buffer->data, buffer->data + buffer->size);
730 bool ret = algo->setParam(static_cast<CKM::ParamName>(name), b);
731 return (ret ? CKMC_ERROR_NONE : CKMC_ERROR_INVALID_PARAMETER);
735 int ckmc_param_list_get_integer(ckmc_param_list_h params,
736 ckmc_param_name_e name,
739 if (!params || !pvalue)
740 return CKMC_ERROR_INVALID_PARAMETER;
742 const CKM::CryptoAlgorithm *algo =
743 reinterpret_cast<const CKM::CryptoAlgorithm *>(params);
745 if (!algo->getParam(static_cast<CKM::ParamName>(name), *pvalue))
746 return CKMC_ERROR_INVALID_PARAMETER;
748 return CKMC_ERROR_NONE;
752 int ckmc_param_list_get_buffer(ckmc_param_list_h params,
753 ckmc_param_name_e name,
754 ckmc_raw_buffer_s **ppbuffer)
756 if (!params || !ppbuffer || *ppbuffer)
757 return CKMC_ERROR_INVALID_PARAMETER;
759 const CKM::CryptoAlgorithm *algo =
760 reinterpret_cast<const CKM::CryptoAlgorithm *>(params);
761 CKM::RawBuffer value;
763 if (!algo->getParam(static_cast<CKM::ParamName>(name), value))
764 return CKMC_ERROR_INVALID_PARAMETER;
766 return ckmc_buffer_new(value.data(), value.size(), ppbuffer);
770 void ckmc_param_list_free(ckmc_param_list_h params)
772 CKM::CryptoAlgorithm *algo = reinterpret_cast<CKM::CryptoAlgorithm *>(params);
777 int ckmc_generate_new_params(ckmc_algo_type_e type, ckmc_param_list_h *pparams)
780 return CKMC_ERROR_INVALID_PARAMETER;
782 ckmc_param_list_h params = NULL;
783 int ret = ckmc_param_list_new(¶ms);
785 if (ret != CKMC_ERROR_NONE)
789 case CKMC_ALGO_AES_CTR:
790 ret = ckmc_param_list_set_integer(params, CKMC_PARAM_ED_CTR_LEN,
791 DEFAULT_IV_LEN_BITS);
794 case CKMC_ALGO_AES_CBC:
795 case CKMC_ALGO_AES_GCM:
796 case CKMC_ALGO_AES_CFB:
797 case CKMC_ALGO_RSA_OAEP:
802 ret = CKMC_ERROR_INVALID_PARAMETER;
806 if (ret != CKMC_ERROR_NONE) {
807 ckmc_param_list_free(params);
811 ret = ckmc_param_list_set_integer(params, CKMC_PARAM_ALGO_TYPE, type);
813 if (ret != CKMC_ERROR_NONE) {
814 ckmc_param_list_free(params);
820 return CKMC_ERROR_NONE;