summaryrefslogtreecommitdiff
path: root/srcs
diff options
context:
space:
mode:
authorDongsun Lee <ds73.lee@samsung.com>2015-05-26 09:42:38 +0900
committerDongsun Lee <ds73.lee@samsung.com>2015-07-24 10:58:41 +0900
commit7abaa019637e0a534969d304cae7f7f43c4ab0a6 (patch)
tree9a2bb4f95b6c50ac39394abf87022d4a1a95fef2 /srcs
parentd6556f8d8b13aadc9907b6609b773e29d2e22e7a (diff)
downloadlibwebappenc-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.txt67
-rw-r--r--srcs/crypto_service.c372
-rw-r--r--srcs/crypto_service.h57
-rw-r--r--srcs/key_handler.c744
-rw-r--r--srcs/key_handler.h86
-rw-r--r--srcs/wae_initializer.c47
-rw-r--r--srcs/wae_log.h38
-rw-r--r--srcs/web_app_enc.c213
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;
+}