diff options
author | Dongsun Lee <ds73.lee@samsung.com> | 2019-01-19 21:21:20 +0900 |
---|---|---|
committer | Dongsun Lee <ds73.lee@samsung.com> | 2019-05-24 13:11:38 +0900 |
commit | fd2d39061c3fde9b2faba0a4146eb79114c29660 (patch) | |
tree | c79254c5d40f0ad01d8f809de5754db369f0ff88 /srcs | |
parent | 4923a69e93f516640fd5230880ac18e3194f0ee7 (diff) | |
download | libwebappenc-fd2d39061c3fde9b2faba0a4146eb79114c29660.tar.gz libwebappenc-fd2d39061c3fde9b2faba0a4146eb79114c29660.tar.bz2 libwebappenc-fd2d39061c3fde9b2faba0a4146eb79114c29660.zip |
Replace DEK_KEK from RSA key to AES keysubmit/tizen/20190524.043832accepted/tizen/unified/20190530.043039
Change-Id: I5a5b6935ee1908bd9be7edf0087fcd17d61b9fd2
Signed-off-by: Dongsun Lee <ds73.lee@samsung.com>
Diffstat (limited to 'srcs')
-rw-r--r-- | srcs/crypto_service.c | 195 | ||||
-rw-r--r-- | srcs/crypto_service.h | 7 | ||||
-rw-r--r-- | srcs/key_handler.c | 79 | ||||
-rw-r--r-- | srcs/key_handler.h | 3 | ||||
-rw-r--r-- | srcs/key_manager.c | 49 |
5 files changed, 60 insertions, 273 deletions
diff --git a/srcs/crypto_service.c b/srcs/crypto_service.c index c28c0cd..dcc172e 100644 --- a/srcs/crypto_service.c +++ b/srcs/crypto_service.c @@ -35,6 +35,11 @@ #include "wae_log.h" #define AES_256_KEY_SIZE 32 +#define KEK_IV_LEN 16 +#define PBKDF2_ITERATION 1024 + + +crypto_element_s *dek_kek = NULL; static bool __initialized = false; @@ -47,186 +52,74 @@ void _initialize() } } -int encrypt_app_dek(const raw_buffer_s *pubkey, const raw_buffer_s *dek, - raw_buffer_s **pencrypted_dek) +int _generate_dek_kek() { - if (!is_buffer_valid(pubkey) || !is_buffer_valid(dek) || pencrypted_dek == NULL) - return WAE_ERROR_INVALID_PARAMETER; - int ret = WAE_ERROR_NONE; - EVP_PKEY *key = NULL; - EVP_PKEY_CTX *ctx = NULL; - raw_buffer_s *encrypted_dek = NULL; - size_t len = 0; - - _initialize(); - - BIO *bio = BIO_new(BIO_s_mem()); - BIO_write(bio, pubkey->buf, pubkey->size); - key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); - - if (key == NULL) { - BIO_reset(bio); - BIO_write(bio, pubkey->buf, pubkey->size); - key = d2i_PUBKEY_bio(bio, NULL); - } - - if (key == NULL) { - ret = WAE_ERROR_FILE; - WAE_SLOGE("Failt to convert to public key."); - goto error; - } - - ctx = EVP_PKEY_CTX_new(key, NULL); - - if (ctx == NULL) { - WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_new failed"); - ret = WAE_ERROR_CRYPTO; - goto error; - } + raw_buffer_s *kek = NULL; + raw_buffer_s *iv = NULL; - 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, &len, dek->buf, dek->size) <= 0) { - WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed"); - ret = WAE_ERROR_CRYPTO; + kek = buffer_create(AES_256_KEY_SIZE); + if (kek == NULL) { + ret = WAE_ERROR_MEMORY; goto error; } - - if ((encrypted_dek = buffer_create(len)) == NULL) { - WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed"); + iv = buffer_create(KEK_IV_LEN); + if (iv == NULL) { ret = WAE_ERROR_MEMORY; goto error; } - if (EVP_PKEY_encrypt(ctx, encrypted_dek->buf, &encrypted_dek->size, dek->buf, - dek->size) <= 0) { - WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed"); + ret = PKCS5_PBKDF2_HMAC_SHA1( + DEK_KEK_SEED, -1, + NULL, 0, + PBKDF2_ITERATION, + AES_256_KEY_SIZE, + kek->buf); + if (ret == 0) { ret = WAE_ERROR_CRYPTO; goto error; + } else { + ret = WAE_ERROR_NONE; } - *pencrypted_dek = encrypted_dek; - + dek_kek = crypto_element_create(kek, iv); error: - if (bio != NULL) - BIO_free(bio); - - if (key != NULL) - EVP_PKEY_free(key); - - if (ctx != NULL) - EVP_PKEY_CTX_free(ctx); - - if (ret != WAE_ERROR_NONE) - buffer_destroy(encrypted_dek); + if (ret != WAE_ERROR_NONE) { + if (kek != NULL) + buffer_destroy(kek); + if (iv != NULL) + buffer_destroy(iv); + } return ret; } -int decrypt_app_dek(const raw_buffer_s *prikey, const char *prikey_pass, - const raw_buffer_s *encrypted_dek, raw_buffer_s **pdek) +int encrypt_preloaded_app_dek(const raw_buffer_s *dek, raw_buffer_s **pencrypted_dek) { - if (!is_buffer_valid(prikey) || !is_buffer_valid(encrypted_dek) || pdek == NULL) - return WAE_ERROR_INVALID_PARAMETER; - int ret = WAE_ERROR_NONE; - EVP_PKEY_CTX *ctx = NULL; - raw_buffer_s *dek = NULL; - size_t len = 0; - - _initialize(); - BIO *bio = BIO_new(BIO_s_mem()); - if (bio == NULL) - return WAE_ERROR_MEMORY; - - BIO_write(bio, prikey->buf, prikey->size); - EVP_PKEY *key = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)prikey_pass); - - if (key == NULL) { - BIO_reset(bio); - BIO_write(bio, prikey->buf, prikey->size); - key = d2i_PrivateKey_bio(bio, NULL); - } - - if (key == NULL) { - ret = WAE_ERROR_FILE; - WAE_SLOGE("Failed to convert to public key."); - goto error; - } - - ctx = EVP_PKEY_CTX_new(key, NULL); - - if (ctx == NULL) { - WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_new failed"); - ret = WAE_ERROR_CRYPTO; - goto error; + if (dek_kek == NULL) { + ret = _generate_dek_kek(); + if (ret != WAE_ERROR_NONE) + return ret; } - 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, &len, encrypted_dek->buf, encrypted_dek->size) <= 0) { - WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt failed"); - ret = WAE_ERROR_CRYPTO; - goto error; - } + return encrypt_aes_cbc(dek_kek, dek, pencrypted_dek); +} - dek = buffer_create(len); - if (dek == NULL) { - WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed"); - ret = WAE_ERROR_MEMORY; - goto error; - } +int decrypt_preloaded_app_dek(const raw_buffer_s *encrypted_dek, raw_buffer_s **pdek) +{ + int ret = WAE_ERROR_NONE; - if (EVP_PKEY_decrypt(ctx, dek->buf, &dek->size, encrypted_dek->buf, - encrypted_dek->size) <= 0) { - WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_decrypt failed"); - ret = WAE_ERROR_CRYPTO; - goto error; + if (dek_kek == NULL) { + ret = _generate_dek_kek(); + if (ret != WAE_ERROR_NONE) + return ret; } - *pdek = dek; - -error: - if (bio != NULL) - BIO_free(bio); - - if (key != NULL) - EVP_PKEY_free(key); - - if (ctx != NULL) - EVP_PKEY_CTX_free(ctx); - - if (ret != WAE_ERROR_NONE) - buffer_destroy(dek); - - return ret; + return decrypt_aes_cbc(dek_kek, encrypted_dek, pdek); } - int encrypt_aes_cbc(const crypto_element_s *ce, const raw_buffer_s *data, raw_buffer_s **pencrypted_data) { diff --git a/srcs/crypto_service.h b/srcs/crypto_service.h index c6340ae..a2d7412 100644 --- a/srcs/crypto_service.h +++ b/srcs/crypto_service.h @@ -28,10 +28,9 @@ extern "C" { #include "types.h" -int encrypt_app_dek(const raw_buffer_s *pubkey, const raw_buffer_s *dek, - raw_buffer_s **pencrypted_dek); -int decrypt_app_dek(const raw_buffer_s *prikey, const char *prikey_pass, - const raw_buffer_s *encrypted_dek, raw_buffer_s **pdek); + +int encrypt_preloaded_app_dek(const raw_buffer_s *dek, raw_buffer_s **pencrypted_dek); +int decrypt_preloaded_app_dek(const raw_buffer_s *encrypted_dek, raw_buffer_s **pdek); int encrypt_aes_cbc(const crypto_element_s *ce, const raw_buffer_s *data, diff --git a/srcs/key_handler.c b/srcs/key_handler.c index a60142e..c198d19 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -104,16 +104,6 @@ int _get_random(raw_buffer_s *rb) return WAE_ERROR_NONE; } -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"); @@ -197,8 +187,8 @@ error: return ret; } -typedef int(*entry_callback)(const char *path, const struct dirent *entry, void *user_data); -static int traverse_directory(const char *path, entry_callback ecb, void *user_data) +typedef int(*entry_callback)(const char *path, const struct dirent *entry); +static int traverse_directory(const char *path, entry_callback ecb) { DIR *dir = opendir(path); if (dir == NULL) { @@ -228,7 +218,7 @@ static int traverse_directory(const char *path, entry_callback ecb, void *user_d continue; } - int _ret = ecb(path, result, user_data); + int _ret = ecb(path, result); if (_ret != WAE_ERROR_NONE) ret = _ret; } @@ -243,10 +233,8 @@ static void _remove_file(const char *path) } static int _entry_callback_remove_all( - const char *path, const struct dirent *entry, void *user_data) + const char *path, const struct dirent *entry) { - (void) user_data; // TODO: use UNUSED macro - char file_path_buff[MAX_PATH_LEN] = {0, }; if ((unsigned)snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) >= sizeof(file_path_buff)) @@ -254,7 +242,7 @@ static int _entry_callback_remove_all( int ret = WAE_ERROR_NONE; if (entry->d_type == DT_DIR) { - int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all, NULL); + int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all); if (_ret != WAE_ERROR_NONE) ret = _ret; rmdir(file_path_buff); @@ -266,7 +254,7 @@ static int _entry_callback_remove_all( void _remove_directory(const char *path) { - traverse_directory(path, _entry_callback_remove_all, NULL); + traverse_directory(path, _entry_callback_remove_all); WAE_SLOGD("remove directory(%s)", path); rmdir(path); @@ -323,8 +311,7 @@ int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *enc return _write_to_file(path, encrypted); } -int _load_preloaded_app_dek( - const raw_buffer_s *prikey, const char *filepath, const char *pkg_id) +int _load_preloaded_app_dek(const char *filepath, const char *pkg_id) { raw_buffer_s *encrypted_dek = NULL; raw_buffer_s *dek = NULL; @@ -337,7 +324,7 @@ int _load_preloaded_app_dek( return ret; } - ret = decrypt_app_dek(prikey, APP_DEK_KEK_PRIKEY_PASSWORD, encrypted_dek, &dek); + ret = decrypt_preloaded_app_dek(encrypted_dek, &dek); if (ret != WAE_ERROR_NONE) { WAE_SLOGW("Failed to decrypt dek. It will be ignored. file=%s", filepath); goto finish; @@ -536,7 +523,6 @@ int get_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) { raw_buffer_s *encrypted_app_dek = NULL; - raw_buffer_s *pubkey = NULL; raw_buffer_s *dek = buffer_create(DEK_LEN); raw_buffer_s *iv = buffer_create(sizeof(AES_CBC_IV)); crypto_element_s *ce = crypto_element_create(dek, iv); @@ -556,14 +542,7 @@ int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) // copy default iv for preloaded app memcpy(iv->buf, AES_CBC_IV, sizeof(AES_CBC_IV)); - ret = _read_from_file(_get_dek_kek_pub_key_path(), &pubkey); - - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("WAE: Fail to read APP_DEK_KEK Public Key"); - goto error; - } - - ret = encrypt_app_dek(pubkey, dek, &encrypted_app_dek); + ret = encrypt_preloaded_app_dek(dek, &encrypted_app_dek); if (ret != WAE_ERROR_NONE) { WAE_SLOGE("WAE: Fail to encrypt APP_DEK with APP_DEK_KEK"); @@ -592,7 +571,6 @@ int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) error: buffer_destroy(encrypted_app_dek); - buffer_destroy(pubkey); if (ret != WAE_ERROR_NONE) { if (ce) { @@ -606,29 +584,13 @@ error: return ret; } -int _get_app_dek_kek(raw_buffer_s **pdek_kek) -{ -#if 0 - return get_dek_kek_from_key_manager(pdek_kek); -#else - return _read_from_file(_get_dek_kek_pri_key_path(), pdek_kek); -#endif -} - static int _entry_callback_load_preloaded_adeks( - const char *path, const struct dirent *entry, void *prikey) + const char *path, const struct dirent *entry) { - const char *pub_key_path = _get_dek_kek_pub_key_path(); - const char *pri_key_path = _get_dek_kek_pri_key_path(); - char file_path_buff[MAX_PATH_LEN] = {0, }; if ((unsigned)snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) >= sizeof(file_path_buff)) return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ - if (strcmp(file_path_buff, pub_key_path) == 0 || - strcmp(file_path_buff, pri_key_path) == 0) - return WAE_ERROR_NONE; /* skip KEK files */ - if (entry->d_type != DT_REG || strstr(entry->d_name, APP_DEK_FILE_PFX) == NULL) { if (entry->d_type == DT_DIR) WAE_SLOGW( @@ -648,7 +610,7 @@ static int _entry_callback_load_preloaded_adeks( return ret; } - ret = _load_preloaded_app_dek((raw_buffer_s *)prikey, file_path_buff, pkg_id); + ret = _load_preloaded_app_dek(file_path_buff, pkg_id); if (ret == WAE_ERROR_NONE || ret == WAE_ERROR_KEY_EXISTS) { WAE_SLOGI("Successfully load app dek(%s)", file_path_buff); return WAE_ERROR_NONE; @@ -666,7 +628,6 @@ int load_preloaded_app_deks() const char *dek_store_path = _get_dek_store_path(); - raw_buffer_s *prikey = NULL; DIR *dir = NULL; // check if all deks were already loaded into key-manager. @@ -686,34 +647,18 @@ int load_preloaded_app_deks() } } - ret = _get_app_dek_kek(&prikey); - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Fail to get APP_DEK_KEK Private Key. ret(%d)", ret); - goto out; - } - // close dek store dir fd not to affect the traverse_directory call closedir(dir); dir = NULL; - ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks, prikey); + ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks); if (ret != WAE_ERROR_NONE) WAE_SLOGE("Fail when traverse dek store directory. ret(%d)", ret); out: - if (prikey != NULL) - buffer_destroy(prikey); - if (dir != NULL) closedir(dir); - // remove dek store after loade done even though it's partially failed - // because malware can still put the file in dek store if it still system service's - // ownership and they can break this logic by inserting any file to dek store path. - // If KEK private key is inserted to key-manager with initial-value feature, malware - // cannot insert/encrypt/decrypt app dek so it's fine on preloaded app security but - // if we handle errors related loading file, malware can at least occur webappenc - // initializer service failure. _remove_directory(dek_store_path); return ret; diff --git a/srcs/key_handler.h b/srcs/key_handler.h index f5ce3e4..871fe60 100644 --- a/srcs/key_handler.h +++ b/srcs/key_handler.h @@ -42,10 +42,9 @@ int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path int _read_encrypted_app_dek_from_file(const char *pkg_id, raw_buffer_s **pencrypted); int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *encrypted); void _remove_directory(const char *path); -const char *_get_dek_kek_pub_key_path(); -const char *_get_dek_kek_pri_key_path(); const char *_get_dek_store_path(); + /* functions for interface */ int get_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type, bool create_for_migrated_app, const crypto_element_s **pce); diff --git a/srcs/key_manager.c b/srcs/key_manager.c index 1f7a96d..ac49bb9 100644 --- a/srcs/key_manager.c +++ b/srcs/key_manager.c @@ -283,52 +283,3 @@ int remove_from_key_manager(const char *name, wae_app_type_e type) return _to_wae_error(ckmc_remove_alias(alias)); } - -static int _get_dek_kek_alias(char *alias, size_t buff_len) -{ - return (unsigned)snprintf(alias, buff_len, "%s%s%s", - ckmc_owner_id_system, - ckmc_owner_id_separator, - APP_DEK_KEK_ALIAS) >= buff_len - ? WAE_ERROR_INVALID_PARAMETER - : WAE_ERROR_NONE; -} - -int get_dek_kek_from_key_manager(raw_buffer_s **pdek_kek) -{ - if (pdek_kek == NULL) - return WAE_ERROR_INVALID_PARAMETER; - - ckmc_raw_buffer_s *buf = NULL; - - char alias[MAX_ALIAS_LEN] = {0, }; - int ret = _get_dek_kek_alias(alias, sizeof(alias)); - if (ret != WAE_ERROR_NONE) - return ret; - - ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf)); - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to get dek kek from key-manager. alias(%s) ret(%d)", - alias, ret); - return ret; - } - - raw_buffer_s *dek_kek = buffer_create(buf->size); - if (dek_kek == NULL) { - ret = WAE_ERROR_MEMORY; - goto error; - } - memcpy(dek_kek->buf, buf->data, dek_kek->size); - - *pdek_kek = dek_kek; - - WAE_SLOGI("Success to get dek kek from key-manager."); - -error: - ckmc_buffer_free(buf); - - if (ret != WAE_ERROR_NONE) - buffer_destroy(dek_kek); - - return ret; -} |