diff options
author | Dongsun Lee <ds73.lee@samsung.com> | 2015-05-26 09:42:38 +0900 |
---|---|---|
committer | Dongsun Lee <ds73.lee@samsung.com> | 2015-07-24 10:58:41 +0900 |
commit | 7abaa019637e0a534969d304cae7f7f43c4ab0a6 (patch) | |
tree | 9a2bb4f95b6c50ac39394abf87022d4a1a95fef2 /srcs | |
parent | d6556f8d8b13aadc9907b6609b773e29d2e22e7a (diff) | |
download | libwebappenc-7abaa019637e0a534969d304cae7f7f43c4ab0a6.tar.gz libwebappenc-7abaa019637e0a534969d304cae7f7f43c4ab0a6.tar.bz2 libwebappenc-7abaa019637e0a534969d304cae7f7f43c4ab0a6.zip |
initial version
Change-Id: Ibb7891bee67bdd82f34187f5da2fc3c4bbfa8fcd
Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
Diffstat (limited to 'srcs')
-rw-r--r-- | srcs/CMakeLists.txt | 67 | ||||
-rw-r--r-- | srcs/crypto_service.c | 372 | ||||
-rw-r--r-- | srcs/crypto_service.h | 57 | ||||
-rw-r--r-- | srcs/key_handler.c | 744 | ||||
-rw-r--r-- | srcs/key_handler.h | 86 | ||||
-rw-r--r-- | srcs/wae_initializer.c | 47 | ||||
-rw-r--r-- | srcs/wae_log.h | 38 | ||||
-rw-r--r-- | srcs/web_app_enc.c | 213 |
8 files changed, 1624 insertions, 0 deletions
diff --git a/srcs/CMakeLists.txt b/srcs/CMakeLists.txt new file mode 100644 index 0000000..e94a7d4 --- /dev/null +++ b/srcs/CMakeLists.txt @@ -0,0 +1,67 @@ +################################################################################ +# for libwebappenc.so +################################################################################ + +SET(WEB_APP_ENC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/web_app_enc.c + ${CMAKE_CURRENT_SOURCE_DIR}/key_handler.c + ${CMAKE_CURRENT_SOURCE_DIR}/crypto_service.c +) + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/include + ${WEB_APP_ENC_DEPS_INCLUDE_DIRS} +) + +ADD_LIBRARY(${TARGET_WEBAPPENC} SHARED ${WEB_APP_ENC_SOURCES}) + +SET_TARGET_PROPERTIES(${TARGET_WEBAPPENC} PROPERTIES + SOVERSION ${SO_VERSION} + VERSION ${VERSION} +) + +TARGET_LINK_LIBRARIES(${TARGET_WEBAPPENC} + pthread + ${WEB_APP_ENC_DEPS_LIBRARIES} +) + +INSTALL(TARGETS ${TARGET_WEBAPPENC} + DESTINATION ${LIBDIR}) + +INSTALL(FILES ${PROJECT_SOURCE_DIR}/include/web_app_enc.h + DESTINATION ${INCLUDEDIR}) + + +################################################################################ +# for wae-initializer +################################################################################ + + +SET(WAE_INITIALIZER_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/wae_initializer.c +) + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR}/include + ${WEB_APP_ENC_DEPS_INCLUDE_DIRS} +) + +# -fPIE and -pie flag is added for ASLR +SET_SOURCE_FILES_PROPERTIES( + ${WAE_INITIALIZER_SOURCES} + PROPERTIES + COMPILE_FLAGS "-D_GNU_SOURCE -fvisibility=hidden -fPIE") + +ADD_EXECUTABLE(${TARGET_WAE_INITIALIZER} ${WAE_INITIALIZER_SOURCES}) + + +TARGET_LINK_LIBRARIES(${TARGET_WAE_INITIALIZER} + pthread + ${WEB_APP_ENC_DEPS_LIBRARIES} + ${TARGET_WEBAPPENC} + -pie +) + +INSTALL(TARGETS ${TARGET_WAE_INITIALIZER} + DESTINATION ${BINDIR}) + diff --git a/srcs/crypto_service.c b/srcs/crypto_service.c new file mode 100644 index 0000000..eb1fc20 --- /dev/null +++ b/srcs/crypto_service.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file crypto_service.c + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief provides encryption and decription operations. + */ + +#include <openssl/evp.h> +#include <openssl/rand.h> +#include <openssl/crypto.h> +#include <openssl/err.h> +#include <openssl/bio.h> +#include <openssl/evp.h> +#include <openssl/pem.h> +#include <openssl/rsa.h> + +#include "web_app_enc.h" +#include "wae_log.h" + +#define AES_256_KEY_SIZE 32 + +#define WAE_FALSE 0 +#define WAE_TRUE 1 + +static unsigned char AES_CBC_IV[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; + +static int __initialized = WAE_FALSE; + +void _initialize() +{ + if(__initialized != WAE_TRUE) { + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + __initialized = WAE_TRUE; + } +} + + + +int encrypt_app_dek(const unsigned char* rsaPublicKey, size_t pubKeyLen, + const unsigned char* dek, size_t dekLen, + unsigned char** encryptedDek, size_t* encryptedDekLen) +{ + int ret = WAE_ERROR_NONE; + EVP_PKEY *pKey = NULL; + BIO* bio = NULL; + EVP_PKEY_CTX *ctx = NULL; + unsigned char* out = NULL; + size_t outLen = 0; + + _initialize(); + + bio = BIO_new(BIO_s_mem()); + BIO_write(bio, rsaPublicKey, pubKeyLen); + pKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + + if(pKey == NULL){ + BIO_reset(bio); + BIO_write(bio, rsaPublicKey, pubKeyLen); + pKey = d2i_PUBKEY_bio(bio, NULL); + } + + if(pKey == NULL) { + ret = WAE_ERROR_FILE; + WAE_SLOGE("Failt to convert to public key."); + goto error; + } + + ctx = EVP_PKEY_CTX_new(pKey, NULL); + if(ctx == NULL) { + WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_new failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + if (EVP_PKEY_encrypt_init(ctx) <= 0) { + WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt_init failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { + WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + /* Determine buffer length */ + if (EVP_PKEY_encrypt(ctx, NULL, &outLen, dek, dekLen) <= 0) { + WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + out = OPENSSL_malloc(outLen); + if(out == NULL) { + WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed"); + ret = WAE_ERROR_MEMORY; + goto error; + } + + if (EVP_PKEY_encrypt(ctx, out, &outLen, dek, dekLen) <= 0) { + WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + *encryptedDek = out; + *encryptedDekLen = outLen; + +error: + if(bio != NULL) + BIO_free(bio); + if(pKey != NULL) + EVP_PKEY_free(pKey); + if(ctx != NULL) + EVP_PKEY_CTX_free(ctx); + if(ret != WAE_ERROR_NONE && out != NULL) + OPENSSL_free(out); + + return ret; +} + +int decrypt_app_dek(const unsigned char* rsaPrivateKey, size_t priKeyLen, + const char* priKeyPassword, + const unsigned char* encryptedDek, size_t dencryptedDekLen, + unsigned char** decryptedDek, size_t* decryptedDekLen) +{ + int ret = WAE_ERROR_NONE; + EVP_PKEY *pKey = NULL; + BIO* bio = NULL; + EVP_PKEY_CTX *ctx = NULL; + unsigned char* out = NULL; + size_t outLen = 0; + + _initialize(); + + bio = BIO_new(BIO_s_mem()); + BIO_write(bio, rsaPrivateKey, priKeyLen); + pKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)priKeyPassword); + + if(pKey == NULL) { + BIO_reset(bio); + BIO_write(bio, rsaPrivateKey, priKeyLen); + pKey = d2i_PrivateKey_bio(bio, NULL); + } + + if(pKey == NULL) { + ret = WAE_ERROR_FILE; + WAE_SLOGE("Failt to convert to public key."); + goto error; + } + + ctx = EVP_PKEY_CTX_new(pKey, NULL); + if(ctx == NULL) { + WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_new failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + if (EVP_PKEY_decrypt_init(ctx) <= 0) { + WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt_init failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { + WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + /* Determine buffer length */ + if (EVP_PKEY_decrypt(ctx, NULL, &outLen, encryptedDek, dencryptedDekLen) <= 0) { + WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + out = OPENSSL_malloc(outLen); + if(out == NULL) { + WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed"); + ret = WAE_ERROR_MEMORY; + goto error; + } + + if (EVP_PKEY_decrypt(ctx, out, &outLen, encryptedDek, dencryptedDekLen) <= 0) { + WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_decrypt failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + *decryptedDek = out; + *decryptedDekLen = outLen; + +error: + if(bio != NULL) + BIO_free(bio); + if(pKey != NULL) + EVP_PKEY_free(pKey); + if(ctx != NULL) + EVP_PKEY_CTX_free(ctx); + if(ret != WAE_ERROR_NONE && out != NULL) + OPENSSL_free(out); + + return ret; +} + + +int encrypt_aes_cbc(const unsigned char* pKey, size_t keyLen, + const unsigned char* pData, size_t dataLen, + unsigned char** ppEncryptedData, size_t* pEncDataLen) +{ + EVP_CIPHER_CTX *ctx; + int len; + unsigned char *ciphertext = NULL; + size_t ciphertext_len; + unsigned char *iv = AES_CBC_IV; + int ret = WAE_ERROR_NONE; + + _initialize(); + + WAE_SLOGI("Encryption Started. size=%d", dataLen); + /* check input paramter */ + if( keyLen != 32 ) { + WAE_SLOGE("Encryption Failed. Invalid Key Length. keyLen=%d", keyLen); + return WAE_ERROR_INVALID_PARAMETER; + } + + // assing a enough memory for decryption. + ciphertext = (unsigned char*) malloc(dataLen + 32); + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) { + WAE_SLOGE("Encryption Failed. EVP_CIPHER_CTX_new failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + /* Initialise the encryption operation. IMPORTANT - ensure you use a key + * and IV size appropriate for your cipher + * In this example we are using 256 bit AES (i.e. a 256 bit key). The + * IV size for *most* modes is the same as the block size. For AES this + * is 128 bits */ + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) { + WAE_SLOGE("Encryption Failed. EVP_EncryptInit_ex failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + /* Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, pData, dataLen)) { + WAE_SLOGE("Encryption Failed. EVP_EncryptUpdate failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + ciphertext_len = len; + + /* Finalise the encryption. Further ciphertext bytes may be written at + * this stage. + */ + if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { + WAE_SLOGE("Encryption Failed. EVP_EncryptFinal_ex failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + ciphertext_len += len; + + *ppEncryptedData = ciphertext; + *pEncDataLen = ciphertext_len; + + ret = WAE_ERROR_NONE; + WAE_SLOGI("Encryption Ended Successfully. encrypted_len", ciphertext_len); +error: + if(ctx != NULL) + EVP_CIPHER_CTX_free(ctx); + if(ret != WAE_ERROR_NONE && ciphertext != NULL) + free(ciphertext); + return ret; +} + +int decrypt_aes_cbc(const unsigned char* pKey, size_t keyLen, + const unsigned char* pData, size_t dataLen, + unsigned char** ppDecryptedData, size_t* pDecDataLen) +{ + EVP_CIPHER_CTX *ctx; + int len; + unsigned char* plaintext = NULL; + size_t plaintext_len; + unsigned char *iv = AES_CBC_IV; + int ret = WAE_ERROR_NONE; + + _initialize(); + + WAE_SLOGI("Decryption Started. size=%d", dataLen); + + /* check input paramter */ + if( keyLen != 32 ) { + WAE_SLOGE("Decryption Failed. Invalid Key Length. keyLen=%d", keyLen); + return WAE_ERROR_INVALID_PARAMETER; + } + + // assing a enough memory for decryption. + plaintext = (unsigned char*) malloc(dataLen); + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) { + WAE_SLOGE("Decryption Failed. EVP_CIPHER_CTX_new failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + /* Initialise the decryption operation. IMPORTANT - ensure you use a key + * and IV size appropriate for your cipher + * In this example we are using 256 bit AES (i.e. a 256 bit key). The + * IV size for *most* modes is the same as the block size. For AES this + * is 128 bits */ + if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) { + WAE_SLOGE("Decryption Failed. EVP_DecryptInit_ex failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + + /* Provide the message to be decrypted, and obtain the plaintext output. + * EVP_DecryptUpdate can be called multiple times if necessary + */ + if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, pData, dataLen)) { + WAE_SLOGE("Decryption Failed. EVP_DecryptUpdate failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + plaintext_len = len; + + /* Finalise the decryption. Further plaintext bytes may be written at + * this stage. + */ + if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) { + WAE_SLOGE("Decryption Failed. EVP_DecryptFinal_ex failed"); + ret = WAE_ERROR_CRYPTO; + goto error; + } + plaintext_len += len; + + *ppDecryptedData = plaintext; + *pDecDataLen = plaintext_len; + + ret = WAE_ERROR_NONE; + WAE_SLOGI("Decryption Ended Successfully. decrypted_len", plaintext_len); +error: + if(ctx != NULL) + EVP_CIPHER_CTX_free(ctx); + if(ret != WAE_ERROR_NONE && plaintext != NULL) + free(plaintext); + return ret; +} + diff --git a/srcs/crypto_service.h b/srcs/crypto_service.h new file mode 100644 index 0000000..c49c34b --- /dev/null +++ b/srcs/crypto_service.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file crypto_service.h + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief a header for key manupulatation. + */ + + + +#ifndef __TIZEN_CORE_WAE_CRYPTO_SERVICE_H +#define __TIZEN_CORE_WAE_CRYPTO_SERVICE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> + + +int encrypt_app_dek(const unsigned char* rsaPublicKey, size_t pubKeyLen, + const unsigned char* dek, const int dekLen, + unsigned char** encryptedDek, size_t* encryptedDekLen); + +int decrypt_app_dek(const unsigned char* rsaPrivateKey, size_t priKeyLen, + const char* priKeyPassword, + const unsigned char* encryptedDek, size_t dencryptedDekLen, + unsigned char** decryptedDek, size_t* decryptedDekLen); + + +int encrypt_aes_cbc(const unsigned char* pKey, size_t keyLen, + const unsigned char* pData, size_t dataLen, + unsigned char** ppEncryptedData, size_t* pEncDataLen); + +int decrypt_aes_cbc(const unsigned char* pKey, size_t keyLen, + const unsigned char* pData, size_t dataLen, + unsigned char** ppDecryptedData, size_t* pDecDataLen); + +#ifdef __cplusplus +} +#endif +#endif /* __TIZEN_CORE_WAE_CRYPTO_SERVICE_H */ + diff --git a/srcs/key_handler.c b/srcs/key_handler.c new file mode 100644 index 0000000..4ec4e5c --- /dev/null +++ b/srcs/key_handler.c @@ -0,0 +1,744 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file key_handler.c + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief a header for key manupulatation. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <ckmc/ckmc-manager.h> +#include "wae_log.h" +#include "web_app_enc.h" +#include "key_handler.h" +#include "crypto_service.h" + +#include <tzplatform_config.h> + +#define APP_DEK_KEK_PRIKEY_PASSWORD "wae_appdek_kek_1q2w3e4r" + + +typedef struct _dek_cache_element{ + char pkgId[MAX_PKGID_LEN]; + unsigned char dek[DEK_LEN]; +} dek_cache_element; + +dek_cache_element APP_DEK_CACHE[MAX_CACHE_SIZE]; +int NEXT_CACHE_IDX = -1; + +void _initialize_cache() +{ + NEXT_CACHE_IDX = 0; + memset(APP_DEK_CACHE, 0, sizeof(dek_cache_element)*MAX_CACHE_SIZE); +} + +unsigned char* _get_app_dek_from_cache(const char* pkgId) +{ + int i = 0; + + if(NEXT_CACHE_IDX < 0) + _initialize_cache(); + + for(i =0; i<MAX_CACHE_SIZE; i++) { + //WAE_SLOGI("CACHED APP_DEK[%d]=%s", i, APP_DEK_CACHE[i].pkgId); + if( strlen(APP_DEK_CACHE[i].pkgId) == strlen(pkgId) && + strncmp(pkgId, APP_DEK_CACHE[i].pkgId, strlen(pkgId)) == 0) { + return APP_DEK_CACHE[i].dek; + } + } + return NULL; +} + +void _add_app_dek_to_cache(const char* pkgId, unsigned char* dek) +{ + int i = 0; + + if(NEXT_CACHE_IDX < 0) + _initialize_cache(); + + // if existing one has the same pkgid + for(i =0; i<MAX_CACHE_SIZE; i++) { + if( strlen(APP_DEK_CACHE[i].pkgId) == strlen(pkgId) && + strncmp(pkgId, APP_DEK_CACHE[i].pkgId, strlen(pkgId)) == 0) { + memcpy(APP_DEK_CACHE[i].dek, dek, DEK_LEN); + return; + } + } + + // for new pkgid + strncpy(APP_DEK_CACHE[NEXT_CACHE_IDX].pkgId, pkgId, strlen(pkgId)); + memcpy(APP_DEK_CACHE[NEXT_CACHE_IDX].dek, dek, DEK_LEN); + + NEXT_CACHE_IDX++; + if(NEXT_CACHE_IDX >= MAX_CACHE_SIZE) + NEXT_CACHE_IDX = 0; +} + +void _remove_app_dek_from_cache(const char* pkgId) +{ + int i = 0; + + for(i =0; i<MAX_CACHE_SIZE; i++) { + if( strlen(APP_DEK_CACHE[i].pkgId) == strlen(pkgId) && + strncmp(pkgId, APP_DEK_CACHE[i].pkgId, strlen(pkgId)) == 0) { + memset(APP_DEK_CACHE[i].pkgId, 0, sizeof(APP_DEK_CACHE[i].pkgId)); + return; + } + } + +} + +int _to_wae_error(int key_manager_error) +{ + switch(key_manager_error) { + case CKMC_ERROR_NONE: return WAE_ERROR_NONE; + case CKMC_ERROR_INVALID_PARAMETER: return WAE_ERROR_INVALID_PARAMETER; + case CKMC_ERROR_PERMISSION_DENIED: return WAE_ERROR_PERMISSION_DENIED; + case CKMC_ERROR_DB_ALIAS_UNKNOWN: return WAE_ERROR_NO_KEY; + case CKMC_ERROR_DB_ALIAS_EXISTS: return WAE_ERROR_KEY_EXISTS; + default: return WAE_ERROR_KEY_MANAGER; + } +} + +int _get_random(size_t length, unsigned char* random) +{ + FILE* f = NULL; + size_t i = 0; + int ch = 0; + //read random file + if((f = fopen(RANDOM_FILE, "r")) != NULL){ + while( i < length){ + if((ch = fgetc(f)) == EOF){ + break; + } + random[i] = (unsigned char) ch; + i++; + } + } + if(f != NULL) + fclose(f); + return WAE_ERROR_NONE; +} + +void _get_alias(const char* pPkgId, char* alias, size_t buff_len) +{ + snprintf(alias, buff_len, "%s%s%s%s", + ckmc_label_shared_owner, + ckmc_label_name_separator, + APP_DEK_ALIAS_PFX, + pPkgId); +} + +void _get_dek_kek_alias(char* alias, size_t buff_len) +{ + snprintf(alias, buff_len, "%s%s%s", + ckmc_label_shared_owner, + ckmc_label_name_separator, + APP_DEK_KEK_ALIAS); +} + +void _get_dek_loading_done_alias(char* alias, size_t buff_len) +{ + snprintf(alias, buff_len, "%s%s%s", + ckmc_label_shared_owner, + ckmc_label_name_separator, + APP_DEK_LOADING_DONE_ALIAS); +} + +const char* _get_dek_kek_pub_key_path() +{ + return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem"); +} + +const char* _get_dek_kek_pri_key_path() +{ + return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem"); +} + +const char* _get_dek_store_path() +{ + return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek"); +} + +int _add_dek_to_key_manager(const char* pPkgId, const unsigned char* pDek, size_t len) +{ + int ret = WAE_ERROR_NONE; + char alias[MAX_ALIAS_LEN] = {0,}; + ckmc_raw_buffer_s buff; + ckmc_policy_s policy; + + buff.data = (unsigned char *)pDek; + buff.size = len; + + policy.password = NULL; + policy.extractable = true; + + // save app_dek in key_manager + _get_alias(pPkgId, alias, sizeof(alias)); + + // even if it fails to remove, ignore it. + ret = _to_wae_error( ckmc_remove_alias(alias)); + + ret = _to_wae_error(ckmc_save_data(alias, buff, policy)); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to add APP_DEK to key-manager. pkgId=%s, ret=%d", pPkgId, ret); + goto error; + } + + // share app_dek for web app laucher to use app_dek + ret = _to_wae_error(ckmc_set_permission(alias, pPkgId, CKMC_PERMISSION_READ)); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to set_permission to APP_DEK. pkgId=%s, ret=%d", pPkgId, ret); + goto error; + } + WAE_SLOGI("Success to add APP_DEK to key-manager. pkgId=%s", pPkgId); +error: + return ret; +} + + +int _get_preloaded_app_dek_file_path(const char* pPkgId, char *path) +{ + sprintf(path, "%s/%s_%s.adek", _get_dek_store_path(), APP_DEK_FILE_PFX, pPkgId); + return WAE_ERROR_NONE; +} + +int _extract_pkg_id_from_file_name(const char* fileName, char* pkgId) +{ + char* start = strstr(fileName, APP_DEK_FILE_PFX); + if(start == NULL){ + WAE_SLOGE("Fail to extract pkgid from APP_DEK file. fileName=%s", fileName); + return WAE_ERROR_FILE; + } + start = start + strlen(APP_DEK_FILE_PFX) + 1; + char* end = strstr(fileName, ".adek"); + if(start == NULL){ + WAE_SLOGE("Fail to extract pkgid from APP_DEK file. fileName=%s", fileName); + return WAE_ERROR_FILE; + } + strncpy(pkgId, start, end-start); + pkgId[end-start] = 0;//terminate string + return WAE_ERROR_NONE; +} + +int _read_encrypted_app_dek_from_file(const char* pPkgId, unsigned char** encrypted_app_dek, size_t *len) +{ + char path[MAX_PATH_LEN] = {0,}; + _get_preloaded_app_dek_file_path(pPkgId, path); + return _read_from_file(path, encrypted_app_dek, len); +} + +int _write_encrypted_app_dek_to_file(const char* pPkgId, const unsigned char* encrypted_app_dek, size_t len) +{ + char path[MAX_PATH_LEN] = {0,}; + _get_preloaded_app_dek_file_path(pPkgId, path); + return _write_to_file( path, encrypted_app_dek, len); +} + +int _read_from_file(const char* path, unsigned char** data, size_t* len) +{ + int ret = WAE_ERROR_NONE; + FILE* f = NULL; + int file_len = -1; + unsigned char* file_contents = NULL; + int ch = 0; + int i = 0; + + f = fopen(path, "r"); + if( f == NULL) { + WAE_SLOGE("Fail to open a file. file=%s", path); + ret = WAE_ERROR_FILE; + goto error; + } + + fseek(f, 0, SEEK_END); // move to the end of a file + file_len = ftell(f); + fseek(f, 0, SEEK_SET); // move to the start of a file + + file_contents = (unsigned char*) malloc(file_len); + if(file_contents == NULL) { + WAE_SLOGE("Fail to allocate memory for encrypted_app_dek"); + ret = WAE_ERROR_MEMORY; + goto error; + } + memset(file_contents, 0x00, file_len); + + while( (ch = fgetc(f)) != EOF) { + file_contents[i++]=(char)ch; + } + + *data = file_contents; + *len = file_len; + +error: + if(f != NULL) + fclose(f); + if(ret != WAE_ERROR_NONE && file_contents != NULL) + free(file_contents); + + return ret; +} + +int _write_to_file(const char* path, const unsigned char* data, size_t len) +{ + int ret = WAE_ERROR_NONE; + + FILE* f = NULL; + int write_len = -1; + + f = fopen(path, "w"); + if( f == NULL) { + WAE_SLOGE("Fail to open a file. file=%s", path); + ret = WAE_ERROR_FILE; + goto error; + } + + write_len = fwrite(data, 1, len, f); + if(write_len != (int) len) { + WAE_SLOGE("Fail to write a file. file=%s", path); + ret = WAE_ERROR_FILE; + goto error; + } +error: + if(f != NULL) + fclose(f); + + return ret; +} + +int get_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen) +{ + int ret = WAE_ERROR_NONE; + + char* password = NULL; + ckmc_raw_buffer_s *pDekBuffer = NULL; + char alias[MAX_ALIAS_LEN] = {0,}; + unsigned char* pDek = NULL; + unsigned char* cached_dek = NULL; + + // get dek from cache + cached_dek = _get_app_dek_from_cache(pPkgId); + if(cached_dek == NULL) { + // get APP_DEK from system database + _get_alias(pPkgId, alias, sizeof(alias)); + + ret = _to_wae_error(ckmc_get_data(alias, password, &pDekBuffer)); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to get APP_DEK from key-manager. alias=%s, ret=%d", alias, ret); + goto error; + } + } + + pDek = (unsigned char*) malloc(DEK_LEN); + if(pDek == NULL) { + WAE_SLOGE("Fail to allocate a memory"); + ret = WAE_ERROR_MEMORY; + goto error; + } + memcpy(pDek, (cached_dek != NULL) ? cached_dek : pDekBuffer->data, DEK_LEN); + + *ppDek = pDek; + *dekLen = DEK_LEN; + WAE_SLOGI("Success to get APP_DEK from key-manager. pkgId=%s", pPkgId); +error: + if(pDekBuffer != NULL) + ckmc_buffer_free(pDekBuffer); + if(ret != WAE_ERROR_NONE && pDek != NULL) + free(pDek); + + return ret; +} + +int create_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen) +{ + int ret = WAE_ERROR_NONE; + unsigned char *dek= NULL; + + dek = (unsigned char*) malloc(DEK_LEN); + if(dek == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } + + ret = _get_random(DEK_LEN, dek); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to get random for APP_DEK. pkgId=%s, ret=%d", pPkgId, ret); + goto error; + } + + // save app_dek in key_manager + ret = _add_dek_to_key_manager(pPkgId, dek, DEK_LEN); + if(ret != WAE_ERROR_NONE) { + goto error; + } + + // store APP_DEK in cache + _add_app_dek_to_cache(pPkgId, dek); + + *ppDek = dek; + *dekLen = DEK_LEN; + + WAE_SLOGI("Success to create APP_DEK and store it in key-manager. pkgId=%s", pPkgId); +error: + if(ret != WAE_ERROR_NONE && dek != NULL) + free(dek); + + return ret; +} + +int get_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen) +{ + int ret = WAE_ERROR_NONE; + unsigned char* cached_dek= NULL; + unsigned char* dek = NULL; + + // get dek from cache + cached_dek = _get_app_dek_from_cache(pPkgId); + if(cached_dek == NULL) { + WAE_SLOGE("Fail to get APP_DEK from cache for preloaded app"); + ret = WAE_ERROR_NO_KEY; + goto error; + } + + dek = (unsigned char*) malloc(DEK_LEN); + if(dek == NULL) { + WAE_SLOGE("Fail to allocate memory for preloaded app dek"); + ret = WAE_ERROR_MEMORY; + goto error; + } + memcpy(dek, cached_dek, DEK_LEN); + + *ppDek = dek; + *dekLen = DEK_LEN; +error: + if(ret != WAE_ERROR_NONE && dek != NULL) + free(dek); + + return ret; +} + +int create_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen) +{ + int ret = WAE_ERROR_NONE; + unsigned char* dek = NULL; + unsigned char* encrypted_app_dek = NULL; + size_t encrypted_app_dek_len = 0; + unsigned char* pubKey = NULL; + size_t pubKeyLen = 0; + + // create APP_DEK + dek = (unsigned char*) malloc(DEK_LEN); + if(dek == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } + + ret = _get_random(DEK_LEN, dek); + if(ret != WAE_ERROR_NONE) { + goto error; + } + + // encrypt APP_DEK with APP_DEK_KEK + ret = _read_from_file(_get_dek_kek_pub_key_path(), &pubKey, &pubKeyLen); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to read APP_DEK_KEK Public Key"); + goto error; + } + + ret = encrypt_app_dek(pubKey, pubKeyLen, dek, DEK_LEN, &encrypted_app_dek, &encrypted_app_dek_len); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to encrypt APP_DEK with APP_DEK_KEK"); + goto error; + } + + // write APP_DEK in a file + ret = _write_encrypted_app_dek_to_file(pPkgId, encrypted_app_dek, encrypted_app_dek_len); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to write encrypted APP_DEK. pkgId=%s", pPkgId); + goto error; + } + + // store APP_DEK in cache + _add_app_dek_to_cache(pPkgId, dek); + + *ppDek = dek; + *dekLen = DEK_LEN; + WAE_SLOGI("Success to create preleaded APP_DEK and write it in initail value file. pkgId=%s", pPkgId); + +error: + if(pubKey != NULL) + free(pubKey); + if(encrypted_app_dek != NULL) + free(encrypted_app_dek); + if(ret != WAE_ERROR_NONE && dek != NULL) + free(dek); + return ret; +} + + +int _get_app_dek_kek(unsigned char** ppDekKek, size_t* kekLen) +{ + int ret = WAE_ERROR_NONE; + + ret = _read_from_file(_get_dek_kek_pri_key_path(), ppDekKek, kekLen); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to read APP_DEK_KEK Private Key"); + return ret; + } +/* + char* password = NULL; + ckmc_raw_buffer_s *pKekBuffer = NULL; + unsigned char* pKek = NULL; + + char dek_kek_alias[MAX_ALIAS_LEN] = {0, }; + _get_dek_kek_alias(dek_kek_alias, sizeof(dek_kek_alias)); + + ret = _to_wae_error(ckmc_get_data(dek_kek_alias, password, &pKekBuffer)); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to get APP_DEK_KEK from key-manager. alias=%s, ret=%d", APP_DEK_KEK_ALIAS, ret); + goto error; + } + + pKek = (unsigned char*) malloc(pKekBuffer->size); + if(pKek == NULL) { + WAE_SLOGE("Fail to allocate a memory"); + ret = WAE_ERROR_MEMORY; + goto error; + } + memcpy(pKek, pKekBuffer->data, pKekBuffer->size); + + *ppDekKek = pKek; + *kekLen = pKekBuffer->size; + WAE_SLOGI("Success to get APP_DEK_KEK from key-manager."); +error: + if(pKekBuffer != NULL) + ckmc_buffer_free(pKekBuffer); + if(ret != WAE_ERROR_NONE && pKek != NULL) + free(pKek); +*/ + return ret; +} + + +int _get_app_deks_loaded() +{ + int ret = WAE_ERROR_NONE; + + ckmc_raw_buffer_s *pBuffer = NULL; + char loading_done_alias[MAX_ALIAS_LEN] = {0, }; + + _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias)); + + ret = _to_wae_error(ckmc_get_data(loading_done_alias, NULL, &pBuffer)); + if(ret == WAE_ERROR_NO_KEY) { + WAE_SLOGI("APP_DEK_LOADING was not done"); + } else if(ret == WAE_ERROR_NONE) { + WAE_SLOGI("APP_DEK_LOADING was already done"); + } else { + WAE_SLOGE("Fail to get information from key-manager about APP_DEK_LOADING_DONE_ALIAS. ret=%d", ret); + goto error; + } + +error: + if(pBuffer != NULL) + ckmc_buffer_free(pBuffer); + + return ret; +} + +int _set_app_deks_loaded() +{ + int ret = WAE_ERROR_NONE; + ckmc_raw_buffer_s buff; + ckmc_policy_s policy; + unsigned char dummyData[1] = {0}; + + buff.data = dummyData; + buff.size = sizeof(dummyData); + + policy.password = NULL; + policy.extractable = true; + + char loading_done_alias[MAX_ALIAS_LEN] = {0, }; + _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias)); + + ret = _to_wae_error(ckmc_save_data(loading_done_alias, buff, policy)); + if(ret == WAE_ERROR_KEY_EXISTS) { + WAE_SLOGI("APP_DEK_LOADING was already done"); + ret = WAE_ERROR_NONE; + } else if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to set APP_DEK_LOADING_DONE_ALIAS to key-manager. ret=%d", ret); + goto error; + } + + WAE_SLOGI("Success to set APP_DEK_LOADING_DONE_ALIAS to key-manager."); +error: + return ret; +} + +int _clear_app_deks_loaded() +{ + int ret = WAE_ERROR_NONE; + char loading_done_alias[MAX_ALIAS_LEN] = {0, }; + _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias)); + + ret = _to_wae_error(ckmc_remove_alias(loading_done_alias)); + if(ret == WAE_ERROR_NO_KEY) { + WAE_SLOGI("APP_DEK_LOADING_DONE_ALIAS was not set to key-manager before."); + ret = WAE_ERROR_NONE; + }else if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to clear APP_DEK_LOADING_DONE_ALIAS to key-manager. ret=%d", ret); + } + + return ret; +} + +int load_preloaded_app_deks(int reload) +{ + int ret = WAE_ERROR_NONE; + + char pkgId[MAX_PKGID_LEN] = {0, }; + + DIR *dir = NULL; + struct dirent entry; + struct dirent *result; + int error; + char file_path_buff[MAX_PATH_LEN]; + unsigned char* encrypted_app_dek = NULL; + size_t encrypted_app_dek_len = 0; + unsigned char* app_dek = NULL; + size_t app_dek_len = 0; + unsigned char* priKey = NULL; + size_t priKeyLen = 0; + + int error_during_loading = 0; + + if(reload != WAE_TRUE) { + // check if all deks were already loaded into key-manager. + ret = _get_app_deks_loaded(); + if(ret == WAE_ERROR_NONE) { + return ret; + } + } + + ret = _get_app_dek_kek(&priKey, &priKeyLen); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to get APP_DEK_KEK Private Key"); + return ret; + } + + dir = opendir(_get_dek_store_path()); + if(dir == NULL) { + WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path()); + ret = WAE_ERROR_FILE; + goto error; + } + + for(;;) { + error = readdir_r(dir, &entry, &result); + if( error != 0 ) { + ret = WAE_ERROR_FILE; + goto error; + } + // readdir_r returns NULL in *result if the end + // of the directory stream is reached + if(result == NULL) + break; + + // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX + if(entry.d_type == DT_REG && strstr(entry.d_name, APP_DEK_FILE_PFX) != NULL) { + memset(file_path_buff, 0, sizeof(file_path_buff)); + sprintf(file_path_buff, "%s/%s", _get_dek_store_path(), entry.d_name); + + ret = _extract_pkg_id_from_file_name(entry.d_name, pkgId); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGW("Fail to extract pkgid from file. It will be ignored. file=%s",file_path_buff); + continue; + } + + ret = _read_from_file(file_path_buff, &encrypted_app_dek, &encrypted_app_dek_len); + if(ret != WAE_ERROR_NONE || encrypted_app_dek == NULL) { + error_during_loading++; + WAE_SLOGW("Fail to read file. It will be ignored. file=%s",file_path_buff); + continue; + } + + ret = decrypt_app_dek(priKey, priKeyLen, APP_DEK_KEK_PRIKEY_PASSWORD, + encrypted_app_dek, encrypted_app_dek_len, + &app_dek, &app_dek_len); + if(ret != WAE_ERROR_NONE || app_dek == NULL) { + error_during_loading++; + WAE_SLOGW("Fail to decrypt APP DEK. It will be ignored. file=%s",file_path_buff); + continue; + } + + // save app_dek in key_manager + ret = _add_dek_to_key_manager(pkgId, app_dek, app_dek_len); + // free temp objects + free(app_dek); + free(encrypted_app_dek); + app_dek = NULL; + encrypted_app_dek = NULL; + + if(ret == WAE_ERROR_KEY_EXISTS) { + WAE_SLOGI("Key Manager already has APP_DEK. It will be ignored. file=%s",file_path_buff); + continue; + }else if(ret != WAE_ERROR_NONE) { + error_during_loading++; + WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s",file_path_buff); + continue; + } + } + } + + ret = _set_app_deks_loaded(); + if(ret == WAE_ERROR_NONE) { + WAE_SLOGI("Success to load_preloaded_app_deks"); + ret = WAE_ERROR_NONE; + }else { + WAE_SLOGW("Fail to _set_app_deks_loaded to key-manager. ret=%d", ret); + } +error: + if(priKey != NULL) + free(priKey); + + return ret; +} + + +int remove_app_dek(const char* pPkgId) +{ + int ret = CKMC_ERROR_NONE; + char alias[MAX_ALIAS_LEN] = {0,}; + + _get_alias(pPkgId, alias,sizeof(alias)); + + ret = _to_wae_error(ckmc_remove_alias(alias)); + if(ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to remove APP_DEK from key-manager. pkgId=%s, alias=%s, ret=%d", pPkgId, alias, ret); + goto error; + } + + _remove_app_dek_from_cache(pPkgId); + WAE_SLOGI("Success to remove APP_DEK from key-manager. pkgId=%s", pPkgId); +error: + return WAE_ERROR_NONE; +} diff --git a/srcs/key_handler.h b/srcs/key_handler.h new file mode 100644 index 0000000..c855241 --- /dev/null +++ b/srcs/key_handler.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file key_handler.h + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief a header for key manupulatation. + */ + + + +#ifndef __TIZEN_CORE_WAE_KEY_HANDLER_H +#define __TIZEN_CORE_WAE_KEY_HANDLER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> + +#define APP_DEK_ALIAS_PFX "APP_DEK_" +#define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED" + +#define DEK_LEN 32 +#define MAX_ALIAS_LEN 256 +#define MAX_PKGID_LEN 256 +#define MAX_PATH_LEN 512 +#define MAX_CACHE_SIZE 100 + + +#define RANDOM_FILE "/dev/urandom" +#define APP_DEK_FILE_PFX "WAE_APP_DEK" +#define APP_DEK_KEK_ALIAS "WAE_APP_DEK_KEK" + +#define WAE_TRUE 1 +#define WAE_FALSE 0 + +void _initialize_cache(); +unsigned char* _get_app_dek_from_cache(const char* pkgId); +void _add_app_dek_to_cache(const char* pkgId, unsigned char* dek); +void _remove_app_dek_from_cache(const char* pkgId); +int _get_random(size_t length, unsigned char* random); +void _get_alias(const char* pPkgId, char* alias, size_t buff_len); +void _get_dek_kek_alias(char* alias, size_t buff_len); +void _get_dek_loading_done_alias(char* alias, size_t buff_len); +const char* _get_dek_kek_pub_key_path(); +const char* _get_dek_kek_pri_key_path(); +const char* _get_dek_store_path(); +int _add_dek_to_key_manager(const char* pPkgId, const unsigned char* pDek, size_t len); +int _get_preloaded_app_dek_file_path(const char* pPkgId, char *path); +int _extract_pkg_id_from_file_name(const char* fileName, char* pkgId); +int _read_encrypted_app_dek_from_file(const char* pPkgId, unsigned char** encrypted_app_dek, size_t*len); +int _write_encrypted_app_dek_to_file(const char* pPkgId, const unsigned char* encrypted_app_dek, size_t len); +int _read_from_file(const char* path, unsigned char** data, size_t* len); +int _write_to_file(const char* path, const unsigned char* data, size_t len); +int _get_app_dek_kek_from_key_manager(unsigned char** ppDekKek, size_t* kekLen); +int _get_app_deks_loaded(); +int _set_app_deks_loaded(); +int _clear_app_deks_loaded(); + +int get_app_dek(const char* pPkgId, unsigned char** ppDek, size_t *dekLen); +int create_app_dek(const char* pPkgId, unsigned char** ppDek, size_t *dekLen); +int get_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t* dekLen); +int create_preloaded_app_dek(const char* pPkgId, unsigned char** ppDek, size_t *dekLen); +int load_preloaded_app_deks(int reload); +int remove_app_dek(const char* pPkgId); + + +#ifdef __cplusplus +} +#endif +#endif /* __TIZEN_CORE_WAE_KEY_HANDLER_H */ + diff --git a/srcs/wae_initializer.c b/srcs/wae_initializer.c new file mode 100644 index 0000000..011c8a0 --- /dev/null +++ b/srcs/wae_initializer.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file wae_initializer.c + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief tool for importing APP DEKs during booting + */ + +#include "key_handler.h" +#include "web_app_enc.h" +#include "wae_log.h" +#include <stdio.h> + +int main(int argc, char* argv[]) +{ + int ret = WAE_ERROR_NONE; + int reload = WAE_FALSE; + + if(argc == 2 && strcmp(argv[1], "--reload")==0) { + reload = WAE_TRUE; + } + + ret = load_preloaded_app_deks(reload); + if(ret == WAE_ERROR_NONE) { + printf("WAE INITIALIZER was finished successfully.\n"); + WAE_SLOGI("WAE INITIALIZER was finished successfully."); + return 0; + }else { + printf("WAE INITIALIZER was finished with error. ret=%d\n", ret); + WAE_SLOGE("WAE INITIALIZER was finished with error. ret=%d", ret); + return -1; + } +} diff --git a/srcs/wae_log.h b/srcs/wae_log.h new file mode 100644 index 0000000..6dfe44a --- /dev/null +++ b/srcs/wae_log.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file wae_log.h + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief a header for loggin. + */ + +#ifndef __WAE_LOG_H__ +#define __WAE_LOG_H__ + +/* Use DLOG logging mechanism */ +#include <dlog.h> + +#define TAG_WAE "WAE" + +#define WAE_SLOGD(format, arg...) SLOG(LOG_DEBUG, TAG_WAE, format, ##arg) +#define WAE_SLOGI(format, arg...) SLOG(LOG_INFO, TAG_WAE, format, ##arg) +#define WAE_SLOGW(format, arg...) SLOG(LOG_WARN, TAG_WAE, format, ##arg) +#define WAE_SLOGE(format, arg...) SLOG(LOG_ERROR, TAG_WAE, format, ##arg) +#define WAE_SLOGF(format, arg...) SLOG(LOG_FATAL, TAG_WAE, format, ##arg) + +#endif /* __WAE_LOG_H__*/ + diff --git a/srcs/web_app_enc.c b/srcs/web_app_enc.c new file mode 100644 index 0000000..7bc8484 --- /dev/null +++ b/srcs/web_app_enc.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + * + * @file web_app_enc.c + * @author Dongsun Lee (ds73.lee@samsung.com) + * @version 1.0 + * @brief provides fucntions for encryption and decryption of web application. + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "web_app_enc.h" +#include "key_handler.h" +#include "crypto_service.h" +#include "wae_log.h" + + +int _wae_encrypt_downloaded_web_application(const char* pPkgId, + const unsigned char* pData, size_t dataLen, + unsigned char** ppEncryptedData, size_t* pEncDataLen) +{ + int ret = WAE_ERROR_NONE; + unsigned char *pDek = NULL; + size_t dekLen = -1; + + if(pPkgId == NULL) { + WAE_SLOGE("Invalid Parameter. pPkgId is NULL"); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + if(pData == NULL || dataLen <= 0) { + WAE_SLOGE("Invalid Parameter. pData is NULL or invalid dataLen(%d)", dataLen); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + if(ppEncryptedData == NULL || pEncDataLen == NULL) { + WAE_SLOGE("Invalid Parameter. ppEncryptedData or pEncDataLen is NULL"); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + + // get APP_DEK. + // if not exists, create APP_DEK + ret = get_app_dek(pPkgId, &pDek, &dekLen); + if(ret == WAE_ERROR_NO_KEY) { + ret = create_app_dek(pPkgId, &pDek, &dekLen); + } + if(ret != WAE_ERROR_NONE) { + goto error; + } + + // encrypt + ret = encrypt_aes_cbc(pDek, dekLen, pData, dataLen, ppEncryptedData, pEncDataLen); + if(ret != WAE_ERROR_NONE) { + goto error; + } + +error: + if(pDek != NULL) + free(pDek); + + return ret; +} + +int _wae_decrypt_downloaded_web_application(const char* pPkgId, + const unsigned char* pData, size_t dataLen, + unsigned char** ppDecryptedData, size_t* pDecDataLen) +{ + int ret = WAE_ERROR_NONE; + unsigned char *pDek = NULL; + size_t dekLen = -1; + + if(pPkgId == NULL) { + WAE_SLOGE("Invalid Parameter. pPkgId is NULL"); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + if(pData == NULL || dataLen <= 0) { + WAE_SLOGE("Invalid Parameter. pData is NULL or invalid dataLen(%d)", dataLen); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + if(ppDecryptedData == NULL || pDecDataLen == NULL) { + WAE_SLOGE("Invalid Parameter. ppDecryptedData or pDecDataLen is NULL"); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + + ret = get_app_dek(pPkgId, &pDek, &dekLen); + if(ret != WAE_ERROR_NONE) { + goto error; + } + + // decrypt + ret = decrypt_aes_cbc(pDek, dekLen, pData, dataLen, ppDecryptedData, pDecDataLen); + if(ret != WAE_ERROR_NONE) { + goto error; + } + +error: + if(pDek != NULL) + free(pDek); + + return ret; +} + +int _wae_encrypt_preloaded_web_application(const char* pPkgId, + const unsigned char* pData, size_t dataLen, + unsigned char** ppEncryptedData, size_t* pEncDataLen) +{ + + int ret = WAE_ERROR_NONE; + unsigned char *pDek = NULL; + size_t dekLen = -1; + + if(pPkgId == NULL) { + WAE_SLOGE("Invalid Parameter. pPkgId is NULL"); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + if(pData == NULL || dataLen <= 0) { + WAE_SLOGE("Invalid Parameter. pData is NULL or invalid dataLen(%d)", dataLen); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + if(ppEncryptedData == NULL || pEncDataLen == NULL) { + WAE_SLOGE("Invalid Parameter. ppEncryptedData or pEncDataLen is NULL"); + ret = WAE_ERROR_INVALID_PARAMETER; + goto error; + } + + ret = get_preloaded_app_dek(pPkgId, &pDek, &dekLen); + if(ret == WAE_ERROR_NO_KEY) { + ret = create_preloaded_app_dek(pPkgId, &pDek, &dekLen); + } + if(ret != WAE_ERROR_NONE) { + goto error; + } + + // encrypt + ret = encrypt_aes_cbc(pDek, dekLen, pData, dataLen, ppEncryptedData, pEncDataLen); + if(ret != WAE_ERROR_NONE) { + goto error; + } +error: + if(pDek != NULL) + free(pDek); + + return ret; +} + +int _wae_decrypt_preloaded_web_application(const char* pPkgId, + const unsigned char* pData, size_t dataLen, + unsigned char** ppDecryptedData, size_t* pDecDataLen) +{ + // same with the decryption of downloaded web application + return _wae_decrypt_downloaded_web_application(pPkgId, pData, dataLen, ppDecryptedData, pDecDataLen); +} + +int wae_encrypt_web_application(const char* pPkgId,int isPreloaded, + const unsigned char* pData, size_t dataLen, + unsigned char** ppEncryptedData, size_t* pEncDataLen) +{ + int ret = WAE_ERROR_NONE; + + if(isPreloaded) + ret = _wae_encrypt_preloaded_web_application(pPkgId, pData, dataLen, ppEncryptedData, pEncDataLen); + else + ret = _wae_encrypt_downloaded_web_application(pPkgId, pData, dataLen, ppEncryptedData, pEncDataLen); + + WAE_SLOGI("Encrypt Web App. pkgId=%s, isPreloaded=%d, dataLen=%d, ret=%d", + pPkgId, isPreloaded, dataLen, ret); + return ret; +} + +int wae_decrypt_web_application(const char* pPkgId, int isPreloaded, + const unsigned char* pData, size_t dataLen, + unsigned char** ppDecryptedData, size_t* pDecDataLen) +{ + int ret = WAE_ERROR_NONE; + + if(isPreloaded) + ret = _wae_decrypt_preloaded_web_application(pPkgId, pData, dataLen, ppDecryptedData, pDecDataLen); + else + ret =_wae_decrypt_downloaded_web_application(pPkgId, pData, dataLen, ppDecryptedData, pDecDataLen); + + WAE_SLOGI("Decrypt Web App. pkgId=%s, isPreloaded=%d, dataLen=%d, ret=%d", + pPkgId, isPreloaded, dataLen, ret); + return ret; +} + + +int wae_remove_app_dek(const char* pPkgId) +{ + int ret = WAE_ERROR_NONE; + ret = remove_app_dek(pPkgId); + WAE_SLOGI("Remove APP DEK. pkgId=%s, ret=%d", pPkgId, ret); + return ret; +} |