return NULL;
}
memset(ckm_alias, 0, alias_len + 1);
- strncat(ckm_alias, ckmc_owner_id_system, alias_len + 1);
- strncat(ckm_alias, ckmc_owner_id_separator, alias_len + 1 - strlen(ckmc_owner_id_system));
- strncat(ckm_alias, name, alias_len + 1 - strlen(ckmc_owner_id_system) + strlen(ckmc_owner_id_separator));
+ strcat(ckm_alias, ckmc_owner_id_system);
+ strcat(ckm_alias, ckmc_owner_id_separator);
+ strcat(ckm_alias, name);
return ckm_alias;
}
-int ckmc_remove_alias_with_shared_owner_prefix(const char *name, int *result)
+int ckmc_remove_alias_with_shared_owner_prefix(const char *name)
{
char *ckm_alias = add_shared_owner_prefix(name);
if (!ckm_alias) {
SLOGE("Failed to allocate memory");
- return CERTSVC_BAD_ALLOC;
+ return CKMC_ERROR_OUT_OF_MEMORY;
}
- *result = ckmc_remove_alias(ckm_alias);
+ int result = ckmc_remove_alias(ckm_alias);
free(ckm_alias);
- return CERTSVC_SUCCESS;
+ return result;
}
char *get_complete_path(const char *str1, const char *str2)
int result = ckmc_save_data(ckm_alias, cert_data, cert_policy);
free(ckm_alias);
+ if (result == CKMC_ERROR_DB_ALIAS_EXISTS) {
+ SLOGI("same alias with gname[%s] alrady exist in ckm. Maybe other store type have it. skip.", pGname);
+ return CERTSVC_SUCCESS;
+ }
+
if (result != CKMC_ERROR_NONE) {
SLOGE("Failed to save trusted data. ckm errcode[%d]", result);
return CERTSVC_FAIL;
int records = 0;
int count = 0;
int counter = 0;
- char *pValue = NULL;
+ char *gname = NULL;
char *query = NULL;
const char *text;
sqlite3_stmt *stmt = NULL;
goto error_and_exit;
}
- while (count < 4) {
+ for (count = 0; count < 4; count++) {
/* get the ssl certificate from database */
if (count == 0)
query = sqlite3_mprintf("select certificate from ssl where enabled=%d and is_root_app_enabled=%d", ENABLED, ENABLED);
((count == 1)?"wifi":(count == 2)?"vpn":"email"), ENABLED, ENABLED, ENABLED);
result = execute_select_query(db_handle, query, &stmt);
+
+ if (query) {
+ sqlite3_free(query);
+ query = NULL;
+ }
+
if (result != CERTSVC_SUCCESS) {
SLOGE("Querying database failed.");
- goto next;
+ goto error_and_exit;
}
/* update the ca-certificate.crt file */
while (1) {
records = sqlite3_step(stmt);
- if (records != SQLITE_ROW || records == SQLITE_DONE) {
+ if (records == SQLITE_DONE) {
result = CERTSVC_SUCCESS;
break;
}
- if (records == SQLITE_ROW) {
- certLength = 0;
- certBuffer = NULL;
- pValue = NULL;
-
- if (count == 0) {
- /* gets the certificate from database for system store */
- text = (const char *)sqlite3_column_text(stmt, 0);
- if (text) {
- certLength = strlen(text);
- certBuffer = strndup(text, certLength);
- }
- } else {
- /* gets the certificate from key-manager for other stores */
- text = (const char *)sqlite3_column_text(stmt, 0);
- if (text)
- pValue = strndup(text, strlen(text));
-
- result = get_certificate_buffer_from_store(db_handle, storeType[count], pValue, &certBuffer, &certLength);
- if (result != CERTSVC_SUCCESS) {
- SLOGE("Failed to get certificate buffer from key-manager.");
- goto error_and_exit;
- }
- }
+ if (records != SQLITE_ROW) {
+ SLOGE("DB query error when select. result[%d].", records);
+ result = CERTSVC_FAIL;
+ goto error_and_exit;
+ }
- if (certBuffer) {
- if (counter++ == 0)
- result = write_to_ca_cert_crt_file("wb", certBuffer, certLength);
- else
- result = write_to_ca_cert_crt_file("ab", certBuffer, certLength);
+ certLength = 0;
+ certBuffer = NULL;
+ gname = NULL;
- if (result != CERTSVC_SUCCESS) {
- SLOGE("Failed to write to file.");
- result = CERTSVC_FAIL;
- goto error_and_exit;
- }
+ if (count == 0) {
+ /* gets the certificate from database for system store */
+ text = (const char *)sqlite3_column_text(stmt, 0);
+ if (text) {
+ certLength = strlen(text);
+ certBuffer = strndup(text, certLength);
+ }
+ } else {
+ /* gets the certificate from key-manager for other stores */
+ text = (const char *)sqlite3_column_text(stmt, 0);
+ if (text)
+ gname = strndup(text, strlen(text));
+
+ result = get_certificate_buffer_from_store(db_handle, storeType[count], gname, &certBuffer, &certLength);
+ if (result != CERTSVC_SUCCESS) {
+ SLOGE("Failed to get certificate buffer from key-manager.");
+ goto error_and_exit;
}
}
- }
-next:
- count++;
- if (query) {
- sqlite3_free(query);
- query = NULL;
+
+ if (certBuffer == NULL) {
+ SLOGE("Failed to extract cert buffer to update ca-certificate.");
+ result = CERTSVC_FAIL;
+ goto error_and_exit;
+ }
+
+ if (counter++ == 0)
+ result = write_to_ca_cert_crt_file("wb", certBuffer, certLength);
+ else
+ result = write_to_ca_cert_crt_file("ab", certBuffer, certLength);
+
+ if (result != CERTSVC_SUCCESS) {
+ SLOGE("Failed to write to file.");
+ result = CERTSVC_FAIL;
+ goto error_and_exit;
+ }
}
}
+
SLOGD("Successfully updated ca-certificate.crt file.");
error_and_exit:
- if (query)
- sqlite3_free(query);
-
if (stmt)
sqlite3_finalize(stmt);
const char *pGname,
CertStatus status)
{
- int ckmc_result = CKMC_ERROR_UNKNOWN;
int result = CERTSVC_SUCCESS;
int records = 0;
size_t certSize = 0;
}
if (storeType != SYSTEM_STORE) {
- result = ckmc_remove_alias_with_shared_owner_prefix(pGname, &ckmc_result);
+ result = ckmc_remove_alias_with_shared_owner_prefix(pGname);
- if (result != CERTSVC_SUCCESS || ckmc_result != CKMC_ERROR_NONE) {
- SLOGE("Failed to delete certificate from key-manager. ckmc_result[%d]", ckmc_result);
+ if (result != CKMC_ERROR_NONE) {
+ SLOGE("Failed to delete certificate from key-manager. ckmc_result[%d]", result);
return CERTSVC_FAIL;
}
return CERTSVC_SUCCESS;
}
-int deleteCertificateFromStore(sqlite3 *db_handle, CertStoreType storeType, const char *pGname) {
-
+int deleteCertificateFromStore(sqlite3 *db_handle, CertStoreType storeType, const char *pGname)
+{
int result = CERTSVC_SUCCESS;
- int ckmc_result = CKMC_ERROR_UNKNOWN;
int records = 0;
char *query = NULL;
char *private_key_name = NULL;
sqlite3_stmt *stmt = NULL;
+ SLOGD("Remove certificate of gname[%s] in store[%d]", pGname, storeType);
+
if (!pGname) {
SLOGE("Invalid input parameter passed.");
return CERTSVC_WRONG_ARGUMENT;
}
- if (storeType != SYSTEM_STORE) {
- /* start constructing query */
- query = sqlite3_mprintf("select private_key_gname from %Q where gname=%Q", ((storeType == WIFI_STORE)? "wifi" :\
+ if (storeType == SYSTEM_STORE) {
+ SLOGE("Invalid store type passed.");
+ return CERTSVC_INVALID_STORE_TYPE;
+ }
+
+ /* start constructing query */
+ query = sqlite3_mprintf("select private_key_gname from %Q where gname=%Q", ((storeType == WIFI_STORE)? "wifi" :\
+ (storeType == VPN_STORE)? "vpn" : "email"), pGname);
+
+ result = execute_select_query(db_handle, query, &stmt);
+ if (result != CERTSVC_SUCCESS) {
+ SLOGE("Querying database failed.");
+ result = CERTSVC_FAIL;
+ goto error;
+ }
+
+ records = sqlite3_step(stmt);
+ if (records != SQLITE_ROW) {
+ SLOGE("No valid records found for passed gname [%s]. result[%d].", pGname, records);
+ result = CERTSVC_FAIL;
+ goto error;
+ }
+
+ /* if a cert is having private-key in it, the private key should
+ * be deleted first from key-manager, then the actual cert */
+ if (sqlite3_column_text(stmt, 0) != NULL)
+ private_key_name = strdup((const char *)sqlite3_column_text(stmt, 0));
+
+ query = sqlite3_mprintf("delete from disabled_certs where gname=%Q", pGname);
+ result = execute_insert_update_query(db_handle, query);
+ if (result != CERTSVC_SUCCESS) {
+ SLOGE("Unable to delete certificate entry from database. result[%d]", result);
+ goto error;
+ }
+
+ if (query) {
+ sqlite3_free(query);
+ query = NULL;
+ }
+
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ stmt = NULL;
+ }
+
+ query = sqlite3_mprintf("delete from %Q where gname=%Q", ((storeType == WIFI_STORE)? "wifi" : \
(storeType == VPN_STORE)? "vpn" : "email"), pGname);
+ result = execute_insert_update_query(db_handle, query);
+ if (result != CERTSVC_SUCCESS) {
+ SLOGE("Unable to delete certificate entry from database. result[%d]", result);
+ goto error;
+ }
+
+ if (query) {
+ sqlite3_free(query);
+ query = NULL;
+ }
+
+ if (stmt) {
+ sqlite3_finalize(stmt);
+ stmt = NULL;
+ }
+
+ CertStoreType other = ALL_STORE & ~SYSTEM_STORE & ~storeType;
+ CertStoreType current;
+ int gname_exist = 0;
+ for (current = VPN_STORE; current < SYSTEM_STORE; current <<= 1) {
+ if ((other & current) == 0)
+ continue;
+
+ query = sqlite3_mprintf("select * from %Q where gname=%Q", ((current == WIFI_STORE)? "wifi" :\
+ (current == VPN_STORE)? "vpn" : "email"), pGname);
result = execute_select_query(db_handle, query, &stmt);
if (result != CERTSVC_SUCCESS) {
SLOGE("Querying database failed.");
result = CERTSVC_FAIL;
goto error;
}
-
records = sqlite3_step(stmt);
- if ((records != SQLITE_ROW) || (records == SQLITE_DONE)) {
- SLOGE("No valid records found for passed gname [%s].",pGname);
- result = CERTSVC_FAIL;
- goto error;
+ if (records == SQLITE_ROW) {
+ SLOGI("Same gname[%s] exist on store[%d].", pGname, current);
+ gname_exist = 1;
+ break;
}
- /* if a cert is having private-key in it, the private key should
- * be deleted first from key-manager, then the actual cert */
- if (sqlite3_column_text(stmt, 0) != NULL) {
- private_key_name = strdup((const char *)sqlite3_column_text(stmt, 0));
- result = ckmc_remove_alias_with_shared_owner_prefix(private_key_name, &ckmc_result);
- if (result != CERTSVC_SUCCESS || ckmc_result != CKMC_ERROR_NONE) {
- SLOGE("Failed to delete certificate from key-manager. ckmc_result[%d]", ckmc_result);
- result = CERTSVC_FAIL;
- goto error;
- }
- }
+ sqlite3_free(query);
+ sqlite3_finalize(stmt);
+ query = NULL;
+ stmt = NULL;
+ }
- /* removing the actual cert */
- result = ckmc_remove_alias_with_shared_owner_prefix(pGname, &ckmc_result);
- if (result != CERTSVC_SUCCESS || ckmc_result != CKMC_ERROR_NONE) {
- query = sqlite3_mprintf("delete from disabled_certs where gname=%Q", pGname);
- result = execute_insert_update_query(db_handle, query);
- if (result != CERTSVC_SUCCESS) {
- SLOGE("Unable to delete certificate entry from database.");
+ if (!gname_exist) {
+ SLOGD("The gname[%s] which is in store[%d] is the last one. so remove it from ckm either.", pGname, storeType);
+
+ if (private_key_name != NULL) {
+ result = ckmc_remove_alias_with_shared_owner_prefix(private_key_name);
+ if (result != CKMC_ERROR_NONE) {
+ SLOGE("Failed to delete certificate from key-manager. ckmc_result[%d]", result);
result = CERTSVC_FAIL;
goto error;
}
}
- if (query) {
- sqlite3_free(query);
- query = NULL;
- }
-
- if (stmt) {
- sqlite3_finalize(stmt);
- stmt = NULL;
- }
-
- query = sqlite3_mprintf("delete from %Q where gname=%Q", ((storeType == WIFI_STORE)? "wifi" : \
- (storeType == VPN_STORE)? "vpn" : "email"), pGname);
-
- result = execute_insert_update_query(db_handle, query);
- if (result != CERTSVC_SUCCESS) {
- SLOGE("Unable to delete certificate entry from database.");
+ /* removing the actual cert */
+ result = ckmc_remove_alias_with_shared_owner_prefix(pGname);
+ if (result != CKMC_ERROR_NONE) {
+ SLOGE("Failed to remove data in ckm with gname[%s]. ckm_result[%d]", pGname, result);
result = CERTSVC_FAIL;
goto error;
}
- } else {
- SLOGE("Invalid store type passed.");
- result = CERTSVC_INVALID_STORE_TYPE;
}
+
SLOGD("Success in deleting the certificate from store.");
+ result = CERTSVC_SUCCESS;
error:
if (query)
sqlite3_finalize(stmt);
free(private_key_name);
+
return result;
}
* @version 1.0
* @brief PKCS#12 container manipulation routines.
*/
+
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
+#include <memory>
+#include <functional>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
#include <openssl/pem.h>
#include "dpl/log/log.h"
-#include "vcore/Certificate.h"
-#include "vcore/Client.h"
#include "cert-svc/cerror.h"
+#include "vcore/Certificate.h"
+#include "vcore/Client.h"
#include "vcore/pkcs12.h"
#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
-#define START_CERT "-----BEGIN CERTIFICATE-----"
-#define END_CERT "-----END CERTIFICATE-----"
-#define START_TRUSTED "-----BEGIN TRUSTED CERTIFICATE-----"
-#define END_TRUSTED "-----END TRUSTED CERTIFICATE-----"
-#define START_KEY "-----BEGIN PRIVATE KEY-----"
-#define END_KEY "-----END PRIVATE KEY-----"
+namespace {
-#define _CERT_SVC_VERIFY_PKCS12
+static const std::string START_CERT = "-----BEGIN CERTIFICATE-----";
+static const std::string END_CERT = "-----END CERTIFICATE-----";
+static const std::string START_TRUSTED = "-----BEGIN TRUSTED CERTIFICATE-----";
+static const std::string END_TRUSTED = "-----END TRUSTED CERTIFICATE-----";
+static const std::string START_KEY = "-----BEGIN PRIVATE KEY-----";
+static const std::string END_KEY = "-----END PRIVATE KEY-----";
+
+using ValidationCore::CertificatePtr;
+using ValidationCore::Certificate;
-static int generate_random_filepath(char **filepath)
+using FileUniquePtr = std::unique_ptr<FILE, std::function<int(FILE*)>>;
+using BioUniquePtr = std::unique_ptr<BIO, std::function<void(BIO*)>>;
+using PKEYUniquePtr = std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY*)>>;
+using X509UniquePtr = std::unique_ptr<X509, std::function<void(X509*)>>;
+using X509StackUniquePtr = std::unique_ptr<STACK_OF(X509), std::function<void(STACK_OF(X509)*)>>;
+
+void X509_stack_free(STACK_OF(X509) *stack)
{
- int generator;
- int64_t random;
- SHA_CTX ctx;
- unsigned char d[SHA_DIGEST_LENGTH];
- int result;
-
- if(!filepath)
- return CERTSVC_WRONG_ARGUMENT;
-
- SYSCALL(generator = open("/dev/urandom", O_RDONLY));
- if(generator == -1)
- return CERTSVC_FAIL;
- SYSCALL(result = read(generator, &random, sizeof(random)));
- if(result == -1) {
- SYSCALL(close(generator));
- return CERTSVC_FAIL;
- }
- SYSCALL(result = close(generator));
- if(result == -1)
- return CERTSVC_FAIL;
-
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, &random, sizeof(random));
- SHA1_Final(d, &ctx);
-
- result = asprintf(filepath, "%s/" \
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
- "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- CERTSVC_PKCS12_STORAGE_DIR,
- d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9],
- d[10], d[11], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19]);
- return (result != -1) ? CERTSVC_SUCCESS : CERTSVC_BAD_ALLOC;
+ sk_X509_free(stack);
}
-static int unique_filename(char **filepath)
+inline bool hasStore(CertStoreType types, CertStoreType type)
{
- int result;
-
- for (unsigned trial = 0x00U; trial < 0xFFU; ++trial) {
- result = generate_random_filepath(filepath);
- if (result != CERTSVC_SUCCESS)
- return result;
-
- result = access(*filepath, F_OK);
- if (result != 0)
- return CERTSVC_SUCCESS;
-
- free(*filepath);
- }
-
- return CERTSVC_FAIL;
+ return (types & type) != 0;
}
-static char *bare_filename(char *filepath)
+inline CertStoreType nextStore(CertStoreType type)
{
- char *needle;
- if(!filepath)
- return NULL;
- needle = strrchr(filepath, '/');
- if(!needle)
- return NULL;
- return *(++needle) ? needle : NULL;
+ switch (type) {
+ case NONE_STORE: return VPN_STORE;
+ case VPN_STORE: return WIFI_STORE;
+ case WIFI_STORE: return EMAIL_STORE;
+ case EMAIL_STORE: return SYSTEM_STORE;
+ case SYSTEM_STORE: return NONE_STORE;
+ default: return NONE_STORE;
+ }
}
-int read_from_file(const char *fileName, char **certBuffer, int *length)
+std::string generateGname(void)
{
- int result = CERTSVC_SUCCESS;
- FILE *fp_out = NULL;
- int certLength = 0;
- struct stat st;
-
- if (stat(fileName, &st) == -1) {
- LogError("Certificate does not exist in disable folder.");
- result = CERTSVC_FAIL;
- goto err;
+ int generator;
+ int64_t random;
+ SHA_CTX ctx;
+ unsigned char d[SHA_DIGEST_LENGTH];
+ int result;
+ char *gname = NULL;
+
+ SYSCALL(generator = open("/dev/urandom", O_RDONLY));
+ if (generator == -1)
+ return std::string();
+ SYSCALL(result = read(generator, &random, sizeof(random)));
+ if (result == -1) {
+ SYSCALL(close(generator));
+ return std::string();
}
+ SYSCALL(result = close(generator));
+ if (result == -1)
+ return std::string();
- if (!(fp_out = fopen(fileName, "rb"))) {
- LogError("Fail to open file for reading, [" << fileName << "].");
- result = CERTSVC_FAIL;
- goto err;
- }
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, &random, sizeof(random));
+ SHA1_Final(d, &ctx);
- fseek(fp_out, 0L, SEEK_END);
- certLength = ftell(fp_out);
- if (certLength < 1) {
- LogError("Fail to get certificate length.");
- result = CERTSVC_IO_ERROR;
- goto err;
- }
+ result = asprintf(&gname,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9],
+ d[10], d[11], d[12], d[13], d[14], d[15], d[16], d[17], d[18], d[19]);
- *certBuffer = (char*)malloc(sizeof(char) * ((int)certLength + 1));
- if (*certBuffer == NULL) {
- LogError("Fail to allocate memory");
- result = CERTSVC_BAD_ALLOC;
- goto err;
- }
+ if (result == -1)
+ return std::string();
- memset(*certBuffer, 0x00, certLength+1);
- rewind (fp_out);
- if (fread(*certBuffer, sizeof(char), (size_t)certLength, fp_out) != (size_t)certLength) {
- LogError("Fail to read file, [" << fileName << "]");
- result = CERTSVC_IO_ERROR;
- goto err;
- }
- *length = certLength;
+ std::string ret(gname);
- LogDebug("Success to read from file[" << fileName << "]");
+ free(gname);
-err:
- if (fp_out != NULL) {
- fclose(fp_out);
- fp_out = NULL;
- }
- return result;
+ return ret;
}
-int c_certsvc_pkcs12_set_certificate_status_to_store(CertStoreType storeType, int is_root_app, const char* gname, CertStatus status)
+std::string getCommonName(CertType type, const std::string &cert)
{
- return vcore_client_set_certificate_status_to_store(storeType, is_root_app, gname, status);
-}
+ BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
+ if (bio.get() == NULL) {
+ LogError("Failed to allocate memory.");
+ return std::string();
+ }
-int c_certsvc_pkcs12_get_certificate_buffer_from_store(CertStoreType storeType, const char* gname, char** certBuffer, size_t* certSize)
-{
- return vcore_client_get_certificate_from_store(storeType, gname, certBuffer, certSize, PEM_CRT);
-}
+ auto readCount = BIO_write(bio.get(), (const void *)cert.data(), (int)cert.length());
+ if (readCount < 1) {
+ LogError("Failed to load cert into bio.");
+ return std::string();
+ }
-int c_certsvc_pkcs12_get_certificate_status_from_store(CertStoreType storeType, const char *gname, CertStatus *status)
-{
- return vcore_client_get_certificate_status_from_store(storeType, gname, status);
-}
+ X509 *x509 = NULL;
+ switch (type) {
+ case P12_TRUSTED:
+ case P12_INTERMEDIATE:
+ x509 = PEM_read_bio_X509_AUX(bio.get(), NULL, 0, NULL);
+ break;
-int c_certsvc_pkcs12_alias_exists_in_store(CertStoreType storeType, const char *alias, int *isUnique)
-{
- return vcore_client_check_alias_exist_in_store(storeType, alias, isUnique);
-}
+ default:
+ x509 = PEM_read_bio_X509(bio.get(), NULL, 0, NULL);
+ break;
+ }
-int c_certsvc_pkcs12_private_key_load_from_store(CertStoreType storeType, const char *gname, char **certBuffer, size_t *certSize)
-{
- return vcore_client_get_certificate_from_store(storeType, gname, certBuffer, certSize, (CertType)P12_PKEY);
-}
+ if (x509 == NULL) {
+ LogError("Failed to create x509 structure.");
+ return std::string();
+ }
-int c_certsvc_pkcs12_delete_certificate_from_store(CertStoreType storeType, const char* gname)
-{
- return vcore_client_delete_certificate_from_store(storeType, gname);
-}
+ X509UniquePtr x509Ptr(x509, X509_free);
-int c_certsvc_pkcs12_get_certificate_alias_from_store(CertStoreType storeType, const char *gname, char **alias)
-{
- return vcore_client_get_certificate_alias_from_store(storeType, gname, alias);
-}
+ const char *subject_c = X509_NAME_oneline(x509->cert_info->subject, NULL, 0);
+ if (subject_c == NULL) {
+ LogError("Failed to parse x509 structure");
+ return std::string();
+ }
-int c_certsvc_pkcs12_load_certificates_from_store(CertStoreType storeType, const char *gname, char ***certs, size_t *ncerts)
-{
- return vcore_client_load_certificates_from_store(storeType, gname, certs, ncerts);
+ return std::string(subject_c);
}
-int c_certsvc_pkcs12_free_aliases_loaded_from_store(CertSvcStoreCertList** certList)
-{
- int result = CERTSVC_SUCCESS;
- CertSvcStoreCertList* tmpNode = NULL;
-
- while (*certList) {
- tmpNode = *certList;
- if (tmpNode->title)
- free(tmpNode->title);
- if (tmpNode->gname)
- free(tmpNode->gname);
- *certList = (*certList)->next;
- free(tmpNode);
- }
- return result;
-}
+/*
+ * column / common name / associated gname / prikey gname /
+ * PEM_CRT : common name / gname / none /
+ * P12_END_USER : alias / gname / prikey gname /
+ * P12_TRUSTED : common name / end cert gname / none /
+ * P12_INTERMEDIATE : common name / end cert gname / none /
+ */
-int c_certsvc_pkcs12_get_root_certificate_list_from_store(CertStoreType storeType, CertSvcStoreCertList** certList, size_t *length)
+int installPKEY(CertStoreType storeType,
+ const std::string &key,
+ const std::string &gname)
{
- return vcore_client_get_root_certificate_list_from_store(storeType, certList, length);
+ return vcore_client_install_certificate_to_store(
+ storeType,
+ gname.c_str(),
+ NULL,
+ NULL,
+ NULL,
+ key.c_str(),
+ key.length(),
+ P12_PKEY);
}
-int c_certsvc_pkcs12_get_end_user_certificate_list_from_store(CertStoreType storeType, CertSvcStoreCertList** certList, size_t *length)
+int installEndCert(CertStoreType storeType,
+ const std::string &cert,
+ const std::string &alias,
+ const std::string &gname,
+ const std::string &prikeyGname)
{
- return vcore_client_get_end_user_certificate_list_from_store(storeType, certList, length);
+ return vcore_client_install_certificate_to_store(
+ storeType,
+ gname.c_str(),
+ alias.c_str(),
+ prikeyGname.c_str(),
+ gname.c_str(),
+ cert.c_str(),
+ cert.length(),
+ P12_END_USER);
}
-int c_certsvc_pkcs12_get_certificate_list_from_store(CertStoreType storeType, int is_root_app, CertSvcStoreCertList** certList, size_t *length)
+int installChainCert(CertStoreType storeType,
+ const std::string &cert,
+ const std::string &gname,
+ const std::string &endCertGname,
+ CertType type)
{
- return vcore_client_get_certificate_list_from_store(storeType, is_root_app, certList, length);
+ std::string commonName = getCommonName(type, cert);
+
+ return vcore_client_install_certificate_to_store(
+ storeType,
+ gname.c_str(),
+ commonName.c_str(),
+ NULL,
+ endCertGname.c_str(),
+ cert.c_str(),
+ cert.length(),
+ type);
}
-
-int install_pem_file_format_to_store(CertStoreType storeType, const char *certBuffer, size_t certLength,
- const char *alias, const char* path, char *private_key_gname, char *associated_gname, CertType decideCert)
+int installCert(CertStoreType storeType,
+ const std::string &cert,
+ const std::string &gname)
{
- int result = CERTSVC_SUCCESS;
- char* fileName = NULL;
- char *unique = NULL;
- struct stat dirST;
-
- if (!certBuffer || !certLength) {
- LogError("Invalid argument. certBuffer is input cert.");
- return CERTSVC_WRONG_ARGUMENT;
- }
-
- if (decideCert == PEM_CRT) {
- result = unique_filename(&unique);
- if (result != CERTSVC_SUCCESS) {
- LogError("Fail to generate unique filename.");
- return result;
- }
- }
- else
- unique = (char*)path;
-
- if (unique == NULL) {
- LogError("Failed to get unique file name.");
- return result;
- }
-
- std::string commonName;
-
- if (stat(path, &dirST) != -1) {
- try {
- ValidationCore::CertificatePtr certPtr = ValidationCore::Certificate::createFromFile(std::string(path));
- commonName = certPtr->getCommonName();
- if (commonName.empty()) {
- LogError("CommonName is NULL");
- result = CERTSVC_FAIL;
- goto error;
- }
- LogDebug("Certificate Common name to install : " << commonName);
- } catch (const ValidationCore::Certificate::Exception::Base &e) {
- LogError("Certificate exception : " << e.DumpToString());
- result = CERTSVC_FAIL;
- goto error;
- }
- }
-
- /* storing the certificate to key-manager */
- fileName = bare_filename(unique);
- if ((decideCert == P12_END_USER) && (private_key_gname != NULL))
- result = vcore_client_install_certificate_to_store(storeType, fileName, alias, private_key_gname, fileName, certBuffer, certLength, decideCert);
- else if ((decideCert == P12_TRUSTED) || (decideCert == P12_INTERMEDIATE))
- result = vcore_client_install_certificate_to_store(storeType, fileName, commonName.c_str(), NULL, associated_gname, certBuffer, certLength, decideCert);
- else
- result = vcore_client_install_certificate_to_store(storeType, fileName, commonName.c_str(), NULL, fileName, certBuffer, certLength, decideCert);
-
- if (result != CERTSVC_SUCCESS) {
- LogError("Failed to intall certificate. result[" << result << "]");
- result = CERTSVC_FAIL;
- goto error;
- }
-
- LogDebug("Success to add certificate in store.");
-
-error:
-
- return result;
+ std::string commonName = getCommonName(PEM_CRT, cert);
+
+ return vcore_client_install_certificate_to_store(
+ storeType,
+ gname.c_str(),
+ commonName.c_str(),
+ NULL,
+ NULL,
+ cert.c_str(),
+ cert.length(),
+ PEM_CRT);
}
-int install_crt_file(
- const char *path,
- CertStoreType storeType,
- const char *alias,
- char *private_key_gname,
- char *associated_gname,
- CertType decideCert)
+std::string readFromFile(const std::string &path)
{
- int result = CERTSVC_SUCCESS;
- int fileSize = 0;
- int certLength = 0;
- const char* header = NULL;
- const char* trailer = NULL;
- char* fileContent = NULL;
- const char* tmpBuffer = NULL;
- char* certBuffer = NULL;
- const char* tailEnd = NULL;
-
- if (read_from_file(path, &fileContent, &fileSize)!=CERTSVC_SUCCESS) {
- LogError("Failed to read the file. [" << path << "]");
- result = CERTSVC_IO_ERROR;
- goto error;
+ FILE *fp = NULL;
+ if ((fp = fopen(path.c_str(), "rb")) == NULL) {
+ LogError("Fail to open file for reading : " << path);
+ return std::string();
}
- tmpBuffer = fileContent;
- if (decideCert == PEM_CRT)
- header = strstr(tmpBuffer, START_CERT);
- else if (decideCert == P12_END_USER)
- header = strstr(tmpBuffer, START_CERT);
- else if ((decideCert == P12_TRUSTED)||(decideCert == P12_INTERMEDIATE))
- header = strstr(tmpBuffer, START_TRUSTED);
- else {
- LogError("Invalid cert.");
- result = CERTSVC_IO_ERROR;
- goto error;
- }
+ FileUniquePtr filePtr(fp, fclose);
- if (header == NULL) {
- LogError("Invalid file type passed.");
- result = CERTSVC_INVALID_CERTIFICATE;
- goto error;
+ fseek(fp, 0L, SEEK_END);
+ int len = ftell(fp);
+ if (len <= 0) {
+ LogError("Fail to get certificate length.");
+ return std::string();
}
- /* Supports installation of only one certificate present in a CRT file */
- if (decideCert == PEM_CRT) {
- trailer = strstr(header, END_CERT);
- tailEnd = END_CERT;
- }
- else if (decideCert == P12_END_USER) {
- trailer = strstr(header, END_CERT);
- tailEnd = END_CERT;
- }
- else if ((decideCert == P12_TRUSTED)||(decideCert == P12_INTERMEDIATE)) {
- trailer = strstr(header, END_TRUSTED);
- tailEnd = END_TRUSTED;
- }
- else {
- LogError("Invalid certificate passed.");
- result = CERTSVC_IO_ERROR;
- goto error;
- }
+ rewind(fp);
- if (trailer == NULL) {
- LogError("Invalid certificate passed.");
- result = CERTSVC_IO_ERROR;
- goto error;
+ char *content = (char *)malloc(sizeof(char) * (len + 1));
+ if (content == NULL) {
+ LogError("Fail to allocate memory");
+ return std::string();
}
- tmpBuffer = trailer;
- certLength = ((int)(trailer - header) + strlen(tailEnd));
- certBuffer = (char*) malloc(sizeof(char) * (certLength+2));
- if (certBuffer == NULL) {
- result = CERTSVC_BAD_ALLOC;
- LogError("Fail to allocate memory.");
- goto error;
+ memset(content, 0x00, len + 1);
+ size_t readLen = fread(content, sizeof(char), (size_t)len, fp);
+ if (readLen != (size_t)len) {
+ LogError("Fail to read file : " << path);
+ free(content);
+ return std::string();
}
- memset(certBuffer, 0x00, certLength+2);
- memcpy(certBuffer, header, certLength);
- certBuffer[certLength] = '\0';
-
- result = install_pem_file_format_to_store(storeType, certBuffer, certLength, alias, \
- path, private_key_gname, associated_gname, decideCert);
- if (result != CERTSVC_SUCCESS) {
- result = CERTSVC_FAIL;
- LogError("Fail to install certificate[" << path << "]");
- }
+ content[len] = '\0';
- LogDebug("Success to install certificate[" << path << "]");
+ std::string ret(content);
-error:
- free(certBuffer);
- free(fileContent);
+ free(content);
- return result;
+ return ret;
}
-int handle_crt_pem_file_installation(CertStoreType storeType, const char *path, const char *alias)
+std::string parseCRT(const std::string &cert)
{
- int result = CERTSVC_SUCCESS;
-
- if ((strstr(path, ".crt")) != NULL || (strstr(path, ".pem")) != NULL) {
- LogDebug("certificate extention is .crt/.pem file");
-
- /* Installs CRT and PEM files. We will passing NULL for private_key_gname and associated_gname parameter in
- * install_crt_file(). Which means that there is no private key involved in the certificate which we are
- * installing and there are no other certificates related with the current certificate which is installed */
- result = install_crt_file(path, storeType, alias, NULL, NULL, PEM_CRT);
- if (result != CERTSVC_SUCCESS) {
- LogError("Failed to install the certificate.");
- result = CERTSVC_FAIL;
- goto error;
- }
+ size_t from = 0;
+ size_t to = 0;
+ size_t tailLen = 0;
+
+ from = cert.find(START_CERT);
+ to = cert.find(END_CERT);
+ tailLen = END_CERT.length();
+
+ if (from == std::string::npos || to == std::string::npos || from > to) {
+ from = cert.find(START_TRUSTED);
+ to = cert.find(END_TRUSTED);
+ tailLen = END_TRUSTED.length();
}
- else {
- LogError("Invalid certificate passed.");
- result = CERTSVC_FAIL;
- goto error;
- }
- LogDebug("Success to install the certificate.");
-error:
- return result;
+ if (from == std::string::npos || to == std::string::npos || from > to)
+ return std::string();
+
+ return std::string(cert, from, to - from + tailLen);
}
-int verify_cert_details(X509** cert, STACK_OF(X509) **certv)
+#define _CERT_SVC_VERIFY_PKCS12
+int verify_cert_details(X509 *cert, STACK_OF(X509) *certv)
{
int result = CERTSVC_SUCCESS;
char* pSubject = NULL;
int res = 0;
#ifdef _CERT_SVC_VERIFY_PKCS12
- if (*certv == NULL) {
- pSubject = X509_NAME_oneline((*cert)->cert_info->subject, NULL, 0);
+ if (certv == NULL) {
+ pSubject = X509_NAME_oneline(cert->cert_info->subject, NULL, 0);
if (!pSubject) {
LogError("Failed to get subject name");
result = CERTSVC_FAIL;
goto free_memory;
}
- pIssuerName = X509_NAME_oneline((*cert)->cert_info->issuer, NULL, 0);
+ pIssuerName = X509_NAME_oneline(cert->cert_info->issuer, NULL, 0);
if (!pIssuerName) {
LogError("Failed to get issuer name");
result = CERTSVC_FAIL;
if (strcmp((const char*)pSubject, (const char*)pIssuerName) == 0) {
/*self signed.. */
- EVP_PKEY* pKey = NULL;
- pKey = X509_get_pubkey(*cert);
+ EVP_PKEY *pKey = NULL;
+ pKey = X509_get_pubkey(cert);
if (!pKey) {
LogError("Failed to get public key");
result = CERTSVC_FAIL;
goto free_memory;
}
- if (X509_verify(*cert, pKey) <= 0) {
+ if (X509_verify(cert, pKey) <= 0) {
LogError("P12 verification failed");
EVP_PKEY_free(pKey);
result = CERTSVC_FAIL;
}
LogDebug("P12 verification Success");
EVP_PKEY_free(pKey);
- }
- else {
+ } else {
cert_store = X509_STORE_new();
if (!cert_store) {
LogError("Memory allocation failed");
}
/* construct store context */
- if (!X509_STORE_CTX_init(cert_ctx, cert_store, *cert, NULL)) {
+ if (!X509_STORE_CTX_init(cert_ctx, cert_store, cert, NULL)) {
LogError("Memory allocation failed");
result = CERTSVC_FAIL;
goto free_memory;
LogDebug("P12 verification Success");
#endif
}
- }
- else if (*certv != NULL) {
+ } else if (certv != NULL) {
/* Cert Chain */
cert_store = X509_STORE_new();
if (!cert_store) {
}
/* construct store context */
- if (!X509_STORE_CTX_init(cert_ctx, cert_store, *cert, NULL)) {
+ if (!X509_STORE_CTX_init(cert_ctx, cert_store, cert, NULL)) {
LogError("Memory allocation failed");
result = CERTSVC_FAIL;
goto free_memory;
}
- X509_STORE_CTX_trusted_stack(cert_ctx, *certv);
+ X509_STORE_CTX_trusted_stack(cert_ctx, certv);
#ifdef P12_VERIFICATION_NEEDED
res = X509_verify_cert(cert_ctx);
if (res != 1) {
#endif //_CERT_SVC_VERIFY_PKCS12
free_memory:
- if (pSubject != NULL) { free(pSubject); }
- if (pIssuerName != NULL) { free(pIssuerName); }
- if (cert_store != NULL) { X509_STORE_free(cert_store); }
- if (cert_ctx) { X509_STORE_CTX_free(cert_ctx); }
+ if (cert_store != NULL)
+ X509_STORE_free(cert_store);
+ if (cert_ctx)
+ X509_STORE_CTX_free(cert_ctx);
+
+ free(pSubject);
+ free(pIssuerName);
+
return result;
}
-int c_certsvc_pkcs12_import_from_file_to_store(CertStoreType storeTypes, const char *path, const char *password, const char *alias)
+enum class OsslType : int {
+ PKEY = 1,
+ X509,
+ X509AUX
+};
+
+std::string osslToPEM(OsslType type, void *data)
+{
+ std::vector<char> buf(4096);
+ BioUniquePtr bio(BIO_new(BIO_s_mem()), BIO_free_all);
+ if (bio.get() == NULL)
+ return std::string();
+
+ switch (type) {
+ case OsslType::PKEY:
+ PEM_write_bio_PrivateKey(bio.get(), static_cast<EVP_PKEY *>(data), NULL, NULL, 0, NULL, NULL);
+ break;
+
+ case OsslType::X509:
+ PEM_write_bio_X509(bio.get(), static_cast<X509 *>(data));
+ break;
+
+ case OsslType::X509AUX:
+ PEM_write_bio_X509_AUX(bio.get(), static_cast<X509 *>(data));
+ break;
+
+ default:
+ break;
+ }
+
+ int size = BIO_read(bio.get(), buf.data(), 4096);
+ if (size <= 0)
+ return std::string();
+
+ buf[size] = '\0';
+
+ return std::string(buf.data());
+}
+
+int extractPkcs12(const std::string &path,
+ const std::string &password,
+ PKEYUniquePtr &keyPtr,
+ X509UniquePtr &certPtr,
+ X509StackUniquePtr &certvPtr)
{
- int result = CERTSVC_SUCCESS;
- int readLen = 0;
- int tmpLen = 0;
- int wr_res;
- size_t nicerts = 0, i = 0, n = 0, ncerts = 0;
- CertStoreType storeType = NONE_STORE;
- FILE* stream = NULL;
- PKCS12* container = NULL;
- EVP_PKEY* key = NULL;
- X509* cert = NULL;
+ FILE *stream = NULL;
+ if ((stream = fopen(path.c_str(), "rb")) == NULL) {
+ LogError("Unable to open the file for reading : " << path);
+ return CERTSVC_IO_ERROR;
+ }
+
+ PKCS12 *container = d2i_PKCS12_fp(stream, NULL);
+ fclose(stream);
+ if (container == NULL) {
+ LogError("Failed to parse the input file passed.");
+ return CERTSVC_FAIL;
+ }
+
+ EVP_PKEY *key = NULL;
+ X509 *cert = NULL;
STACK_OF(X509) *certv = NULL;
- char* bare = NULL;
- char* pkvalue = NULL;
- char** cvaluev = NULL;
- char **certs = NULL;
- char* tmpPkValue = NULL;
- char* unique = NULL;
- char fileBuffer[4096] = {0,};
- int loopCount = 0;
- CertType decideCert = INVALID_DATA;
- int exists = 0;
-
- if ((!alias) || (strlen(alias) < 1) || (!path) || (strlen(path) < 1)) {
- LogError("Invalid input parameter.");
- return CERTSVC_WRONG_ARGUMENT;
+ int result = PKCS12_parse(container, password.c_str(), &key, &cert, &certv);
+ PKCS12_free(container);
+ if (result != 1) {
+ LogError("Failed to parse the file passed. openssl err : " << ERR_get_error());
+ return CERTSVC_FAIL;
+ }
+
+ keyPtr.reset(key);
+ certPtr.reset(cert);
+ certvPtr.reset(certv);
+
+ return CERTSVC_SUCCESS;
+}
+
+void rollbackStore(CertStoreType storeTypes, const std::string &endCertName)
+{
+ for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE; storeType = nextStore(storeType)) {
+ if (!hasStore(storeTypes, storeType))
+ continue;
+
+ char **certChainName = NULL;
+ size_t ncerts = 0;
+
+ int result = vcore_client_load_certificates_from_store(storeType, endCertName.c_str(), &certChainName, &ncerts);
+ if (result != CERTSVC_SUCCESS) {
+ LogError("Unable to load certificates from store. result : " << result);
+ continue;
+ }
+
+ for (size_t i = 0; i < ncerts; i++) {
+ if (certChainName[i] == NULL)
+ continue;
+
+ vcore_client_delete_certificate_from_store(storeType, certChainName[i]);
+ free(certChainName[i]);
+ }
+
+ vcore_client_delete_certificate_from_store(storeType, endCertName.c_str());
}
+}
+
+int insertToStore(CertStoreType storeTypes,
+ const std::string &alias,
+ const std::string &prikeyName,
+ const std::string &prikeyBuffer,
+ const std::string &endCertName,
+ const std::string &endCertBuffer,
+ const std::vector<std::string> &certChainName,
+ const std::vector<std::string> &certChainBuffer)
+{
+ size_t ncerts = certChainName.size();
+
+ for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE; storeType = nextStore(storeType)) {
+ if (!hasStore(storeTypes, storeType))
+ continue;
- while(1) {
- /* Iteration only possible from VPN_STORE till SYSTEM_STORE */
- if (loopCount == (MAX_STORE_ENUMS-1)) break;
+ LogDebug("Processing store type : " << storeType);
+
+ int result = installPKEY(storeType, prikeyBuffer, prikeyName);
+ if (result != CERTSVC_SUCCESS) {
+ LogError("Failed to store the private key contents. result : " << result);
+ return result;
+ }
- /* User should not install any form of certificates inside SYSTEM_STORE */
- if (((1 << loopCount) & storeTypes) == SYSTEM_STORE) {
- LogError("Not a valid store type installing certificate, store type passed [" << (1 << loopCount) << "]");
- return CERTSVC_INVALID_STORE_TYPE;
+ result = installEndCert(storeType, endCertBuffer, alias, endCertName, prikeyName);
+ if (result != CERTSVC_SUCCESS) {
+ LogError("Failed to install the end user certificate. result : " << result);
+ return result;
}
- /* Iterating over all the stores */
- if ((1 << loopCount) & storeTypes) {
- storeType = NONE_STORE;
- storeType = (CertStoreType) (1 << loopCount);
- LogDebug("Processing store type : [" << ((storeType == VPN_STORE)? "VPN" : (storeType == WIFI_STORE)? "WIFI" : "EMAIL") << "]");
+ for (size_t i = 0; i < ncerts; i++) {
+ if (i == ncerts - 1)
+ result = installChainCert(storeType, certChainBuffer[i], certChainName[i], endCertName, P12_INTERMEDIATE);
+ else
+ result = installChainCert(storeType, certChainBuffer[i], certChainName[i], endCertName, P12_TRUSTED);
- /* check if the alias exists before installing certificate */
- result = c_certsvc_pkcs12_alias_exists_in_store(storeType, alias, &exists);
if (result != CERTSVC_SUCCESS) {
- LogError("Failure to access database.");
- result = CERTSVC_FAIL;
- goto error;
+ LogError("Failed to install the ca certificates. result : " << result);
+ return result;
}
+ }
+ }
- if (exists!=CERTSVC_TRUE) {
- LogError("Alias exist in store [" << ((storeType == VPN_STORE)? "VPN" : (storeType == WIFI_STORE)? "WIFI" : "EMAIL") << "]");
- result = CERTSVC_DUPLICATED_ALIAS;
- goto error;
- }
+ LogDebug("Success to insert extracted pkcs12 data to db");
- /* Logic for handling crt/pem cert installation */
- /* Check if the input file is a PEM/CRT, since a PFX cert can also be opened without a password */
- if (password == NULL && ((strstr(path, ".pfx") == NULL) || (strstr(path, ".p12")))) {
- result = handle_crt_pem_file_installation(storeType, path, alias);
- if (result != CERTSVC_SUCCESS) {
- LogError("Failed to install PEM/CRT file to store.");
- result = CERTSVC_FAIL;
- }
- loopCount++;
- continue;
- }
+ return CERTSVC_SUCCESS;
+}
- /* Logic for handling .pfx/.p12 cert installation */
- if ((stream = fopen(path, "rb")) == NULL) {
- LogError("Unable to open the file for reading [" << path << "]");
- result = CERTSVC_IO_ERROR;
- goto error;
- }
+int insertToStorePEM(CertStoreType storeTypes, const std::string &path, const std::string &gname)
+{
+ std::string content = readFromFile(path);
+ if (content.empty()) {
+ LogError("Failed to read the file : " << path);
+ return CERTSVC_IO_ERROR;
+ }
- if (container == NULL) {
- container = d2i_PKCS12_fp(stream, NULL);
- fclose(stream);
- if (container == NULL) {
- LogError("Failed to parse the input file passed.");
- result = CERTSVC_FAIL;
- goto error;
- }
- }
+ std::string parsed = parseCRT(content);
+ if (parsed.empty()) {
+ LogError("Failed to parse CRT : " << path);
+ return CERTSVC_FAIL;
+ }
- /* To ensure when the code re-enters, we should clean up */
- if (key==NULL && cert==NULL && certv==NULL) {
- result = PKCS12_parse(container, password, &key, &cert, &certv);
- PKCS12_free(container);
- if (result == CERTSVC_FAIL) {
- LogError("Failed to parse the file passed.");
- result = CERTSVC_FAIL;
- goto error;
- }
-
- result = verify_cert_details(&cert, &certv);
- if (result == CERTSVC_FAIL) {
- LogError("Failed to verify p12 certificate.");
- goto error;
- }
- }
+ for (CertStoreType storeType = VPN_STORE; storeType < SYSTEM_STORE; storeType = nextStore(storeType)) {
+ if (!hasStore(storeTypes, storeType))
+ continue;
- if (certv) {
- int tempCertNum = sk_X509_num(certv);
- if (tempCertNum < 0)
- nicerts = 0;
- else
- nicerts = static_cast<size_t>(tempCertNum);
- } else {
- nicerts = 0;
- }
+ int result = installCert(storeType, parsed, gname);
+ if (result != CERTSVC_SUCCESS) {
+ LogError("Failed to install PEM/CRT to db store : " << storeType << " result : " << result);
+ rollbackStore(storeTypes, gname);
+ return result;
+ }
- if (cvaluev != NULL) {
- for (i = 0; i < n; i++)
- free(cvaluev[i]);
- if (cvaluev) free(cvaluev);
- cvaluev = NULL;
- }
+ LogDebug("Success to install PEM/CRT to db store : " << storeType);
+ }
- cvaluev = (char **)calloc(1 + nicerts, sizeof(char *));
- if (unique != NULL) { free(unique); unique = NULL; }
- result = unique_filename(&unique);
- if (result != CERTSVC_SUCCESS || !unique) {
- LogError("Unique filename generation failed.");
- goto error;
- }
+ LogDebug("Success to install PEM/CRT to db stores : " << storeTypes);
- if ((stream = fopen(unique, "w+")) == NULL) {
- LogError("Unable to open the file for writing [" << unique << "]");
- result = CERTSVC_IO_ERROR;
- goto error;
- }
+ return CERTSVC_SUCCESS;
+}
- result = PEM_write_PrivateKey(stream, key, NULL, NULL, 0, NULL, NULL);
- if (result == 0) {
- LogError("Writing the private key contents failed.");
- result = CERTSVC_FAIL;
- fclose(stream);
- goto error;
- }
+} // namespace anonymous
- fseek(stream, 0, SEEK_SET);
- memset(fileBuffer, 0, (sizeof(char)*4096));
- readLen=0;
- readLen = fread(fileBuffer, sizeof(char), 4096, stream);
- fclose(stream);
- if (readLen <= 0){
- LogError("Failed to read key file");
- result = CERTSVC_FAIL;
- goto error;
- }
- bare = bare_filename(unique);
- if (bare) {
- pkvalue = strdup(bare);
- tmpLen = strlen((const char*)pkvalue);
- tmpPkValue = (char*)malloc(sizeof(char) * (tmpLen + 1));
- memset(tmpPkValue, 0x00, tmpLen+1);
- memcpy(tmpPkValue, pkvalue, tmpLen);
- }
+int pkcs12_import_from_file_to_store(CertStoreType storeTypes,
+ const char *_path,
+ const char *_password,
+ const char *_alias)
+{
- decideCert = P12_PKEY;
- result = vcore_client_install_certificate_to_store(storeType, tmpPkValue, NULL, NULL, NULL, fileBuffer, readLen, decideCert);
- if (result != CERTSVC_SUCCESS) {
- LogDebug("Failed to store the private key contents.");
- result = CERTSVC_FAIL;
- goto error;
- }
+ int result = 0;
- unlink(unique);
- if (unique!=NULL) { free(unique); unique=NULL; }
- result = unique_filename(&unique);
- if (result != CERTSVC_SUCCESS || !unique) {
- LogError("Unique filename generation failed.");
- goto error;
- }
+ if (_alias == NULL || _path == NULL || strlen(_path) < 4) {
+ LogError("Invalid input parameter.");
+ return CERTSVC_WRONG_ARGUMENT;
+ }
- if ((stream = fopen(unique, "w")) == NULL) {
- LogError("Unable to open the file for writing [" << unique << "]");
- result = CERTSVC_IO_ERROR;
- goto error;
- }
+ std::string path(_path);
+ std::string alias(_alias);
+ std::string password;
+ if (_password != NULL)
+ password = std::string(_password);
- result = PEM_write_X509(stream, cert);
- fclose(stream);
- if (result == 0) {
- LogError("Failed to write contents to file.");
- result = CERTSVC_FAIL;
- goto error;
- }
+ LogDebug("pkcs12_import_from_file_to_store start. path[" << path << "] password[" << password << "] alias[" << alias << "]");
- n = 0;
- bare = bare_filename(unique);
- if (bare)
- cvaluev[n++] = strdup(bare);
+ if (storeTypes & SYSTEM_STORE) {
+ LogError("User should not install any form of certificates in SYSTEM_STORE.");
+ return CERTSVC_INVALID_STORE_TYPE;
+ }
- decideCert = P12_END_USER;
- wr_res = install_crt_file(unique, storeType, alias, tmpPkValue, NULL, decideCert);
- if (wr_res != CERTSVC_SUCCESS) {
- result = CERTSVC_FAIL;
- LogError("Failed to install the end user certificate.");
- goto error;
- }
+ /*
+ * Installs CRT and PEM files.
+ * We will passing NULL for private_key_gname and associated_gname parameter
+ * in installFilePEM(). Which means that there is no private key involved
+ * in the certificate which we are installing and there are no other
+ * certificates related with the current certificate which is installed
+ */
+ std::string suffix = path.substr(path.length() - 4, 4);
+ if (strcasecmp(suffix.c_str(), ".pem") == 0 || strcasecmp(suffix.c_str(), ".crt") == 0) {
+ std::string gnamePEM = generateGname();
+ result = insertToStorePEM(storeTypes, path, gnamePEM);
+ if (result != CERTSVC_SUCCESS)
+ LogError("Failed to install PEM/CRT file to store. gname : " << gnamePEM << " result : " << result);
+
+ return result;;
+ }
- unlink(unique);
- for (i=nicerts; i>0; i--) {
- result = unique_filename(&unique);
- if (result != CERTSVC_SUCCESS || !unique) {
- LogError("Unique filename generation failed.");
- goto error;
- }
-
- if ((stream = fopen(unique, "w")) == NULL) {
- result = CERTSVC_IO_ERROR;
- LogError("Unable to open the file for writing.");
- goto error;
- }
-
- result = PEM_write_X509_AUX(stream, sk_X509_value(certv, i-1));
- fclose(stream);
- if (result == 0) {
- result = CERTSVC_FAIL;
- LogError("Unable to extract the certificates.");
- goto error;
- }
-
- if (i==nicerts)
- decideCert = P12_INTERMEDIATE;
- else
- decideCert = P12_TRUSTED;
- wr_res = install_crt_file(unique, storeType, alias, NULL, cvaluev[0], decideCert);
- if (wr_res != CERTSVC_SUCCESS) {
- result = CERTSVC_FAIL;
- goto error;
- }
-
- unlink(unique);
- bare = bare_filename(unique);
- if (bare)
- cvaluev[n++] = strdup(bare);
- }
- }
- loopCount++;
+ LogDebug("Convert ossl type to string start");
+
+ /* 0. extract pkcs12 data from file */
+ PKEYUniquePtr key(nullptr, EVP_PKEY_free);
+ X509UniquePtr cert(nullptr, X509_free);
+ X509StackUniquePtr certv(nullptr, X509_stack_free);
+ result = extractPkcs12(path, password, key, cert, certv);
+ if (result != CERTSVC_SUCCESS) {
+ LogError("Failed to extract pkcs12 file. result : " << result);
+ return result;
}
-error:
- /* if any certificate parsing/installation fails in middle,
- * the below logic will delete the chain installed in DB */
+ LogDebug("extract pkcs12 to unique ptr success");
+
+ result = verify_cert_details(cert.get(), certv.get());
if (result != CERTSVC_SUCCESS) {
- if (nicerts > 0) {
- nicerts = 0; i = 0;
- /* cvaluev[0] holds the end user certificate identifier which will be associated
- * to chain certs. Pull the cert chain based on end user cert and delete one by one. */
- if (c_certsvc_pkcs12_load_certificates_from_store(storeType, cvaluev[0], &certs, &ncerts) != CERTSVC_SUCCESS) {
- LogError("Unable to load certificates from store.");
- return result;
- }
+ LogError("Failed to verify p12 certificate. result : " << result);
+ return result;
+ }
- for (i=0; i<ncerts; i++) {
- if (certs[i] != NULL) {
- LogDebug("file to delete : " << certs[i]);
- c_certsvc_pkcs12_delete_certificate_from_store(storeType, (char *)certs[i]);
- }
- }
+ /* 1. handling private key */
+ std::string prikeyName = generateGname();
+ std::string prikeyBuffer = osslToPEM(OsslType::PKEY, key.get());
+ if (prikeyName.empty() || prikeyBuffer.empty()) {
+ LogError("Failed to transform pkey to PEM. result : " << result);
+ return CERTSVC_FAIL;
+ }
- if (certs[i] != NULL) {
- for (i=0; i<ncerts; i++)
- free(certs[i]);
- }
+ LogDebug("Convert pkey to string success");
+
+ /* 2. handling end user certificate */
+ std::string endCertName = generateGname();
+ std::string endCertBuffer = osslToPEM(OsslType::X509, cert.get());
+ if (endCertName.empty() || endCertBuffer.empty()) {
+ LogError("Failed to transform x509 to PEM. result : " << result);
+ return CERTSVC_FAIL;
+ }
+
+ LogDebug("Convert end cert to string success");
+
+ /* 3. handling certificate chain */
+ std::vector<std::string> certChainName;
+ std::vector<std::string> certChainBuffer;
+ int ncerts = certv ? sk_X509_num(certv.get()) : 0;
+ for (int i = 0; i < ncerts; i++) {
+ std::string tempName = generateGname();
+ std::string tempBuffer = osslToPEM(OsslType::X509AUX, sk_X509_value(certv.get(), i));
+ if (tempName.empty() || tempBuffer.empty()) {
+ LogError("Failed to transform x509 AUX to PEM");
+ return CERTSVC_FAIL;
}
+
+ certChainName.push_back(std::move(tempName));
+ certChainBuffer.push_back(std::move(tempBuffer));
}
- if (key != NULL) EVP_PKEY_free(key);
- if (cert != NULL) X509_free(cert);
- if (certv != NULL) sk_X509_free(certv);
- if (pkvalue != NULL) free(pkvalue);
- if (tmpPkValue != NULL) free(tmpPkValue);
- if (unique != NULL) free(unique);
+ LogDebug("Convert cert chain to string success");
+
+ /* 4. insert extracted pkcs12 data to db */
+ result = insertToStore(storeTypes,
+ alias,
+ prikeyName,
+ prikeyBuffer,
+ endCertName,
+ endCertBuffer,
+ certChainName,
+ certChainBuffer);
+
+ if (result != CERTSVC_SUCCESS)
+ rollbackStore(storeTypes, endCertName);
+
+ LogDebug("Success to import pkcs12 to store");
+
return result;
}
-int c_certsvc_pkcs12_has_password(const char *filepath, int *passworded)
+int pkcs12_has_password(const char *filepath, int *passworded)
{
- FILE *stream;
- EVP_PKEY *pkey;
- X509 *cert;
- PKCS12 *container;
- int result;
-
- if(passworded == NULL)
- return CERTSVC_WRONG_ARGUMENT;
- if((stream = fopen(filepath, "rb")) == NULL)
- return CERTSVC_IO_ERROR;
- container = d2i_PKCS12_fp(stream, NULL);
- fclose(stream);
- if(container == NULL)
- return CERTSVC_FAIL;
- result = PKCS12_parse(container, NULL, &pkey, &cert, NULL);
- PKCS12_free(container);
- if(result == 1) {
- EVP_PKEY_free(pkey);
- X509_free(cert);
- *passworded = 0;
- return CERTSVC_SUCCESS;
- }
- else {
- if(ERR_GET_REASON(ERR_peek_last_error()) == PKCS12_R_MAC_VERIFY_FAILURE) {
- *passworded = 1;
- return CERTSVC_SUCCESS;
- }
- else
- return CERTSVC_FAIL;
- }
-}
+ if (filepath == NULL || passworded == NULL)
+ return CERTSVC_WRONG_ARGUMENT;
-void c_certsvc_pkcs12_free_certificates(char **certs)
-{
- size_t i = 0;
- if (!certs)
- return;
- while (certs[i])
- free(certs[i++]);
- free(certs);
+ FILE *stream;
+ if ((stream = fopen(filepath, "rb")) == NULL)
+ return CERTSVC_IO_ERROR;
+
+ PKCS12 *container = d2i_PKCS12_fp(stream, NULL);
+ fclose(stream);
+
+ if (container == NULL)
+ return CERTSVC_FAIL;
+
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ int result = PKCS12_parse(container, NULL, &pkey, &cert, NULL);
+
+ PKCS12_free(container);
+
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ if (cert != NULL)
+ X509_free(cert);
+
+ if (result != 1 && ERR_GET_REASON(ERR_peek_last_error()) != PKCS12_R_MAC_VERIFY_FAILURE)
+ return CERTSVC_FAIL;
+
+ *passworded = (result == 1) ? 1 : 0;
+
+ return CERTSVC_SUCCESS;
}
* limitations under the License.
*/
/*
- * @file pkcs12.c
+ * @file pkcs12.h
* @author Jacek Migacz (j.migacz@samsung.com)
* @version 1.0
* @brief PKCS#12 container manipulation routines.
*/
-#ifndef _PKCS12_H_
-#define _PKCS12_H_
+#pragma once
#include <cert-svc/ccert.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**
* To import the p12/pfx/crt/pem file to specified store (WIFI_STORE/VPN_STORE/EMAIL_STORE).
*
* @param[in] alias Logical name for certificate bundle identification (can't be empty).
* @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_DUPLICATED_ALIAS, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_BAD_ALLOC.
*/
-int c_certsvc_pkcs12_import_from_file_to_store(CertStoreType storeType, const char *path, const char *password, const char *alias);
-
-/**
- * To get the list of certificate information present in a store. User will be getting
- * the information in a linked list where every list will contain Alias, Path to certificate,
- * Certificate status of all the certificates present in the specified store.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] is_root_app If set to ENABLED, can get all the certs without any restriction (should be used only by master application).
- * If set to DISABLED, only certs which are enabled by master application can only be retrieved.
- * @param[out] certList Linked-list having all the information about each certificate present in a store.
- * @param[out] length provides the length of the linked list.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_get_certificate_list_from_store(CertStoreType storeType, int is_root_app, CertSvcStoreCertList **certList, size_t *length);
-
-/**
- * To set the status for a specified certificate in a particular store to enabled / disabled.
- * The gname is the key for accessing the certificate.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] gname Referred as group name, is the key for accessing the certificate.
- * @param[in] is_root_app Set as ENABLED/DISABLED. Enabled, if used by master application is changing the status. Disabled, should be used by other applications.
- * @param[in] status Allows to set the status of the certificate to enabled / disabled.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_set_certificate_status_to_store(CertStoreType storeType, int is_root_app, const char *gname, CertStatus status);
-
-/**
- * To get the status (enabled/disabled) for the specified certificate in a particular store.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] gname Referred as group name, is the key for accessing the certificate.
- * @param[out] status Returns the status of the certificate. It will be set Disable=0, Enable=1, Fail=-1.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_ALIAS_DOES_NOT_EXIST, CERTSVC_IO_ERROR
- */
-int c_certsvc_pkcs12_get_certificate_status_from_store(CertStoreType storeType, const char *gname, CertStatus *status);
-
-/**
- * To get the encoded form of the specified certificate from the specified store.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] gname Referred as group name, is the key for accessing the certificate.
- * @param[out] certBuffer Which will be having the encoded value of the certificate requested.
- * @param[out] certSize Which will be having the size of the buffer.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_get_certificate_buffer_from_store(CertStoreType storeType, const char *gname, char **certBuffer, size_t *certSize);
-
-/**
- * To delete the certificate from the specified store (VPN_STORE, WIFI_STORE, EMAIL_STORE, SYSTEM_STORE, ALL_STORE).
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] gname Referred as group name, is the key for accessing the certificate.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_delete_certificate_from_store(CertStoreType storeType, const char* gname);
-
-/**
- * To free the certificate list which got generated from
- * c_certsvc_pkcs12_get_certificate_list_from_store() function.
- *
- * @param[in] certList Linked-list having all the information about each certificate present in a store.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL.
- */
-int c_certsvc_pkcs12_free_aliases_loaded_from_store(CertSvcStoreCertList **certList);
-
-/**
- * Checks if the alias exist in the user store or not.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] Alias Logical name for certificate bundle identification (can't be empty).
- * @param[out] isUnique A Boolean value which states if the alias is unique or not.
- * @return CERTSVC_SUCCESS, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT.
- */
-int c_certsvc_pkcs12_alias_exists_in_store(CertStoreType storeType, const char *alias, int *isUnique);
-
-/**
- * Function to get the size of the file passed.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[in] gname Refers to unique name referring to the certificate.
- * @param[out] certs Provides the list of certificates matching the unique name provided.
- * @param[out] ncerts Provides the number of certs in certs.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_load_certificates_from_store(CertStoreType storeType, const char *gname, char ***certs, size_t *ncerts);
-
-/**
- * To load the private key for the specified certificate mapped by an Alias.
- *
- * @param[in] alias Logical name for certificate bundle identification (can't be empty).
- * @param[out] pkey Will hold the private key value of the certificate.
- * @param[out] count Will hold the siz of the private key buffer.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_BAD_ALLOC.
- */
-int c_certsvc_pkcs12_private_key_load_from_store(CertStoreType storeType, const char *gname, char **pkey, size_t *count);
-
-/**
- * Gets the alias name for the gname passed.
- *
- * @param[in] instance CertSvcInstance object.
- * @param[in] gname Certificate identification of pfx/pkcs file.
- * @param[out] alias Alias name for the given gname.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_WRONG_ARGUMENT
- */
-int c_certsvc_pkcs12_get_certificate_alias_from_store(CertStoreType storeType, const char *gname, char **alias);
-
-/**
- * To get the list of only end user certificate information present in a store. User will be getting
- * the information in a linked list where every list will contain Alias, Path to certificate,
- * Certificate status of all the certificates present in the specified store.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[out] certList Linked-list having all the information about each certificate present in a store.
- * @param[out] length provides the length of the linked list.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_get_end_user_certificate_list_from_store(CertStoreType storeType, CertSvcStoreCertList **certList, size_t *length);
-
-/**
- * To get the list of only root/trusted certificate information present in a store. User will be getting
- * the information in a linked list where every list will contain Alias, Path to certificate,
- * Certificate status of all the certificates present in the specified store.
- *
- * @param[in] storeType Refers to VPN_STORE / WIFI_STORE / EMAIL_STORE / SYSTEM_STORE / ALL_STORE.
- * @param[out] certList Linked-list having all the information about each certificate present in a store.
- * @param[out] length provides the length of the linked list.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT, CERTSVC_INVALID_STORE_TYPE.
- */
-int c_certsvc_pkcs12_get_root_certificate_list_from_store(CertStoreType storeType, CertSvcStoreCertList **certList, size_t *length);
+int pkcs12_import_from_file_to_store(CertStoreType storeType, const char *path, const char *password, const char *alias);
/**
* TO check if the p12/pfx file is protected by password or not.
* @param[out] passworded A boolean value to state if the file is protected by password or not.
* @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR, CERTSVC_WRONG_ARGUMENT.
*/
-int c_certsvc_pkcs12_has_password(const char *filepath, int *passworded);
-
-/**
- * To free the certificates from memory which was loaded by
- * c_certsvc_pkcs12_load_certificates() functon.
- *
- * @param[in] certs A pointer holding all the certificates in memory.
- * @return CERTSVC_SUCCESS, CERTSVC_FAIL, CERTSVC_IO_ERROR.
- */
-void c_certsvc_pkcs12_free_certificates(char **certs);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+int pkcs12_has_password(const char *filepath, int *passworded);