2 * Copyright (c) 2000 - 2014 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 <protocols.h>
32 #include <openssl/x509v3.h>
33 #include <openssl/pkcs12.h>
34 #include <openssl/evp.h>
35 #include <openssl/pem.h>
37 #include <crypto-init.h>
38 #include <dpl/log/log.h>
39 #include <dpl/errno_string.h>
43 const size_t DEFAULT_IV_LEN = 16;
44 const size_t DEFAULT_IV_LEN_BITS = 8 * DEFAULT_IV_LEN;
45 const size_t DEFAULT_KEY_LEN_BITS = 4096;
47 int _ckmc_load_cert_from_x509(X509 *xCert, ckmc_cert_s **cert)
50 return CKMC_ERROR_INVALID_FORMAT;
52 BIO *bcert = BIO_new(BIO_s_mem());
54 i2d_X509_bio(bcert, xCert);
56 CKM::RawBuffer output(8196);
57 int size = BIO_read(bcert, output.data(), output.size());
61 return CKMC_ERROR_INVALID_FORMAT;
65 return ckmc_cert_new(output.data(), output.size(), CKMC_FORM_DER, cert);
68 } // namespace anonymous
71 const char *const ckmc_label_name_separator = CKM::ALIAS_SEPARATOR;
72 const char *const ckmc_owner_id_separator = CKM::ALIAS_SEPARATOR;
73 const char *const ckmc_owner_id_system = CKM::CLIENT_ID_SYSTEM;
76 int ckmc_alias_new(const char *owner_id, const char *alias, char **full_alias)
78 if (owner_id == NULL || alias == NULL || full_alias == NULL)
79 return CKMC_ERROR_INVALID_PARAMETER;
81 size_t len = strlen(owner_id) + strlen(alias) + strlen(ckmc_owner_id_separator);
82 char *_full_alias = static_cast<char *>(malloc(len + 1));
84 if (_full_alias == NULL)
85 return CKMC_ERROR_OUT_OF_MEMORY;
87 strncpy(_full_alias, owner_id, len + 1);
88 strncat(_full_alias, ckmc_owner_id_separator, len - strlen(_full_alias));
89 strncat(_full_alias, alias, len - strlen(_full_alias));
91 *full_alias = _full_alias;
93 return CKMC_ERROR_NONE;
97 int ckmc_key_new(unsigned char *raw_key, size_t key_size,
98 ckmc_key_type_e key_type, char *password, ckmc_key_s **ppkey)
102 if (raw_key == NULL || key_size == 0 || ppkey == NULL)
103 return CKMC_ERROR_INVALID_PARAMETER;
105 pkey = static_cast<ckmc_key_s *>(malloc(sizeof(ckmc_key_s)));
108 return CKMC_ERROR_OUT_OF_MEMORY;
110 pkey->raw_key = reinterpret_cast<unsigned char *>(malloc(key_size));
112 if (pkey->raw_key == NULL) {
114 return CKMC_ERROR_OUT_OF_MEMORY;
117 memcpy(pkey->raw_key, raw_key, key_size);
119 pkey->key_size = key_size;
120 pkey->key_type = key_type;
122 if (password != NULL) {
123 pkey->password = strdup(password);
124 if (pkey->password == NULL) {
127 return CKMC_ERROR_OUT_OF_MEMORY;
130 pkey->password = NULL;
135 return CKMC_ERROR_NONE;
139 void ckmc_key_free(ckmc_key_s *key)
144 if (key->password != NULL)
147 if (key->raw_key != NULL) {
148 memset(key->raw_key, 0, key->key_size);
156 int ckmc_buffer_new(unsigned char *data, size_t size,
157 ckmc_raw_buffer_s **ppbuffer)
159 ckmc_raw_buffer_s *pbuff;
161 if (data == NULL || size == 0 || ppbuffer == NULL)
162 return CKMC_ERROR_INVALID_PARAMETER;
164 pbuff = static_cast<ckmc_raw_buffer_s *>(malloc(sizeof(ckmc_raw_buffer_s)));
167 return CKMC_ERROR_OUT_OF_MEMORY;
169 pbuff->data = reinterpret_cast<unsigned char *>(malloc(size));
171 if (pbuff->data == NULL) {
173 return CKMC_ERROR_OUT_OF_MEMORY;
176 memcpy(pbuff->data, data, size);
181 return CKMC_ERROR_NONE;
185 void ckmc_buffer_free(ckmc_raw_buffer_s *buffer)
190 if (buffer->data != NULL) {
191 memset(buffer->data, 0, buffer->size);
199 int ckmc_cert_new(unsigned char *raw_cert, size_t cert_size,
200 ckmc_data_format_e data_format, ckmc_cert_s **ppcert)
204 if (raw_cert == NULL || cert_size == 0 || ppcert == NULL)
205 return CKMC_ERROR_INVALID_PARAMETER;
207 pcert = static_cast<ckmc_cert_s *>(malloc(sizeof(ckmc_cert_s)));
210 return CKMC_ERROR_OUT_OF_MEMORY;
212 pcert->raw_cert = reinterpret_cast<unsigned char *>(malloc(cert_size));
214 if (pcert->raw_cert == NULL) {
216 return CKMC_ERROR_OUT_OF_MEMORY;
219 memcpy(pcert->raw_cert, raw_cert, cert_size);
221 pcert->cert_size = cert_size;
222 pcert->data_format = data_format;
225 return CKMC_ERROR_NONE;
229 int ckmc_load_cert_from_file(const char *file_path, ckmc_cert_s **cert)
231 CKM::initOpenSslOnce();
233 FILE *fp = fopen(file_path, "r");
236 return CKMC_ERROR_FILE_ACCESS_DENIED;
240 if (!(pcert = d2i_X509_fp(fp, NULL))) {
241 if (-1 == fseek(fp, 0, SEEK_SET)) {
242 LogError("fseek() failed: " << CKM::GetErrnoString(errno));
244 return CKMC_ERROR_UNKNOWN;
247 pcert = PEM_read_X509(fp, NULL, NULL, NULL);
253 return CKMC_ERROR_INVALID_FORMAT;
255 int ret = _ckmc_load_cert_from_x509(pcert, cert);
263 void ckmc_cert_free(ckmc_cert_s *cert)
268 if (cert->raw_cert != NULL) {
269 memset(cert->raw_cert, 0, cert->cert_size);
270 free(cert->raw_cert);
277 int ckmc_pkcs12_new(ckmc_key_s *private_key, ckmc_cert_s *cert,
278 ckmc_cert_list_s *ca_cert_list, ckmc_pkcs12_s **pkcs12_bundle)
280 ckmc_pkcs12_s *pkcs12;
282 if (!pkcs12_bundle ||
283 (private_key == NULL && cert == NULL && (ca_cert_list == NULL ||
284 ca_cert_list->cert == NULL)))
285 return CKMC_ERROR_INVALID_PARAMETER;
287 pkcs12 = static_cast<ckmc_pkcs12_s *>(malloc(sizeof(ckmc_pkcs12_s)));
290 return CKMC_ERROR_OUT_OF_MEMORY;
292 // ownership is transferred into pkcs12 - mentioned in the docs
293 pkcs12->priv_key = private_key;
295 pkcs12->ca_chain = ca_cert_list;
297 *pkcs12_bundle = pkcs12;
298 return CKMC_ERROR_NONE;
302 int ckmc_load_from_pkcs12_file(const char *file_path, const char *passphrase,
303 ckmc_key_s **private_key, ckmc_cert_s **ckmcert,
304 ckmc_cert_list_s **ca_cert_list)
306 class Pkcs12Converter {
317 ckmc_key_s *retPrivateKey;
318 ckmc_cert_s *retCkmCert;
319 ckmc_cert_list_s *retCaCertList;
328 ret = CKMC_ERROR_NONE;
329 retPrivateKey = NULL;
331 retCaCertList = NULL;
342 if (x509Cert != NULL)
349 sk_X509_pop_free(ca, X509_free);
351 if (ret != CKMC_ERROR_NONE) {
352 if (retPrivateKey != NULL) {
353 ckmc_key_free(retPrivateKey);
354 retPrivateKey = NULL;
357 if (retCkmCert != NULL) {
358 ckmc_cert_free(retCkmCert);
362 if (retCaCertList != NULL) {
363 ckmc_cert_list_all_free(retCaCertList);
364 retCaCertList = NULL;
369 int parsePkcs12(const char *filePath, const char *pass)
373 if (!(fp_in = fopen(filePath, "rb")))
374 return CKMC_ERROR_FILE_ACCESS_DENIED;
376 if (!(p12 = d2i_PKCS12_fp(fp_in, NULL)))
377 return CKMC_ERROR_INVALID_FORMAT;
379 /* parse PKCS#12 certificate */
380 if ((ret = PKCS12_parse(p12, pass, &pkey, &x509Cert, &ca)) != 1)
381 return CKMC_ERROR_INVALID_FORMAT;
383 return CKMC_ERROR_NONE;
388 if ((ret = _ckmc_load_cert_from_x509(x509Cert, &retCkmCert)) != CKMC_ERROR_NONE)
391 return CKMC_ERROR_NONE;
396 BIO *bkey = BIO_new(BIO_s_mem());
398 i2d_PrivateKey_bio(bkey, pkey);
400 CKM::RawBuffer output(8196);
401 int size = BIO_read(bkey, output.data(), output.size());
405 return CKMC_ERROR_INVALID_FORMAT;
409 int type = EVP_PKEY_type(pkey->type);
410 ckmc_key_type_e key_type = CKMC_KEY_NONE;
414 key_type = CKMC_KEY_RSA_PRIVATE;
418 key_type = CKMC_KEY_DSA_PRIVATE;
422 key_type = CKMC_KEY_ECDSA_PRIVATE;
426 if (key_type == CKMC_KEY_NONE)
427 return CKMC_ERROR_INVALID_FORMAT;
429 char *nullPassword = NULL;
431 return ckmc_key_new(output.data(), size, key_type, nullPassword,
435 int toCaCkmCertList()
438 X509 *popedCert = NULL;
439 ckmc_cert_s *popedCkmCert = NULL;
440 ckmc_cert_list_s *tmpCertList = NULL;
442 while ((popedCert = sk_X509_pop(ca)) != NULL) {
443 tmpRet = _ckmc_load_cert_from_x509(popedCert, &popedCkmCert);
444 X509_free(popedCert);
445 if (tmpRet != CKMC_ERROR_NONE)
446 return CKMC_ERROR_OUT_OF_MEMORY;
448 if (tmpCertList == NULL) { // first
449 tmpRet = ckmc_cert_list_new(popedCkmCert, &tmpCertList);
450 retCaCertList = tmpCertList;
452 tmpRet = ckmc_cert_list_add(tmpCertList, popedCkmCert, &tmpCertList);
455 if (tmpRet != CKMC_ERROR_NONE) {
456 ckmc_cert_list_all_free(retCaCertList);
457 retCaCertList = NULL;
462 return CKMC_ERROR_NONE;
466 LogWarning("DEPRECATION WARNING: " << __func__ << "() is deprecated and will be "
467 "removed from next release. Use ckmc_pkcs12_load() instead.");
469 CKM::initOpenSslOnce();
471 int ret = CKMC_ERROR_NONE;
473 Pkcs12Converter converter;
475 if ((ret = converter.parsePkcs12(file_path, passphrase)) != CKMC_ERROR_NONE)
478 if ((ret = converter.toCkmCert()) != CKMC_ERROR_NONE)
481 if ((ret = converter.toCkmKey()) != CKMC_ERROR_NONE)
484 if ((ret = converter.toCaCkmCertList()) != CKMC_ERROR_NONE)
487 *private_key = converter.retPrivateKey;
488 *ckmcert = converter.retCkmCert;
489 *ca_cert_list = converter.retCaCertList;
491 return CKMC_ERROR_NONE;
495 int ckmc_pkcs12_load(const char *file_path, const char *passphrase,
496 ckmc_pkcs12_s **pkcs12_bundle)
499 ckmc_key_s *private_key = 0;
500 ckmc_cert_s *cert = 0;
501 ckmc_cert_list_s *ca_cert_list = 0;
503 if (!file_path || !pkcs12_bundle)
504 return CKMC_ERROR_INVALID_PARAMETER;
506 ec = ckmc_load_from_pkcs12_file(file_path, passphrase, &private_key, &cert,
509 if (ec != CKMC_ERROR_NONE)
512 ec = ckmc_pkcs12_new(private_key, cert, ca_cert_list, pkcs12_bundle);
514 if (ec != CKMC_ERROR_NONE) {
515 ckmc_key_free(private_key);
516 ckmc_cert_free(cert);
517 ckmc_cert_list_free(ca_cert_list);
521 return CKMC_ERROR_NONE;
525 void ckmc_pkcs12_free(ckmc_pkcs12_s *pkcs12)
530 ckmc_key_free(pkcs12->priv_key);
531 ckmc_cert_free(pkcs12->cert);
532 ckmc_cert_list_all_free(pkcs12->ca_chain);
537 int ckmc_alias_list_new(char *alias, ckmc_alias_list_s **ppalias_list)
539 ckmc_alias_list_s *previous = NULL;
540 return ckmc_alias_list_add(previous, alias, ppalias_list);
544 int ckmc_alias_list_add(ckmc_alias_list_s *previous, char *alias,
545 ckmc_alias_list_s **pplast)
547 ckmc_alias_list_s *plist;
549 if (alias == NULL || pplast == NULL)
550 return CKMC_ERROR_INVALID_PARAMETER;
552 plist = static_cast<ckmc_alias_list_s *>(malloc(sizeof(ckmc_alias_list_s)));
555 return CKMC_ERROR_OUT_OF_MEMORY;
557 plist->alias = alias;
560 if (previous != NULL)
561 previous->next = plist;
565 return CKMC_ERROR_NONE;
569 void ckmc_alias_list_free(ckmc_alias_list_s *first)
571 ckmc_alias_list_s *next = first;
574 ckmc_alias_list_s *current = next;
575 next = current->next;
581 void ckmc_alias_list_all_free(ckmc_alias_list_s *first)
583 ckmc_alias_list_s *next = first;
586 ckmc_alias_list_s *current = next;
587 next = current->next;
588 free(current->alias);
594 int ckmc_cert_list_new(ckmc_cert_s *cert, ckmc_cert_list_s **ppalias_list)
596 ckmc_cert_list_s *previous = NULL;
597 return ckmc_cert_list_add(previous, cert, ppalias_list);
601 int ckmc_cert_list_add(ckmc_cert_list_s *previous, ckmc_cert_s *cert,
602 ckmc_cert_list_s **pplast)
604 ckmc_cert_list_s *plist;
606 if (cert == NULL || pplast == NULL)
607 return CKMC_ERROR_INVALID_PARAMETER;
609 plist = static_cast<ckmc_cert_list_s *>(malloc(sizeof(ckmc_cert_list_s)));
612 return CKMC_ERROR_OUT_OF_MEMORY;
617 if (previous != NULL)
618 previous->next = plist;
622 return CKMC_ERROR_NONE;
626 void ckmc_cert_list_free(ckmc_cert_list_s *first)
628 ckmc_cert_list_s *next = first;
631 ckmc_cert_list_s *current = next;
632 next = current->next;
638 void ckmc_cert_list_all_free(ckmc_cert_list_s *first)
640 ckmc_cert_list_s *next = first;
643 ckmc_cert_list_s *current = next;
644 next = current->next;
645 ckmc_cert_free(current->cert);
651 int ckmc_param_list_new(ckmc_param_list_h *pparams)
654 return CKMC_ERROR_INVALID_PARAMETER;
656 *pparams = reinterpret_cast<ckmc_param_list_h>(new(std::nothrow)(
657 CKM::CryptoAlgorithm));
660 return CKMC_ERROR_OUT_OF_MEMORY;
662 return CKMC_ERROR_NONE;
666 int ckmc_param_list_set_integer(ckmc_param_list_h params,
667 ckmc_param_name_e name,
671 return CKMC_ERROR_INVALID_PARAMETER;
673 CKM::CryptoAlgorithm *algo = reinterpret_cast<CKM::CryptoAlgorithm *>(params);
674 bool ret = algo->setParam(static_cast<CKM::ParamName>(name), value);
675 return (ret ? CKMC_ERROR_NONE : CKMC_ERROR_INVALID_PARAMETER);
679 int ckmc_param_list_set_buffer(ckmc_param_list_h params,
680 ckmc_param_name_e name,
681 const ckmc_raw_buffer_s *buffer)
683 if (!params || !buffer || !buffer->data || buffer->size == 0)
684 return CKMC_ERROR_INVALID_PARAMETER;
686 CKM::CryptoAlgorithm *algo = reinterpret_cast<CKM::CryptoAlgorithm *>(params);
687 CKM::RawBuffer b(buffer->data, buffer->data + buffer->size);
688 bool ret = algo->setParam(static_cast<CKM::ParamName>(name), b);
689 return (ret ? CKMC_ERROR_NONE : CKMC_ERROR_INVALID_PARAMETER);
693 int ckmc_param_list_get_integer(ckmc_param_list_h params,
694 ckmc_param_name_e name,
697 if (!params || !pvalue)
698 return CKMC_ERROR_INVALID_PARAMETER;
700 const CKM::CryptoAlgorithm *algo =
701 reinterpret_cast<const CKM::CryptoAlgorithm *>(params);
703 if (!algo->getParam(static_cast<CKM::ParamName>(name), *pvalue))
704 return CKMC_ERROR_INVALID_PARAMETER;
706 return CKMC_ERROR_NONE;
710 int ckmc_param_list_get_buffer(ckmc_param_list_h params,
711 ckmc_param_name_e name,
712 ckmc_raw_buffer_s **ppbuffer)
714 if (!params || !ppbuffer || *ppbuffer)
715 return CKMC_ERROR_INVALID_PARAMETER;
717 const CKM::CryptoAlgorithm *algo =
718 reinterpret_cast<const CKM::CryptoAlgorithm *>(params);
719 CKM::RawBuffer value;
721 if (!algo->getParam(static_cast<CKM::ParamName>(name), value))
722 return CKMC_ERROR_INVALID_PARAMETER;
724 return ckmc_buffer_new(value.data(), value.size(), ppbuffer);
728 void ckmc_param_list_free(ckmc_param_list_h params)
730 CKM::CryptoAlgorithm *algo = reinterpret_cast<CKM::CryptoAlgorithm *>(params);
735 int ckmc_generate_new_params(ckmc_algo_type_e type, ckmc_param_list_h *pparams)
738 return CKMC_ERROR_INVALID_PARAMETER;
740 ckmc_param_list_h params = NULL;
741 int ret = ckmc_param_list_new(¶ms);
743 if (ret != CKMC_ERROR_NONE)
747 case CKMC_ALGO_AES_CTR:
748 ret = ckmc_param_list_set_integer(params, CKMC_PARAM_ED_CTR_LEN,
749 DEFAULT_IV_LEN_BITS);
752 case CKMC_ALGO_AES_CBC:
753 case CKMC_ALGO_AES_GCM:
754 case CKMC_ALGO_AES_CFB:
755 case CKMC_ALGO_RSA_OAEP:
760 ret = CKMC_ERROR_INVALID_PARAMETER;
764 if (ret != CKMC_ERROR_NONE) {
765 ckmc_param_list_free(params);
769 ret = ckmc_param_list_set_integer(params, CKMC_PARAM_ALGO_TYPE, type);
771 if (ret != CKMC_ERROR_NONE) {
772 ckmc_param_list_free(params);
778 return CKMC_ERROR_NONE;