From f0718c7aa95e51b41e1ee71747a01d75b3aaa9e6 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Tue, 19 Jul 2016 16:16:10 +0900 Subject: [PATCH 01/16] Logging openssl log on crypto error cases Change-Id: I60d574d8813637077fa1e278a3d72dbfed07333c Signed-off-by: Kyungwook Tak --- srcs/decrypt_migrated_wgt.c | 73 +++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/srcs/decrypt_migrated_wgt.c b/srcs/decrypt_migrated_wgt.c index d240fa4..dfaf28a 100644 --- a/srcs/decrypt_migrated_wgt.c +++ b/srcs/decrypt_migrated_wgt.c @@ -28,12 +28,23 @@ #include #include #include +#include #include "wae_log.h" #include "web_app_enc.h" #define DUK_LEN 16 +static void _logging_openssl_err() +{ + unsigned long e = ERR_get_error(); + char buf[512] = {0, }; + + ERR_error_string_n(e, buf, 511); + + WAE_SLOGE("Openssl err: %s", buf); +} + static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_len) { unsigned char salt[32]; @@ -46,7 +57,12 @@ static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_l return WAE_ERROR_MEMORY; } - PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1, (DUK_LEN * 2), duk); + if (PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1, + (DUK_LEN * 2), duk) != 1) { + free(duk); + return WAE_ERROR_CRYPTO; + } + duk[DUK_LEN * 2] = '\0'; *pduk = duk; @@ -59,19 +75,15 @@ static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_l static int _get_old_iv(const unsigned char *src, size_t src_len, unsigned char **piv, size_t *piv_len) { - unsigned char iv_buf[SHA_DIGEST_LENGTH] = {0, }; - unsigned int iv_len = 0; - - if (EVP_Digest(src, src_len, iv_buf, &iv_len, EVP_sha1(), NULL) != 1) { - WAE_SLOGE("Failed to EVP_Digest for getting old iv"); - return WAE_ERROR_CRYPTO; - } - - unsigned char *iv = (unsigned char *)malloc(sizeof(unsigned char) * sizeof(iv_buf)); + unsigned int iv_len = SHA_DIGEST_LENGTH; + unsigned char *iv = (unsigned char *)malloc(sizeof(unsigned char) * iv_len); if (iv == NULL) return WAE_ERROR_MEMORY; - memcpy(iv, iv_buf, sizeof(iv_buf)); + if (EVP_Digest(src, src_len, iv, &iv_len, EVP_sha1(), NULL) != 1) { + free(iv); + return WAE_ERROR_CRYPTO; + } *piv = iv; *piv_len = iv_len; @@ -111,48 +123,47 @@ static int _decrypt(const unsigned char *key, size_t key_len, EVP_CIPHER_CTX_init(&ctx); - int ret = EVP_CipherInit(&ctx, algo, key, iv, 0); + int ret = WAE_ERROR_NONE; - if (ret != 1) { + if (EVP_CipherInit(&ctx, algo, key, iv, 0) != 1) { ret = WAE_ERROR_CRYPTO; goto error; } - ret = EVP_CIPHER_CTX_set_padding(&ctx, 1); - - if (ret != 1) { + if (EVP_CIPHER_CTX_set_padding(&ctx, 1) != 1) { ret = WAE_ERROR_CRYPTO; goto error; } - ret = EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len); - - if (ret != 1) { + if (EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len) != 1) { ret = WAE_ERROR_CRYPTO; goto error; } else if (decrypted_len <= 0) { - ret = WAE_ERROR_CRYPTO; + WAE_SLOGE("EVP_CipherUpdate success but returned decrypted_len(%d) <= 0", + decrypted_len); + ret = WAE_ERROR_UNKNOWN; goto error; } - ret = EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len); - - if (ret != 1) { + if (EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len) != 1) { ret = WAE_ERROR_CRYPTO; goto error; } else if (final_len <= 0) { - ret = WAE_ERROR_CRYPTO; + WAE_SLOGE("EVP_CipherFinal success but returned final_len(%d) <= 0", + final_len); + ret = WAE_ERROR_UNKNOWN; goto error; } *pdecrypted = decrypted; *pdecrypted_len = decrypted_len + final_len; - ret = WAE_ERROR_NONE; - error: EVP_CIPHER_CTX_cleanup(&ctx); + if (ret != WAE_ERROR_NONE) + free(decrypted); + return ret; } @@ -161,13 +172,14 @@ int decrypt_by_old_ss_algo(const char *pkg_id, const unsigned char *encrypted, s { unsigned char *duk = NULL; size_t duk_len = 0; + unsigned char *iv = NULL; + size_t iv_len = 0; + int ret = _get_old_duk(pkg_id, &duk, &duk_len); if (ret != WAE_ERROR_NONE) - return ret; + goto error; - unsigned char *iv = NULL; - size_t iv_len = 0; ret = _get_old_iv(duk, duk_len, &iv, &iv_len); if (ret != WAE_ERROR_NONE) @@ -178,6 +190,9 @@ int decrypt_by_old_ss_algo(const char *pkg_id, const unsigned char *encrypted, s WAE_SLOGI("decrypt with old ss algo success of pkg: %s", pkg_id); error: + if (ret == WAE_ERROR_CRYPTO) + _logging_openssl_err(); + free(duk); free(iv); -- 2.7.4 From 1aebf02f77796380a570ea41732db0c706213ed1 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Tue, 19 Jul 2016 16:21:51 +0900 Subject: [PATCH 02/16] Fix memory leak on decrypt migrated wgt Change-Id: I300a887e7e633af858e102797c500d1266566355 Signed-off-by: Kyungwook Tak --- srcs/web_app_enc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/srcs/web_app_enc.c b/srcs/web_app_enc.c index a5224ea..083addf 100644 --- a/srcs/web_app_enc.c +++ b/srcs/web_app_enc.c @@ -76,10 +76,7 @@ int _wae_decrypt_downloaded_web_application(const char *pkg_id, wae_app_type_e a "needed secure-storage data migration.", pkg_id); ret = decrypt_by_old_ss_algo(pkg_id, data, data_len, pdecrypted_data, pdecrypted_data_len); - if (ret != WAE_ERROR_NONE) - goto error; - else - return WAE_ERROR_NONE; + goto error; // always go to error to skip decyprt_aes_cbc } else if (ret != WAE_ERROR_NONE) { goto error; } -- 2.7.4 From 6818b8559b7d4d45adaeb1937d708a154dc00fd7 Mon Sep 17 00:00:00 2001 From: Yunjin Lee Date: Wed, 20 Jul 2016 19:24:34 +0900 Subject: [PATCH 03/16] Set SmackProcessLabel to System Change-Id: I685a98780fde45ad0975a0a80dcabd68760f9244 Signed-off-by: Yunjin Lee --- systemd/webappenc-initializer.service.in | 1 + 1 file changed, 1 insertion(+) diff --git a/systemd/webappenc-initializer.service.in b/systemd/webappenc-initializer.service.in index e9441d8..976a877 100644 --- a/systemd/webappenc-initializer.service.in +++ b/systemd/webappenc-initializer.service.in @@ -7,6 +7,7 @@ After=central-key-manager.service [Service] Type=oneshot ExecStart=/usr/bin/wae_initializer +SmackProcessLabel=System [Install] WantedBy=multi-user.target -- 2.7.4 From d6da3e3d9bc29e22103b094bee5ca68f5d8f0f61 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Thu, 21 Jul 2016 16:46:00 +0900 Subject: [PATCH 04/16] Add data structures For migrated web app, we need to more fields in cache e.g., IV and is_migrated flag to handle it separately. Because cipher algorithm, iv and key size could be different between old secure storage, it depends on product implementation. So this architecture needs more flexibility. A lot of code changed because of the principle data structure is added from the bottom. Change-Id: Id6a10b9f707f4da25016dd928ab4049be619a610 Signed-off-by: Kyungwook Tak --- srcs/CMakeLists.txt | 2 + srcs/crypto_service.c | 187 ++++++------ srcs/crypto_service.h | 25 +- srcs/decrypt_migrated_wgt.c | 141 +++++---- srcs/decrypt_migrated_wgt.h | 16 +- srcs/key_handler.c | 710 ++++++++++++++++---------------------------- srcs/key_handler.h | 38 +-- srcs/key_manager.c | 393 ++++++++++++++++++++++++ srcs/key_manager.h | 46 +++ srcs/types.c | 255 ++++++++++++++++ srcs/types.h | 65 ++++ srcs/web_app_enc.c | 98 +++--- tests/internals.cpp | 325 ++++++++++---------- tests/non-normals.cpp | 8 +- tests/normals.cpp | 4 +- tests/test-common.cpp | 35 ++- tests/test-common.h | 7 +- tests/test-helper.cpp | 100 +++---- tests/test-helper.h | 4 +- 19 files changed, 1530 insertions(+), 929 deletions(-) create mode 100644 srcs/key_manager.c create mode 100644 srcs/key_manager.h create mode 100644 srcs/types.c create mode 100644 srcs/types.h diff --git a/srcs/CMakeLists.txt b/srcs/CMakeLists.txt index 3de6d18..0b44fdd 100644 --- a/srcs/CMakeLists.txt +++ b/srcs/CMakeLists.txt @@ -25,6 +25,8 @@ SET(WEB_APP_ENC_SOURCES key_handler.c crypto_service.c decrypt_migrated_wgt.c + types.c + key_manager.c ) INCLUDE_DIRECTORIES( diff --git a/srcs/crypto_service.c b/srcs/crypto_service.c index 0991d42..bd83eba 100644 --- a/srcs/crypto_service.c +++ b/srcs/crypto_service.c @@ -36,11 +36,6 @@ #define AES_256_KEY_SIZE 32 -static unsigned char AES_CBC_IV[16] = { - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F -}; - static bool __initialized = false; void _initialize() @@ -52,26 +47,27 @@ void _initialize() } } -int encrypt_app_dek(const unsigned char *pubkey, size_t pubkey_len, - const unsigned char *dek, size_t dek_len, - unsigned char **pencrypted_dek, size_t *pencrypted_dek_len) +int encrypt_app_dek(const raw_buffer_s *pubkey, const raw_buffer_s *dek, + raw_buffer_s **pencrypted_dek) { + 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; - BIO *bio = NULL; EVP_PKEY_CTX *ctx = NULL; - unsigned char *out = NULL; - size_t out_len = 0; + raw_buffer_s *encrypted_dek = NULL; + size_t len = 0; _initialize(); - bio = BIO_new(BIO_s_mem()); - BIO_write(bio, pubkey, pubkey_len); + 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, pubkey_len); + BIO_write(bio, pubkey->buf, pubkey->size); key = d2i_PUBKEY_bio(bio, NULL); } @@ -102,28 +98,26 @@ int encrypt_app_dek(const unsigned char *pubkey, size_t pubkey_len, } /* Determine buffer length */ - if (EVP_PKEY_encrypt(ctx, NULL, &out_len, dek, dek_len) <= 0) { + 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; goto error; } - out = OPENSSL_malloc(out_len); - - if (out == NULL) { + if ((encrypted_dek = buffer_create(len)) == NULL) { WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed"); ret = WAE_ERROR_MEMORY; goto error; } - if (EVP_PKEY_encrypt(ctx, out, &out_len, dek, dek_len) <= 0) { + 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 = WAE_ERROR_CRYPTO; goto error; } - *pencrypted_dek = out; - *pencrypted_dek_len = out_len; + *pencrypted_dek = encrypted_dek; error: if (bio != NULL) @@ -135,39 +129,41 @@ error: if (ctx != NULL) EVP_PKEY_CTX_free(ctx); - if (ret != WAE_ERROR_NONE && out != NULL) - OPENSSL_free(out); + if (ret != WAE_ERROR_NONE) + buffer_destroy(encrypted_dek); return ret; } -int decrypt_app_dek(const unsigned char *prikey, size_t prikey_len, - const char *prikey_pass, - const unsigned char *encrypted_dek, size_t encrypted_dek_len, - unsigned char **pdecrypted_dek, size_t *pdecrypted_dek_len) +int decrypt_app_dek(const raw_buffer_s *prikey, const char *prikey_pass, + const raw_buffer_s *encrypted_dek, raw_buffer_s **pdek) { + if (!is_buffer_valid(prikey) || !is_buffer_valid(encrypted_dek) || pdek == NULL) + return WAE_ERROR_INVALID_PARAMETER; + int ret = WAE_ERROR_NONE; - EVP_PKEY *key = NULL; - BIO *bio = NULL; EVP_PKEY_CTX *ctx = NULL; - unsigned char *out = NULL; - size_t out_len = 0; + raw_buffer_s *dek = NULL; + size_t len = 0; _initialize(); - bio = BIO_new(BIO_s_mem()); - BIO_write(bio, prikey, prikey_len); - key = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)prikey_pass); + 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, prikey_len); + BIO_write(bio, prikey->buf, prikey->size); key = d2i_PrivateKey_bio(bio, NULL); } if (key == NULL) { ret = WAE_ERROR_FILE; - WAE_SLOGE("Failt to convert to public key."); + WAE_SLOGE("Failed to convert to public key."); goto error; } @@ -192,28 +188,27 @@ int decrypt_app_dek(const unsigned char *prikey, size_t prikey_len, } /* Determine buffer length */ - if (EVP_PKEY_decrypt(ctx, NULL, &out_len, encrypted_dek, encrypted_dek_len) <= 0) { + 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; } - out = OPENSSL_malloc(out_len); - - if (out == NULL) { + dek = buffer_create(len); + if (dek == NULL) { WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed"); ret = WAE_ERROR_MEMORY; goto error; } - if (EVP_PKEY_decrypt(ctx, out, &out_len, encrypted_dek, encrypted_dek_len) <= 0) { + 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; } - *pdecrypted_dek = out; - *pdecrypted_dek_len = out_len; + *pdek = dek; error: if (bio != NULL) @@ -225,36 +220,40 @@ error: if (ctx != NULL) EVP_PKEY_CTX_free(ctx); - if (ret != WAE_ERROR_NONE && out != NULL) - OPENSSL_free(out); + if (ret != WAE_ERROR_NONE) + buffer_destroy(dek); return ret; } -int encrypt_aes_cbc(const unsigned char *key, size_t key_len, - const unsigned char *data, size_t data_len, - unsigned char **pencrypted_data, size_t *pencrypted_data_len) +int encrypt_aes_cbc(const crypto_element_s *ce, const raw_buffer_s *data, + raw_buffer_s **pencrypted_data) { - EVP_CIPHER_CTX *ctx; - int len; - unsigned char *ciphertext = NULL; - size_t ciphertext_len; - unsigned char *iv = AES_CBC_IV; + if (!is_crypto_element_valid(ce) || !is_buffer_valid(data) || pencrypted_data == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + EVP_CIPHER_CTX *ctx = NULL; + int len = 0; + raw_buffer_s *encrypted_data = NULL; int ret = WAE_ERROR_NONE; _initialize(); - WAE_SLOGI("Encryption Started. size=%d", data_len); + WAE_SLOGI("Encryption Started. size=%d", data->size); /* check input paramter */ - if (key_len != 32) { - WAE_SLOGE("Encryption Failed. Invalid Key Length. key_len=%d", key_len); + if (ce->dek->size != 32) { + WAE_SLOGE("Encryption Failed. Invalid Key Length. key_len=%d", ce->dek->size); return WAE_ERROR_INVALID_PARAMETER; } // assing a enough memory for decryption. - ciphertext = (unsigned char *) malloc(data_len + 32); + encrypted_data = buffer_create(data->size + 32); + if (encrypted_data == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } /* Create and initialise the context */ if (!(ctx = EVP_CIPHER_CTX_new())) { @@ -268,7 +267,7 @@ int encrypt_aes_cbc(const unsigned char *key, size_t key_len, * 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, key, iv)) { + if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, ce->dek->buf, ce->iv->buf) != 1) { WAE_SLOGE("Encryption Failed. EVP_EncryptInit_ex failed"); ret = WAE_ERROR_CRYPTO; goto error; @@ -277,64 +276,68 @@ int encrypt_aes_cbc(const unsigned char *key, size_t key_len, /* 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, data, data_len)) { + len = encrypted_data->size; + if (EVP_EncryptUpdate(ctx, encrypted_data->buf, &len, data->buf, + data->size) != 1) { WAE_SLOGE("Encryption Failed. EVP_EncryptUpdate failed"); ret = WAE_ERROR_CRYPTO; goto error; } - ciphertext_len = len; + encrypted_data->size = len; - /* Finalise the encryption. Further ciphertext bytes may be written at + /* Finalise the encryption. Further encrypted data bytes may be written at * this stage. */ - if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { + if (EVP_EncryptFinal_ex(ctx, encrypted_data->buf + encrypted_data->size, &len) != 1) { WAE_SLOGE("Encryption Failed. EVP_EncryptFinal_ex failed"); ret = WAE_ERROR_CRYPTO; goto error; } - ciphertext_len += len; + encrypted_data->size += len; - *pencrypted_data = ciphertext; - *pencrypted_data_len = ciphertext_len; + *pencrypted_data = encrypted_data; - ret = WAE_ERROR_NONE; - WAE_SLOGI("Encryption Ended Successfully. encrypted_len", ciphertext_len); + WAE_SLOGI("Encryption Ended Successfully. encrypted_len: %d", encrypted_data->size); error: if (ctx != NULL) EVP_CIPHER_CTX_free(ctx); - if (ret != WAE_ERROR_NONE && ciphertext != NULL) - free(ciphertext); + if (ret != WAE_ERROR_NONE) + buffer_destroy(encrypted_data); return ret; } -int decrypt_aes_cbc(const unsigned char *key, size_t key_len, - const unsigned char *data, size_t data_len, - unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) +int decrypt_aes_cbc(const crypto_element_s *ce, const raw_buffer_s *encrypted_data, + raw_buffer_s **pdata) { - EVP_CIPHER_CTX *ctx; - int len; - unsigned char *plaintext = NULL; - size_t plaintext_len; - unsigned char *iv = AES_CBC_IV; + if (!is_crypto_element_valid(ce) || !is_buffer_valid(encrypted_data) || pdata == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + EVP_CIPHER_CTX *ctx = NULL; + int len = 0; + raw_buffer_s *data = NULL; int ret = WAE_ERROR_NONE; _initialize(); - WAE_SLOGI("Decryption Started. size=%d", data_len); + WAE_SLOGI("Decryption Started. size=%d", encrypted_data->size); /* check input paramter */ - if (key_len != 32) { - WAE_SLOGE("Decryption Failed. Invalid Key Length. key_len=%d", key_len); + if (ce->dek->size != 32) { + WAE_SLOGE("Decryption Failed. Invalid Key Length. key_len=%d", ce->dek->size); return WAE_ERROR_INVALID_PARAMETER; } // assing a enough memory for decryption. - plaintext = (unsigned char *) malloc(data_len); + data = buffer_create(encrypted_data->size); + if (data == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } /* Create and initialise the context */ if (!(ctx = EVP_CIPHER_CTX_new())) { @@ -348,7 +351,7 @@ int decrypt_aes_cbc(const unsigned char *key, size_t key_len, * 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, key, iv)) { + if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, ce->dek->buf, ce->iv->buf) != 1) { WAE_SLOGE("Decryption Failed. EVP_DecryptInit_ex failed"); ret = WAE_ERROR_CRYPTO; goto error; @@ -357,37 +360,37 @@ int decrypt_aes_cbc(const unsigned char *key, size_t key_len, /* 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, data, data_len)) { + len = data->size; + if (EVP_DecryptUpdate(ctx, data->buf, &len, encrypted_data->buf, + encrypted_data->size) != 1) { WAE_SLOGE("Decryption Failed. EVP_DecryptUpdate failed"); ret = WAE_ERROR_CRYPTO; goto error; } - plaintext_len = len; + data->size = len; /* Finalise the decryption. Further plaintext bytes may be written at * this stage. */ - if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) { + if (EVP_DecryptFinal_ex(ctx, data->buf + data->size, &len) != 1) { WAE_SLOGE("Decryption Failed. EVP_DecryptFinal_ex failed"); ret = WAE_ERROR_CRYPTO; goto error; } - plaintext_len += len; + data->size += len; - *pdecrypted_data = plaintext; - *pdecrypted_data_len = plaintext_len; + *pdata = data; - ret = WAE_ERROR_NONE; - WAE_SLOGI("Decryption Ended Successfully. decrypted_len", plaintext_len); + WAE_SLOGI("Decryption Ended Successfully. decrypted_len: %d", data->size); error: if (ctx != NULL) EVP_CIPHER_CTX_free(ctx); - if (ret != WAE_ERROR_NONE && plaintext != NULL) - free(plaintext); + if (ret != WAE_ERROR_NONE) + buffer_destroy(data); return ret; } diff --git a/srcs/crypto_service.h b/srcs/crypto_service.h index 8a64d6d..c6340ae 100644 --- a/srcs/crypto_service.h +++ b/srcs/crypto_service.h @@ -26,25 +26,18 @@ extern "C" { #endif -#include +#include "types.h" -int encrypt_app_dek(const unsigned char *pubkey, size_t pubkey_len, - const unsigned char *dek, size_t dek_len, - unsigned char **encryptedDek, size_t *encryptedDekLen); +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 decrypt_app_dek(const unsigned char *prikey, size_t prikey_len, - const char *prikey_pass, - const unsigned char *encrypted_dek, size_t encrypted_dek_len, - unsigned char **pdecrypted_dek, size_t *pdecrypted_dek_len); - -int encrypt_aes_cbc(const unsigned char *key, size_t key_len, - const unsigned char *data, size_t data_len, - unsigned char **pencrypted_data, size_t *pencrypted_data_len); - -int decrypt_aes_cbc(const unsigned char *key, size_t key_len, - const unsigned char *data, size_t data_len, - unsigned char **pdecrypted_data, size_t *pdecrypted_data_len); +int encrypt_aes_cbc(const crypto_element_s *ce, const raw_buffer_s *data, + raw_buffer_s **pencrypted_data); +int decrypt_aes_cbc(const crypto_element_s *ce, const raw_buffer_s *encrypted_data, + raw_buffer_s **pdata); #ifdef __cplusplus } diff --git a/srcs/decrypt_migrated_wgt.c b/srcs/decrypt_migrated_wgt.c index dfaf28a..1012a35 100644 --- a/srcs/decrypt_migrated_wgt.c +++ b/srcs/decrypt_migrated_wgt.c @@ -33,7 +33,7 @@ #include "wae_log.h" #include "web_app_enc.h" -#define DUK_LEN 16 +#define DUK_SIZE 16 static void _logging_openssl_err() { @@ -45,64 +45,62 @@ static void _logging_openssl_err() WAE_SLOGE("Openssl err: %s", buf); } -static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_len) +static int _get_old_duk(const char *pkg_id, raw_buffer_s **pduk) { + if (pkg_id == NULL || pduk == NULL) + return WAE_ERROR_INVALID_PARAMETER; + unsigned char salt[32]; memset(salt, 0xFF, sizeof(salt)); - unsigned char *duk = (unsigned char *)malloc(sizeof(unsigned char) * ((DUK_LEN * 2) + 1)); - if (duk == NULL) { - WAE_SLOGE("Failed to allocate memory for old duk."); + raw_buffer_s *duk = buffer_create(DUK_SIZE * 2); + if (duk == NULL) return WAE_ERROR_MEMORY; - } if (PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1, - (DUK_LEN * 2), duk) != 1) { - free(duk); + duk->size, duk->buf) != 1) { + buffer_destroy(duk); return WAE_ERROR_CRYPTO; } - duk[DUK_LEN * 2] = '\0'; + duk->size = DUK_SIZE; *pduk = duk; - *pduk_len = DUK_LEN; - WAE_SLOGD("get old duk of length: %d", *pduk_len); + WAE_SLOGD("get old duk of length: %d", duk->size); return WAE_ERROR_NONE; } -static int _get_old_iv(const unsigned char *src, size_t src_len, unsigned char **piv, size_t *piv_len) +static int _get_old_iv(const raw_buffer_s *src, raw_buffer_s **piv) { - unsigned int iv_len = SHA_DIGEST_LENGTH; - unsigned char *iv = (unsigned char *)malloc(sizeof(unsigned char) * iv_len); + if (!is_buffer_valid(src) || piv == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + raw_buffer_s *iv = buffer_create(SHA_DIGEST_LENGTH); if (iv == NULL) return WAE_ERROR_MEMORY; - if (EVP_Digest(src, src_len, iv, &iv_len, EVP_sha1(), NULL) != 1) { - free(iv); + if (EVP_Digest(src->buf, src->size, iv->buf, &iv->size, EVP_sha1(), NULL) != 1) { + buffer_destroy(iv); return WAE_ERROR_CRYPTO; } *piv = iv; - *piv_len = iv_len; - WAE_SLOGD("get old iv of length: %d", *piv_len); + WAE_SLOGD("get old iv of length: %d", iv->size); return WAE_ERROR_NONE; } -static int _decrypt(const unsigned char *key, size_t key_len, - const unsigned char *iv, size_t iv_len, - const unsigned char *data, size_t data_len, - unsigned char **pdecrypted, size_t *pdecrypted_len) +static int _decrypt(const crypto_element_s *ce, const raw_buffer_s *data, + raw_buffer_s **pdecrypted) { - if (key == NULL || iv == NULL || data == NULL || pdecrypted == NULL || - pdecrypted_len == 0) + if (!is_crypto_element_valid(ce) || !is_buffer_valid(data) || pdecrypted == NULL) return WAE_ERROR_INVALID_PARAMETER; - if (key_len != 16 || iv_len < 16) { + if (ce->dek->size != DUK_SIZE || ce->iv->size < DUK_SIZE) { WAE_SLOGE("Invalid key or iv size for decrypt by aes_128_cbc algorithm. " "key should be 16 bytes and iv should be bigger than 16 bytes"); return WAE_ERROR_INVALID_PARAMETER; @@ -110,22 +108,22 @@ static int _decrypt(const unsigned char *key, size_t key_len, const struct evp_cipher_st *algo = EVP_aes_128_cbc(); - EVP_CIPHER_CTX ctx; - - size_t tmp_len = (data_len / algo->block_size + 1) * algo->block_size; - int decrypted_len = 0; + int in_len = data->size; + int out_len = 0; int final_len = 0; - unsigned char *decrypted = (unsigned char *)calloc(tmp_len, 1); + raw_buffer_s *decrypted = buffer_create( + (in_len / algo->block_size + 1) * algo->block_size); if (decrypted == NULL) return WAE_ERROR_MEMORY; + EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); int ret = WAE_ERROR_NONE; - if (EVP_CipherInit(&ctx, algo, key, iv, 0) != 1) { + if (EVP_CipherInit(&ctx, algo, ce->dek->buf, ce->iv->buf, 0) != 1) { ret = WAE_ERROR_CRYPTO; goto error; } @@ -135,66 +133,85 @@ static int _decrypt(const unsigned char *key, size_t key_len, goto error; } - if (EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len) != 1) { + if (EVP_CipherUpdate(&ctx, decrypted->buf, &out_len, data->buf, in_len) != 1) { ret = WAE_ERROR_CRYPTO; goto error; - } else if (decrypted_len <= 0) { - WAE_SLOGE("EVP_CipherUpdate success but returned decrypted_len(%d) <= 0", - decrypted_len); - ret = WAE_ERROR_UNKNOWN; - goto error; } - if (EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len) != 1) { + if (EVP_CipherFinal(&ctx, decrypted->buf + out_len, &final_len) != 1) { ret = WAE_ERROR_CRYPTO; goto error; - } else if (final_len <= 0) { - WAE_SLOGE("EVP_CipherFinal success but returned final_len(%d) <= 0", - final_len); - ret = WAE_ERROR_UNKNOWN; - goto error; } + decrypted->size = out_len + final_len; + *pdecrypted = decrypted; - *pdecrypted_len = decrypted_len + final_len; error: EVP_CIPHER_CTX_cleanup(&ctx); if (ret != WAE_ERROR_NONE) - free(decrypted); + buffer_destroy(decrypted); return ret; } -int decrypt_by_old_ss_algo(const char *pkg_id, const unsigned char *encrypted, size_t encrypted_len, - unsigned char **pdecrypted, size_t *pdecrypted_len) +int get_old_ss_crypto_element(const char *pkg_id, crypto_element_s **pce) { - unsigned char *duk = NULL; - size_t duk_len = 0; - unsigned char *iv = NULL; - size_t iv_len = 0; + if (pkg_id == NULL || pce == NULL) + return WAE_ERROR_INVALID_PARAMETER; - int ret = _get_old_duk(pkg_id, &duk, &duk_len); + raw_buffer_s *duk = NULL; + raw_buffer_s *iv = NULL; + crypto_element_s *ce = NULL; + int ret = _get_old_duk(pkg_id, &duk); if (ret != WAE_ERROR_NONE) - goto error; - - ret = _get_old_iv(duk, duk_len, &iv, &iv_len); + return ret; + ret = _get_old_iv(duk, &iv); if (ret != WAE_ERROR_NONE) goto error; - ret = _decrypt(duk, duk_len, iv, iv_len, encrypted, encrypted_len, pdecrypted, pdecrypted_len); + ce = crypto_element_create(duk, iv); + if (ce == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } - WAE_SLOGI("decrypt with old ss algo success of pkg: %s", pkg_id); + ce->is_migrated_app = true; + + *pce = ce; + + return WAE_ERROR_NONE; error: - if (ret == WAE_ERROR_CRYPTO) - _logging_openssl_err(); + buffer_destroy(duk); + buffer_destroy(iv); - free(duk); - free(iv); + return ret; +} - return WAE_ERROR_NONE; +int decrypt_by_old_ss_algo(const crypto_element_s *ce, const raw_buffer_s *encrypted, + raw_buffer_s **pdecrypted) +{ + if (!is_crypto_element_valid(ce) || !is_buffer_valid(encrypted) || pdecrypted == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + int ret = _decrypt(ce, encrypted, pdecrypted); + + switch (ret) { + case WAE_ERROR_CRYPTO: + WAE_SLOGE("decrypt with old ss algo failed with crypto error below."); + _logging_openssl_err(); + break; + case WAE_ERROR_NONE: + WAE_SLOGI("decrypt with old ss algo success!"); + break; + default: + WAE_SLOGE("decrypt with old ss algo failed! ret(%d)", ret); + break; + } + + return ret; } diff --git a/srcs/decrypt_migrated_wgt.h b/srcs/decrypt_migrated_wgt.h index 95f481e..42f99ad 100644 --- a/srcs/decrypt_migrated_wgt.h +++ b/srcs/decrypt_migrated_wgt.h @@ -22,10 +22,18 @@ #ifndef __WAE_SS_KEY_GENERATOR_H #define __WAE_SS_KEY_GENERATOR_H -#include +#ifdef __cplusplus +extern "C" { +#endif -int decrypt_by_old_ss_algo(const char *pkg_id, - const unsigned char *encrypted, size_t encrypted_len, - unsigned char **pdecrypted, size_t *pdecrypted_len); +#include "types.h" + +int get_old_ss_crypto_element(const char *pkg_id, crypto_element_s **pce); +int decrypt_by_old_ss_algo(const crypto_element_s *ce, const raw_buffer_s *encrypted, + raw_buffer_s **pdecrypted); + +#ifdef __cplusplus +} +#endif #endif /* __WAE_SS_KEY_GENERATOR_H */ diff --git a/srcs/key_handler.c b/srcs/key_handler.c index 0cb2776..af7280b 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -27,112 +27,55 @@ #include #include -#include #include #include "wae_log.h" -#include "web_app_enc.h" #include "crypto_service.h" +#include "key_manager.h" +#include "decrypt_migrated_wgt.h" #define RANDOM_FILE "/dev/urandom" #define APP_DEK_KEK_PRIKEY_PASSWORD "wae_appdek_kek_1q2w3e4r" -#define APP_DEK_ALIAS_PFX "APP_DEK_" -#define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED" #define APP_DEK_FILE_PFX "WAE_APP_DEK" -#define APP_DEK_KEK_ALIAS "WAE_APP_DEK_KEK" #define DEK_LEN 32 -#define MAX_ALIAS_LEN 256 +#define IV_LEN 16 #define MAX_PKGID_LEN 256 #define MAX_CACHE_SIZE 100 -typedef struct _dek_cache_element { - char pkg_id[MAX_PKGID_LEN]; - unsigned char dek[DEK_LEN]; -} dek_cache_element; +static unsigned char AES_CBC_IV[IV_LEN] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; -dek_cache_element APP_DEK_CACHE[MAX_CACHE_SIZE]; -int NEXT_CACHE_IDX = -1; +static crypto_element_map_s *_map; -void _initialize_cache() +static void deinit_lib(void) __attribute__((destructor)); +static void deinit_lib(void) { - NEXT_CACHE_IDX = 0; - memset(APP_DEK_CACHE, 0, sizeof(dek_cache_element) * MAX_CACHE_SIZE); + crypto_element_map_destroy(_map); } -const unsigned char *_get_app_dek_from_cache(const char *pkg_id) +static const crypto_element_s *_get_app_ce_from_cache(const char *pkg_id) { - if (NEXT_CACHE_IDX < 0) - _initialize_cache(); - - for (size_t i = 0; i < MAX_CACHE_SIZE; i++) { - //WAE_SLOGI("CACHED APP_DEK[%d]=%s", i, APP_DEK_CACHE[i].pkg_id); - if (strncmp(pkg_id, APP_DEK_CACHE[i].pkg_id, MAX_PKGID_LEN) == 0) - return APP_DEK_CACHE[i].dek; - } - - return NULL; + return crypto_element_map_get(_map, pkg_id); } -void _add_app_dek_to_cache(const char *pkg_id, const unsigned char *dek) +static int _add_app_ce_to_cache(const char *pkg_id, crypto_element_s *ce) { - if (NEXT_CACHE_IDX < 0) - _initialize_cache(); - - // if existing one has the same pkgid - for (size_t i = 0; i < MAX_CACHE_SIZE; i++) { - if (strncmp(pkg_id, APP_DEK_CACHE[i].pkg_id, MAX_PKGID_LEN) == 0) { - memcpy(APP_DEK_CACHE[i].dek, dek, DEK_LEN); - return; - } - } - - // for new pkgid - strncpy(APP_DEK_CACHE[NEXT_CACHE_IDX].pkg_id, pkg_id, MAX_PKGID_LEN - 1); - 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; + return crypto_element_map_add(&_map, pkg_id, ce); } -void _remove_app_dek_from_cache(const char *pkg_id) +void _remove_app_ce_from_cache(const char *pkg_id) { - for (size_t i = 0; i < MAX_CACHE_SIZE; i++) { - if (strncmp(pkg_id, APP_DEK_CACHE[i].pkg_id, MAX_PKGID_LEN) == 0) { - memset(APP_DEK_CACHE[i].pkg_id, 0, MAX_PKGID_LEN); - return; - } - } - + crypto_element_map_remove(&_map, pkg_id); } -int _to_wae_error(int key_manager_error) +int _get_random(raw_buffer_s *rb) { - switch (key_manager_error) { - case CKMC_ERROR_NONE: - return WAE_ERROR_NONE; - - case CKMC_ERROR_INVALID_PARAMETER: + if (!is_buffer_valid(rb)) 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 = fopen(RANDOM_FILE, "r"); if (f == NULL) { @@ -142,100 +85,95 @@ int _get_random(size_t length, unsigned char *random) size_t i = 0; int ch = 0; - while (i < length && (ch = fgetc(f) != EOF)) - random[i++] = (unsigned char)ch; + while (i < rb->size && (ch = fgetc(f) != EOF)) + rb->buf[i++] = (unsigned char)ch; fclose(f); return WAE_ERROR_NONE; } -void _get_alias(const char *pkg_id, wae_app_type_e app_type, bool forSave, char *alias, size_t buff_len) +static const char *_get_dek_kek_pub_key_path() { - if (app_type == WAE_DOWNLOADED_NORMAL_APP) { - if (forSave) { - snprintf(alias, buff_len, "%s%s", - APP_DEK_ALIAS_PFX, - pkg_id); - } else { - snprintf(alias, buff_len, "%c%s%s%s%s", - '/', INSTALLER_LABEL, - ckmc_owner_id_separator, - APP_DEK_ALIAS_PFX, - pkg_id); - } - } else { // system alias - snprintf(alias, buff_len, "%s%s%s%s", - ckmc_owner_id_system, - ckmc_owner_id_separator, - APP_DEK_ALIAS_PFX, - pkg_id); - } + return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem"); } -void _get_dek_kek_alias(char *alias, size_t buff_len) +static const char *_get_dek_kek_pri_key_path() { - snprintf(alias, buff_len, "%s%s%s", - ckmc_owner_id_system, - ckmc_owner_id_separator, - APP_DEK_KEK_ALIAS); + return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem"); } -void _get_dek_loading_done_alias(char *alias, size_t buff_len) +static const char *_get_dek_store_path() { - snprintf(alias, buff_len, "%s%s%s", - ckmc_owner_id_system, - ckmc_owner_id_separator, - APP_DEK_LOADING_DONE_ALIAS); + return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek"); } -const char *_get_dek_kek_pub_key_path() +static int _write_to_file(const char *path, const raw_buffer_s *data) { - return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem"); -} + if (path == NULL || data == NULL || data->buf == NULL || data->size == 0) + return WAE_ERROR_INVALID_PARAMETER; -const char *_get_dek_kek_pri_key_path() -{ - return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem"); -} + FILE *f = fopen(path, "w"); -const char *_get_dek_store_path() -{ - return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek"); + if (f == NULL) { + WAE_SLOGE("WAE: Fail to open a file. file=%s", path); + return WAE_ERROR_FILE; + } + + int write_len = fwrite(data->buf, 1, data->size, f); + + fclose(f); + + if (write_len != (int)data->size) { + WAE_SLOGE("WAE: Fail to write a file. file=%s", path); + return WAE_ERROR_FILE; + } + + return WAE_ERROR_NONE; } -int _add_dek_to_key_manager(const char *pkg_id, wae_app_type_e app_type, const unsigned char *dek, size_t dek_len) +static int _read_from_file(const char *path, raw_buffer_s **pdata) { int ret = WAE_ERROR_NONE; - char alias[MAX_ALIAS_LEN] = {0, }; - ckmc_raw_buffer_s buff; - ckmc_policy_s policy; - - buff.data = (unsigned char *)dek; - buff.size = dek_len; + raw_buffer_s *data = NULL; + int ch = 0; + int i = 0; - policy.password = NULL; - policy.extractable = true; + FILE *f = fopen(path, "r"); - _get_alias(pkg_id, app_type, true, alias, sizeof(alias)); + if (f == NULL) { + WAE_SLOGE("Failed to open a file. file=%s", path); + return WAE_ERROR_FILE; + } - // even if it fails to remove, ignore it. - ckmc_remove_alias(alias); + fseek(f, 0, SEEK_END); // move to the end of a file + int file_len = ftell(f); - ret = _to_wae_error(ckmc_save_data(alias, buff, policy)); - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("WAE: Fail to add APP_DEK to key-manager. pkg_id=%s, alias=%s, ret=%d", pkg_id, alias, ret); - return ret; + if (file_len <= 0) { + WAE_SLOGE("Failed to get file size by ftell. ret: %d", file_len); + ret = WAE_ERROR_FILE; + goto error; } - // share app_dek for web app laucher to use app_dek - ret = _to_wae_error(ckmc_set_permission(alias, pkg_id, CKMC_PERMISSION_READ)); - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("WAE: Fail to set_permission to APP_DEK. pkg_id=%s, ret=%d", pkg_id, ret); - return ret; + fseek(f, 0, SEEK_SET); // move to the start of a file + + data = buffer_create(file_len); + if (data == NULL) { + WAE_SLOGE("Failed to allocate memory for encrypted_dek"); + ret = WAE_ERROR_MEMORY; + goto error; } - WAE_SLOGI("WAE: Success to add APP_DEK to key-manager. pkg_id=%s, alias=%s", pkg_id, alias); + while ((ch = fgetc(f)) != EOF) + data->buf[i++] = (char)ch; + + *pdata = data; + +error: + fclose(f); + + if (ret != WAE_ERROR_NONE) + buffer_destroy(data); return ret; } @@ -251,7 +189,7 @@ int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path return WAE_ERROR_NONE; } -int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id) +static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id) { char *start = strstr(file_name, APP_DEK_FILE_PFX); @@ -274,238 +212,172 @@ int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id) return WAE_ERROR_NONE; } -int _read_encrypted_app_dek_from_file(const char *pkg_id, unsigned char **pencrypted_app_dek, size_t *pencrypted_app_dek_len) +int _read_encrypted_app_dek_from_file(const char *pkg_id, raw_buffer_s **pencrypted) { char path[MAX_PATH_LEN] = {0,}; _get_preloaded_app_dek_file_path(pkg_id, sizeof(path), path); - return _read_from_file(path, pencrypted_app_dek, pencrypted_app_dek_len); + return _read_from_file(path, pencrypted); } -int _write_encrypted_app_dek_to_file(const char *pkg_id, const unsigned char *encrypted_app_dek, size_t encrypted_app_dek_len) +int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *encrypted) { char path[MAX_PATH_LEN] = {0,}; _get_preloaded_app_dek_file_path(pkg_id, sizeof(path), path); - return _write_to_file(path, encrypted_app_dek, encrypted_app_dek_len); + return _write_to_file(path, encrypted); } -int _read_from_file(const char *path, unsigned char **pdata, size_t *pdata_len) +int get_app_ce(const char *pkg_id, wae_app_type_e app_type, bool create_for_migrated_app, + const crypto_element_s **pce) { - int ret = WAE_ERROR_NONE; - unsigned char *file_contents = NULL; - int ch = 0; - int i = 0; - - FILE *f = fopen(path, "r"); + if (pkg_id == NULL || pce == NULL) + return WAE_ERROR_INVALID_PARAMETER; - if (f == NULL) { - WAE_SLOGE("WAE: Fail to open a file. file=%s", path); - return WAE_ERROR_FILE; + const crypto_element_s *cached_ce = _get_app_ce_from_cache(pkg_id); + if (cached_ce != NULL) { + WAE_SLOGD("cache hit of app ce for pkg_id(%s)", pkg_id); + *pce = cached_ce; + return WAE_ERROR_NONE; } - fseek(f, 0, SEEK_END); // move to the end of a file - int file_len = ftell(f); + WAE_SLOGD("cache miss of app ce for pkg_id(%s)", pkg_id); - if (file_len <= 0) { - WAE_SLOGE("WAE: Failed to get file size by ftell. ret: %d", file_len); - ret = WAE_ERROR_FILE; - goto error; - } + crypto_element_s *ce = NULL; + int ret = get_from_key_manager(pkg_id, app_type, &ce); - fseek(f, 0, SEEK_SET); // move to the start of a file + if (create_for_migrated_app && + (ret == WAE_ERROR_NO_KEY && app_type == WAE_DOWNLOADED_GLOBAL_APP)) { + WAE_SLOGI("No dek found for pkg_id(%s)! It should be migrated app.", pkg_id); - file_contents = (unsigned char *)malloc(file_len); + if ((ret = get_old_ss_crypto_element(pkg_id, &ce)) != WAE_ERROR_NONE) + goto error; - if (file_contents == NULL) { - WAE_SLOGE("WAE: Fail to allocate memory for encrypted_app_dek"); - ret = WAE_ERROR_MEMORY; + // (k.tak) disable to save ce to key-maanger for migrated app because of permission issue. + //ret = save_to_key_manager(pkg_id, app_type, ce); + //if (ret != WAE_ERROR_NONE) { + // WAE_SLOGW("Failed to save migrated app ce to key-manager with ret(%d). " + // "Ignore this error because we can create ce later again.", ret); + // ret = WAE_ERROR_NONE; + //} + } else if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to get crypto element from key-manager. pkg_id=%s, ret=%d", + pkg_id, ret); goto error; } - memset(file_contents, 0x00, file_len); + ret = _add_app_ce_to_cache(pkg_id, ce); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret); + goto error; + } - while ((ch = fgetc(f)) != EOF) - file_contents[i++] = (char)ch; + *pce = ce; - *pdata = file_contents; - *pdata_len = file_len; + WAE_SLOGD("Successfully get ce! pkgid(%s)", pkg_id); -error: - fclose(f); + return WAE_ERROR_NONE; - if (ret != WAE_ERROR_NONE) - free(file_contents); +error: + crypto_element_destroy(ce); return ret; } -int _write_to_file(const char *path, const unsigned char *data, size_t data_len) +int create_app_ce(const char *pkg_id, wae_app_type_e app_type, const crypto_element_s **pce) { - FILE *f = fopen(path, "w"); + raw_buffer_s *dek = buffer_create(DEK_LEN); + raw_buffer_s *iv = buffer_create(IV_LEN); + crypto_element_s *ce = crypto_element_create(dek, iv); - if (f == NULL) { - WAE_SLOGE("WAE: Fail to open a file. file=%s", path); - return WAE_ERROR_FILE; - } - - int write_len = fwrite(data, 1, data_len, f); - - fclose(f); - - if (write_len != (int)data_len) { - WAE_SLOGE("WAE: Fail to write a file. file=%s", path); - return WAE_ERROR_FILE; - } - - return WAE_ERROR_NONE; -} - -int get_app_dek(const char *pkg_id, wae_app_type_e app_type, unsigned char **pdek, size_t *pdek_len) -{ int ret = WAE_ERROR_NONE; - ckmc_raw_buffer_s *dek_buffer = NULL; - char alias[MAX_ALIAS_LEN] = {0, }; - - const unsigned char *cached_dek = _get_app_dek_from_cache(pkg_id); - - if (cached_dek == NULL) { - // get APP_DEK from system database - _get_alias(pkg_id, app_type, false, alias, sizeof(alias)); - - ret = _to_wae_error(ckmc_get_data(alias, NULL, &dek_buffer)); - - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to get APP_DEK from key-manager. pkg_id=%s, alias=%s, ret=%d", - pkg_id, alias, ret); - goto error; - } else if (dek_buffer == NULL || dek_buffer->data == NULL) { - WAE_SLOGE("key-manager success but buffer is null for getting dek of pkg_id=%s", - pkg_id); - ret = WAE_ERROR_KEY_MANAGER; - goto error; - } else if (dek_buffer->size != DEK_LEN) { - WAE_SLOGE("DEK's length which has been saved in key-manager is not valid!"); - ret = WAE_ERROR_KEY_MANAGER; - goto error; - } - - WAE_SLOGD("Successfully get dek from key-manager for pkgid=%s", pkg_id); - cached_dek = dek_buffer->data; - } - - unsigned char *dek = (unsigned char *)malloc(DEK_LEN); - - if (dek == NULL) { - WAE_SLOGE("Fail to allocate a memory"); + if (ce == NULL) { ret = WAE_ERROR_MEMORY; goto error; } - memcpy(dek, cached_dek, DEK_LEN); - - *pdek = dek; - *pdek_len = DEK_LEN; - - WAE_SLOGI("WAE: Success to get APP_DEK from key-manager. pkg_id=%s, alias=%s", - pkg_id, alias); - -error: - ckmc_buffer_free(dek_buffer); - - if (ret != WAE_ERROR_NONE) - free(dek); - - return ret; -} - -int create_app_dek(const char *pkg_id, wae_app_type_e app_type, unsigned char **pdek, size_t *pdek_len) -{ - unsigned char *dek = (unsigned char *)malloc(DEK_LEN); - - if (dek == NULL) - return WAE_ERROR_MEMORY; - - int ret = _get_random(DEK_LEN, dek); + memcpy(ce->iv->buf, AES_CBC_IV, ce->iv->size); + ret = _get_random(dek); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("WAE: Fail to get random for APP_DEK. pkg_id=%s, ret=%d", pkg_id, ret); + WAE_SLOGE("Failed to get random for dek. pkg_id(%s) ret(%d)", pkg_id, ret); goto error; } - // save app_dek in key_manager - ret = _add_dek_to_key_manager(pkg_id, app_type, dek, DEK_LEN); - + ret = save_to_key_manager(pkg_id, app_type, ce); if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to save ce to key-manager. pkg_id(%s) app_type(%d) ret(%d)", + pkg_id, app_type, ret); goto error; } - // store APP_DEK in cache - _add_app_dek_to_cache(pkg_id, dek); + ret = _add_app_ce_to_cache(pkg_id, ce); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret); + goto error; + } - *pdek = dek; - *pdek_len = DEK_LEN; + *pce = ce; - WAE_SLOGI("WAE: Success to create APP_DEK and store it in key-manager. pkg_id=%s", pkg_id); + WAE_SLOGI("Success to create dek/iv and store it in key-manager. pkg_id(%s)", pkg_id); return WAE_ERROR_NONE; error: - free(dek); + if (ce == NULL) { + buffer_destroy(dek); + buffer_destroy(iv); + } else { + crypto_element_destroy(ce); + } return ret; } -int get_preloaded_app_dek(const char *pkg_id, unsigned char **pdek, size_t *pdek_len) +int get_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) { - const unsigned char *cached_dek = _get_app_dek_from_cache(pkg_id); + const crypto_element_s *cached_ce = _get_app_ce_from_cache(pkg_id); - if (cached_dek == NULL) { + if (cached_ce == NULL) { WAE_SLOGE("WAE: Fail to get APP_DEK from cache for preloaded app"); return WAE_ERROR_NO_KEY; } - unsigned char *dek = (unsigned char *)malloc(DEK_LEN); - - if (dek == NULL) { - WAE_SLOGE("WAE: Fail to allocate memory for preloaded app dek"); - return WAE_ERROR_MEMORY; - } - - memcpy(dek, cached_dek, DEK_LEN); - - *pdek = dek; - *pdek_len = DEK_LEN; + *pce = cached_ce; return WAE_ERROR_NONE; } -int create_preloaded_app_dek(const char *pkg_id, unsigned char **pdek, size_t *pdek_len) +int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) { - unsigned char *encrypted_app_dek = NULL; - size_t encrypted_app_dek_len = 0; - unsigned char *pubkey = NULL; - size_t pubkey_len = 0; + 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); - // create APP_DEK - unsigned char *dek = (unsigned char *)malloc(DEK_LEN); + int ret = WAE_ERROR_NONE; - if (dek == NULL) - return WAE_ERROR_MEMORY; + if (dek == NULL || iv == NULL || ce == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } - int ret = _get_random(DEK_LEN, dek); + ret = _get_random(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, &pubkey_len); + // 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, pubkey_len, dek, DEK_LEN, &encrypted_app_dek, &encrypted_app_dek_len); + ret = encrypt_app_dek(pubkey, dek, &encrypted_app_dek); if (ret != WAE_ERROR_NONE) { WAE_SLOGE("WAE: Fail to encrypt APP_DEK with APP_DEK_KEK"); @@ -513,139 +385,48 @@ int create_preloaded_app_dek(const char *pkg_id, unsigned char **pdek, size_t *p } // write APP_DEK in a file - ret = _write_encrypted_app_dek_to_file(pkg_id, encrypted_app_dek, encrypted_app_dek_len); + ret = _write_encrypted_app_dek_to_file(pkg_id, encrypted_app_dek); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("WAE: Fail to write encrypted APP_DEK. pkg_id=%s", pkg_id); + WAE_SLOGE("Failed to write encrypted dek to file. pkg_id(%s)", pkg_id); goto error; } // store APP_DEK in cache - _add_app_dek_to_cache(pkg_id, dek); - - *pdek = dek; - *pdek_len = DEK_LEN; - WAE_SLOGI("WAE: Success to create preleaded APP_DEK and write it in initail value file. pkg_id=%s", pkg_id); - -error: - free(pubkey); - free(encrypted_app_dek); - - if (ret != WAE_ERROR_NONE) - free(dek); - - return ret; -} - -int _get_app_dek_kek(unsigned char **pdek_kek, size_t *pdek_kek_len) -{ - int ret = _read_from_file(_get_dek_kek_pri_key_path(), pdek_kek, pdek_kek_len); - - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("WAE: Fail to read APP_DEK_KEK Private Key"); - return ret; - } - -#if 0 - ckmc_raw_buffer_s *kek_buffer = NULL; - unsigned char* kek = 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, NULL, &kek_buffer)); + _add_app_ce_to_cache(pkg_id, ce); 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; + WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret); + goto error; } - kek = (unsigned char *)malloc(kek_buffer->size); - if(kek == NULL) { - WAE_SLOGE("Fail to allocate a memory"); - ret = WAE_ERROR_MEMORY; - goto error; - } - memcpy(kek, kek_buffer->data, kek_buffer->size); + *pce = ce; - *pdek_kek = kek; - *pdek_kek_len = kek_buffer->size; - WAE_SLOGI("Success to get APP_DEK_KEK from key-manager."); + WAE_SLOGI("Success to create preleaded dek and write it in initial value file. " + "pkg_id(%s)", pkg_id); error: - ckmc_buffer_free(kek_buffer); - free(kek); -#endif - - return ret; -} - -int _get_app_deks_loaded() -{ - char loading_done_alias[MAX_ALIAS_LEN] = {0, }; - _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias)); - - ckmc_raw_buffer_s *buffer = NULL; - int ret = _to_wae_error(ckmc_get_data(loading_done_alias, NULL, &buffer)); - - if (ret == WAE_ERROR_NO_KEY) - WAE_SLOGI("WAE: APP_DEK_LOADING was not done"); - else if (ret == WAE_ERROR_NONE) - WAE_SLOGI("WAE: APP_DEK_LOADING was already done"); - else - WAE_SLOGE("WAE: Fail to get information from key-manager about APP_DEK_LOADING_DONE_ALIAS. ret=%d", ret); - - ckmc_buffer_free(buffer); + buffer_destroy(encrypted_app_dek); + buffer_destroy(pubkey); - return ret; -} - -int _set_app_deks_loaded() -{ - ckmc_raw_buffer_s buff; - ckmc_policy_s policy; - unsigned char dummy_data[1] = {0}; - - buff.data = dummy_data; - buff.size = sizeof(dummy_data); - - 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)); - - int ret = _to_wae_error(ckmc_save_data(loading_done_alias, buff, policy)); - - if (ret == WAE_ERROR_KEY_EXISTS) { - WAE_SLOGI("WAE: APP_DEK_LOADING was already done"); - ret = WAE_ERROR_NONE; - } else if (ret == WAE_ERROR_NONE) { - WAE_SLOGI("Success to set APP_DEK_LOADING_DONE_ALIAS to key-manager."); - } else { - WAE_SLOGE("WAE: Fail to set APP_DEK_LOADING_DONE_ALIAS to key-manager. ret=%d", ret); + if (ret != WAE_ERROR_NONE) { + if (ce) { + crypto_element_destroy(ce); + } else { + buffer_destroy(dek); + buffer_destroy(iv); + } } return ret; } -int _clear_app_deks_loaded() +int _get_app_dek_kek(raw_buffer_s **pdek_kek) { - char loading_done_alias[MAX_ALIAS_LEN] = {0, }; - _get_dek_loading_done_alias(loading_done_alias, sizeof(loading_done_alias)); - - int 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_SLOGI("Success to clear app deks loaded"); - } else { - WAE_SLOGE("Fail to clear APP_DEK_LOADING_DONE_ALIAS to key-manager. ret=%d", ret); - } - - return ret; +#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 } int load_preloaded_app_deks(bool reload) @@ -655,24 +436,23 @@ int load_preloaded_app_deks(bool reload) char pkg_id[MAX_PKGID_LEN] = {0, }; 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 prikey_len = 0; + raw_buffer_s *encrypted_dek = NULL; + raw_buffer_s *dek = NULL; + raw_buffer_s *iv = NULL; + raw_buffer_s *prikey = NULL; + crypto_element_s *ce = NULL; int error_during_loading = 0; if (!reload) { // check if all deks were already loaded into key-manager. - ret = _get_app_deks_loaded(); + ret = is_app_deks_loaded_in_key_manager(); if (ret == WAE_ERROR_NONE) return ret; } - ret = _get_app_dek_kek(&prikey, &prikey_len); + ret = _get_app_dek_kek(&prikey); if (ret != WAE_ERROR_NONE) { WAE_SLOGE("Fail to get APP_DEK_KEK Private Key"); @@ -706,7 +486,6 @@ int load_preloaded_app_deks(bool reload) if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL) continue; - memset(file_path_buff, 0, sizeof(file_path_buff)); ret = snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", _get_dek_store_path(), entry.d_name); @@ -719,75 +498,92 @@ int load_preloaded_app_deks(bool reload) ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id); if (ret != WAE_ERROR_NONE) { - WAE_SLOGW("Fail to extract pkgid from file. It will be ignored. file=%s", file_path_buff); + WAE_SLOGW("Failed 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); + ret = _read_from_file(file_path_buff, &encrypted_dek); - 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); + if (ret != WAE_ERROR_NONE || encrypted_dek == NULL) { + ++error_during_loading; + WAE_SLOGW("Failed to read file. It will be ignored. file=%s", file_path_buff); continue; } - ret = decrypt_app_dek(prikey, prikey_len, APP_DEK_KEK_PRIKEY_PASSWORD, - encrypted_app_dek, encrypted_app_dek_len, - &app_dek, &app_dek_len); + ret = decrypt_app_dek(prikey, APP_DEK_KEK_PRIKEY_PASSWORD, encrypted_dek, &dek); - 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); + buffer_destroy(encrypted_dek); + encrypted_dek = NULL; + + if (ret != WAE_ERROR_NONE || dek == NULL) { + ++error_during_loading; + WAE_SLOGW("Failed to decrypt dek. It will be ignored. file=%s", + file_path_buff); continue; } + iv = buffer_create(IV_LEN); + if (iv == NULL) { + ++error_during_loading; + buffer_destroy(dek); + dek = NULL; + continue; + } + + memcpy(iv->buf, AES_CBC_IV, iv->size); - // save app_dek in key_manager - ret = _add_dek_to_key_manager(pkg_id, WAE_PRELOADED_APP, app_dek, app_dek_len); - // free temp objects - free(app_dek); - free(encrypted_app_dek); - app_dek = NULL; - encrypted_app_dek = NULL; + ce = crypto_element_create(dek, iv); + if (ce == NULL) { + ++error_during_loading; + buffer_destroy(iv); + iv = NULL; + buffer_destroy(dek); + dek = NULL; + continue; + } + + ret = save_to_key_manager(pkg_id, WAE_PRELOADED_APP, ce); if (ret == WAE_ERROR_KEY_EXISTS) { - WAE_SLOGI("Key Manager already has APP_DEK. It will be ignored. file=%s", file_path_buff); + WAE_SLOGI("Key Manager already has dek. It will be ignored. file=%s", + file_path_buff); } else if (ret != WAE_ERROR_NONE) { - error_during_loading++; + ++error_during_loading; WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s", file_path_buff); } + + crypto_element_destroy(ce); + ce = NULL; } - ret = _set_app_deks_loaded(); + ret = set_app_deks_loaded_to_key_manager(); - 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 (ret != WAE_ERROR_NONE) { + if (ce) { + crypto_element_destroy(ce); + } else { + buffer_destroy(dek); + buffer_destroy(iv); + } } -error: - free(prikey); + buffer_destroy(prikey); closedir(dir); return ret; } -int remove_app_dek(const char *pkg_id, wae_app_type_e app_type) +int remove_app_ce(const char *pkg_id, wae_app_type_e app_type) { - char alias[MAX_ALIAS_LEN] = {0,}; - - _get_alias(pkg_id, app_type, true, alias, sizeof(alias)); - - int ret = _to_wae_error(ckmc_remove_alias(alias)); + int ret = remove_from_key_manager(pkg_id, app_type); - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Fail to remove APP_DEK from key-manager. pkg_id=%s, alias=%s, ret=%d", pkg_id, alias, ret); - return ret; - } + if (ret != WAE_ERROR_NONE) + WAE_SLOGE("Failed to remove app ce for pkg_id(%s) ret(%d)", pkg_id, ret); + else + WAE_SLOGI("Success to remove app ce for pkg_id(%s)", pkg_id); - _remove_app_dek_from_cache(pkg_id); - WAE_SLOGI("Success to remove APP_DEK from key-manager. pkg_id=%s", pkg_id); + _remove_app_ce_from_cache(pkg_id); - return WAE_ERROR_NONE; + return ret; } diff --git a/srcs/key_handler.h b/srcs/key_handler.h index c2e65a7..e64d81c 100644 --- a/srcs/key_handler.h +++ b/srcs/key_handler.h @@ -28,40 +28,28 @@ extern "C" { #include #include + #include "web_app_enc.h" +#include "types.h" #define MAX_PATH_LEN 512 /* functions with "_" prefix are internal static functions but declared here for testing */ -void _initialize_cache(); -const unsigned char *_get_app_dek_from_cache(const char *pkg_id); -void _add_app_dek_to_cache(const char *pkg_id, const unsigned char *dek); -void _remove_app_dek_from_cache(const char *pkg_id); -int _get_random(size_t length, unsigned char *random); -void _get_alias(const char *pkg_id, wae_app_type_e app_type, bool forSave, 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 *pkg_id, wae_app_type_e app_type, const unsigned char *dek, size_t dek_len); +void _remove_app_ce_from_cache(const char *pkg_id); +int _get_random(raw_buffer_s *rb); int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path); -int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id); -int _read_encrypted_app_dek_from_file(const char *pkg_id, unsigned char **pencrypted_app_dek, size_t *pencrypted_app_dek_len); -int _write_encrypted_app_dek_to_file(const char *pkg_id, const unsigned char *encrypted_app_dek, size_t encrypted_app_dek_len); -int _read_from_file(const char *path, unsigned char **pdata, size_t *pdata_len); -int _write_to_file(const char *path, const unsigned char *data, size_t data_len); -int _get_app_deks_loaded(); -int _set_app_deks_loaded(); -int _clear_app_deks_loaded(); +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); /* functions for interface */ -int get_app_dek(const char *pkg_id, wae_app_type_e app_type, unsigned char **pdek, size_t *pdek_len); -int create_app_dek(const char *pkg_id, wae_app_type_e app_type, unsigned char **pdek, size_t *pdek_len); -int get_preloaded_app_dek(const char *pkg_id, unsigned char **pdek, size_t *pdek_len); -int create_preloaded_app_dek(const char *pkg_id, unsigned char **pdek, size_t *pdek_len); +int get_app_ce(const char *pkg_id, wae_app_type_e app_type, bool create_for_migrated_app, + const crypto_element_s **pce); +int create_app_ce(const char *pkg_id, wae_app_type_e app_type, + const crypto_element_s **pce); +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); int load_preloaded_app_deks(bool reload); -int remove_app_dek(const char *pkg_id, wae_app_type_e app_type); +int remove_app_ce(const char *pkg_id, wae_app_type_e app_type); #ifdef __cplusplus } diff --git a/srcs/key_manager.c b/srcs/key_manager.c new file mode 100644 index 0000000..4ef5b8a --- /dev/null +++ b/srcs/key_manager.c @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2016 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_manager.c + * @author Kyungwook Tak + * @version 1.0 + * @brief Serialize/deserialize crypto element and save/get to key-manager + */ +#include "key_manager.h" + +#include +#include +#include + +#include + +#include "wae_log.h" + +#define MAX_ALIAS_LEN 256 +#define APP_DEK_ALIAS_PFX "APP_DEK_" +#define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED" +#define APP_DEK_KEK_ALIAS "WAE_APP_DEK_KEK" + +static 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; + + case CKMC_ERROR_OUT_OF_MEMORY: + return WAE_ERROR_MEMORY; + + default: + return WAE_ERROR_KEY_MANAGER; + } +} + +static int _serialize(const crypto_element_s *ce, ckmc_raw_buffer_s **pbuf) +{ + if (!is_crypto_element_valid(ce) || pbuf == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + size_t total_len = sizeof(size_t) * 3 + ce->dek->size + ce->iv->size + sizeof(bool); + + WAE_SLOGD("(serialization) total(%d) dek(%d) iv(%d) is_migrated(%d)", + total_len, ce->dek->size, ce->iv->size, ce->is_migrated_app); + + unsigned char *_buf = (unsigned char *)malloc(total_len); + if (_buf == NULL) + return WAE_ERROR_MEMORY; + + ckmc_raw_buffer_s *buf = NULL; + int ret = _to_wae_error(ckmc_buffer_new(_buf, total_len, &buf)); + + free(_buf); + + if (ret != WAE_ERROR_NONE) + return ret; + + size_t pos = 0; + memcpy(buf->data, &total_len, sizeof(size_t)); + pos += sizeof(size_t); + memcpy(buf->data + pos, &ce->dek->size, sizeof(size_t)); + pos += sizeof(size_t); + memcpy(buf->data + pos, ce->dek->buf, ce->dek->size); + pos += ce->dek->size; + memcpy(buf->data + pos, &ce->iv->size, sizeof(size_t)); + pos += sizeof(size_t); + memcpy(buf->data + pos, ce->iv->buf, ce->iv->size); + pos += ce->iv->size; + memcpy(buf->data + pos, &ce->is_migrated_app, sizeof(bool)); + pos += sizeof(bool); + + if (total_len != pos) { + WAE_SLOGE("(serialization) total len(%d) and actualy written byte(%d) " + "isn't matched!", total_len, pos); + ckmc_buffer_free(buf); + return WAE_ERROR_UNKNOWN; + } + + *pbuf = buf; + + WAE_SLOGD("(serialization) success!"); + + return WAE_ERROR_NONE; +} + +static int _deserialize(const ckmc_raw_buffer_s *buf, crypto_element_s **pce) +{ + if (buf == NULL || buf->data == NULL || buf->size == 0 || pce == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + size_t dek_size = 0; + size_t iv_size = 0; + bool is_migrated_app = false; + size_t pos = 0; + size_t total_len = 0; + crypto_element_s *ce = NULL; + + memcpy(&total_len, buf->data, sizeof(size_t)); + pos += sizeof(size_t); + + if (buf->size != total_len) { + WAE_SLOGE("(deserialization) total len(%d) and actualy written byte(%d) " + "isn't matched!", total_len, buf->size); + return WAE_ERROR_UNKNOWN; + } + + // deserialize dek size + memcpy(&dek_size, buf->data + pos, sizeof(size_t)); + pos += sizeof(size_t); + + raw_buffer_s *dek = buffer_create(dek_size); + if (dek == NULL) + return WAE_ERROR_MEMORY; + + // deserialize dek + memcpy(dek->buf, buf->data + pos, dek->size); + pos += dek->size; + + // deserialize iv size + memcpy(&iv_size, buf->data + pos, sizeof(size_t)); + pos += sizeof(size_t); + + raw_buffer_s *iv = buffer_create(iv_size); + int ret = WAE_ERROR_NONE; + if (iv == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } + + // deserialize iv + memcpy(iv->buf, buf->data + pos, iv->size); + pos += iv->size; + + // deserialize is_migrated_app + memcpy(&is_migrated_app, buf->data + pos, sizeof(bool)); + pos += sizeof(bool); + + WAE_SLOGD("(deserialization) total(%d) dek(%d) iv(%d) is_migrated(%d)", + total_len, dek_size, iv_size, is_migrated_app); + + if (pos != buf->size) { + WAE_SLOGE("(deserialization) raw buffer remained after deserializatation done!"); + ret = WAE_ERROR_UNKNOWN; + goto error; + } + + ce = crypto_element_create(dek, iv); + if (ce == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } + + ce->is_migrated_app = is_migrated_app; + + *pce = ce; + + WAE_SLOGD("(deserialization) success!"); + + return WAE_ERROR_NONE; + +error: + buffer_destroy(dek); + buffer_destroy(iv); + + return ret; +} + +static void _get_alias(const char *pkg_id, wae_app_type_e type, bool forSave, + char *alias, size_t buff_len) +{ + if (type == WAE_DOWNLOADED_NORMAL_APP) { + if (forSave) { + snprintf(alias, buff_len, "%s%s", + APP_DEK_ALIAS_PFX, + pkg_id); + } else { + snprintf(alias, buff_len, "%c%s%s%s%s", + '/', INSTALLER_LABEL, + ckmc_owner_id_separator, + APP_DEK_ALIAS_PFX, + pkg_id); + } + } else { // system alias + snprintf(alias, buff_len, "%s%s%s%s", + ckmc_owner_id_system, + ckmc_owner_id_separator, + APP_DEK_ALIAS_PFX, + pkg_id); + } +} + +static void _get_dek_loading_done_alias(char *alias, size_t buff_len) +{ + snprintf(alias, buff_len, "%s%s%s", + ckmc_owner_id_system, + ckmc_owner_id_separator, + APP_DEK_LOADING_DONE_ALIAS); +} + +bool is_app_deks_loaded_in_key_manager() +{ + char alias[MAX_ALIAS_LEN] = {0, }; + + _get_dek_loading_done_alias(alias, sizeof(alias)); + + ckmc_raw_buffer_s *buf = NULL; + int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf)); + + ckmc_buffer_free(buf); + + switch (ret) { + case WAE_ERROR_NONE: + return true; + case WAE_ERROR_NO_KEY: + WAE_SLOGI("app dek loading isn't done yet"); + return false; + default: + WAE_SLOGE("Failed to get dek loading flag data from key-manager. ret(%d)", ret); + return false; + } +} + +int set_app_deks_loaded_to_key_manager() +{ + unsigned char dummy_data[1] = {0}; + ckmc_raw_buffer_s buf; + buf.data = dummy_data; + buf.size = sizeof(dummy_data); + + ckmc_policy_s policy; + policy.password = NULL; + policy.extractable = true; + + char alias[MAX_ALIAS_LEN] = {0, }; + _get_dek_loading_done_alias(alias, sizeof(alias)); + + int ret = _to_wae_error(ckmc_save_data(alias, buf, policy)); + if (ret == WAE_ERROR_KEY_EXISTS) + ret = WAE_ERROR_NONE; + + return ret; +} + +int clear_app_deks_loaded_from_key_manager() +{ + char alias[MAX_ALIAS_LEN] = {0, }; + _get_dek_loading_done_alias(alias, sizeof(alias)); + + return _to_wae_error(ckmc_remove_alias(alias)); +} + +int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce) +{ + char alias[MAX_ALIAS_LEN] = {0, }; + + _get_alias(pkg_id, type, true, alias, sizeof(alias)); + + ckmc_raw_buffer_s *buf = NULL; + int ret = _serialize(ce, &buf); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to serialize crypto element of pkg_id: %s", pkg_id); + return ret; + } + + ckmc_policy_s policy; + policy.password = NULL; + policy.extractable = true; + + ret = _to_wae_error(ckmc_save_data(alias, *buf, policy)); + + ckmc_buffer_free(buf); + + if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to add crypto element to ckm: pkg_id(%s) alias(%s) ret(%d)", + pkg_id, alias, ret); + return ret; + } + + ret = _to_wae_error(ckmc_set_permission(alias, pkg_id, CKMC_PERMISSION_READ)); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Failed to set perm of crypto element: pkg_id(%s) alias(%s) ret(%d)", + pkg_id, alias, ret); + + ckmc_remove_alias(alias); // rollback + return ret; + } + + WAE_SLOGI("Success to save crypto element to key-manager. pkg_id(%s)", pkg_id); + + return WAE_ERROR_NONE; +} + +int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element_s **pce) +{ + if (pkg_id == NULL || pce == NULL) + return WAE_ERROR_INVALID_PARAMETER; + + char alias[MAX_ALIAS_LEN] = {0, }; + + _get_alias(pkg_id, type, false, alias, sizeof(alias)); + + ckmc_raw_buffer_s *buf = NULL; + int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf)); + if (ret != WAE_ERROR_NONE) + return ret; + + ret = _deserialize(buf, pce); + + ckmc_buffer_free(buf); + + return ret; +} + +int remove_from_key_manager(const char *pkg_id, wae_app_type_e type) +{ + char alias[MAX_ALIAS_LEN] = {0, }; + + _get_alias(pkg_id, type, true, alias, sizeof(alias)); + + return _to_wae_error(ckmc_remove_alias(alias)); +} + +static void _get_dek_kek_alias(char *alias, size_t buff_len) +{ + snprintf(alias, buff_len, "%s%s%s", + ckmc_owner_id_system, + ckmc_owner_id_separator, + APP_DEK_KEK_ALIAS); +} + +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, }; + _get_dek_kek_alias(alias, sizeof(alias)); + + int 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; +} diff --git a/srcs/key_manager.h b/srcs/key_manager.h new file mode 100644 index 0000000..ec84561 --- /dev/null +++ b/srcs/key_manager.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 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_manager.h + * @author Kyungwook Tak + * @version 1.0 + * @brief Serialize/deserialize crypto element and save/get to key-manager + */ +#ifndef __WAE_KEY_MANAGER_H +#define __WAE_KEY_MANAGER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "web_app_enc.h" +#include "types.h" + +int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce); +int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element_s **pce); +int remove_from_key_manager(const char *pkg_id, wae_app_type_e type); + +bool is_app_deks_loaded_in_key_manager(); +int set_app_deks_loaded_to_key_manager(); +int clear_app_deks_loaded_from_key_manager(); + +#ifdef __cplusplus +} +#endif + +#endif /* __WAE_KEY_MANAGER_H */ diff --git a/srcs/types.c b/srcs/types.c new file mode 100644 index 0000000..fc76c33 --- /dev/null +++ b/srcs/types.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2016 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 types.c + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief Type definitions + */ +#include "types.h" + +#include +#include + +#include "wae_log.h" +#include "web_app_enc.h" + +const size_t MAX_MAP_ELEMENT_SIZE = 20; + +raw_buffer_s *buffer_create(size_t size) +{ + raw_buffer_s *rb = (raw_buffer_s *)malloc(sizeof(raw_buffer_s)); + if (rb == NULL) + return NULL; + + rb->buf = (unsigned char *)malloc(sizeof(unsigned char) * size); + if (rb->buf == NULL) { + free(rb); + return NULL; + } + + memset(rb->buf, 0x00, size); + + rb->size = size; + + return rb; +} + +raw_buffer_s *buffer_create_managed(unsigned char *buf, size_t size) +{ + if (buf == NULL || size == 0) + return NULL; + + raw_buffer_s *rb = (raw_buffer_s *)malloc(sizeof(raw_buffer_s)); + if (rb == NULL) + return NULL; + + rb->buf = buf; + rb->size = size; + + return rb; +} + +void buffer_destroy(raw_buffer_s *rb) +{ + if (rb == NULL) + return; + + free(rb->buf); + free(rb); +} + +bool is_buffer_valid(const raw_buffer_s *rb) +{ + return rb != NULL && rb->buf != NULL && rb->size != 0; +} + +crypto_element_s *crypto_element_create(raw_buffer_s *dek, raw_buffer_s *iv) +{ + if (dek == NULL || iv == NULL) + return NULL; + + crypto_element_s *ce = (crypto_element_s *)malloc(sizeof(crypto_element_s)); + if (ce == NULL) + return NULL; + + ce->dek = dek; + ce->iv = iv; + ce->is_migrated_app = false; + + return ce; +} + +void crypto_element_destroy(crypto_element_s *ce) +{ + if (ce == NULL) + return; + + buffer_destroy(ce->dek); + buffer_destroy(ce->iv); + free(ce); +} + +bool is_crypto_element_valid(const crypto_element_s *ce) +{ + return ce != NULL && is_buffer_valid(ce->dek) && is_buffer_valid(ce->iv); +} + +struct _crypto_element_map_s { + char *key; + crypto_element_s *value; + crypto_element_map_s *next; +}; + +static crypto_element_map_s *crypto_element_map_create() +{ + crypto_element_map_s *cem = (crypto_element_map_s *)malloc(sizeof(crypto_element_map_s)); + if (cem == NULL) + return NULL; + + cem->key = NULL; + cem->value = NULL; + cem->next = NULL; + + return cem; +} + +void crypto_element_map_destroy(crypto_element_map_s *cem) +{ + if (cem == NULL) + return; + + crypto_element_map_s *current = cem; + while (current) { + WAE_SLOGD("Destroy crypto element of key(%s)", current->key); + crypto_element_map_s *tmp = current->next; + + free(current->key); + crypto_element_destroy(current->value); + free(current); + + current = tmp; + } +} + +int crypto_element_map_add(crypto_element_map_s **map, + const char *key, crypto_element_s *value) +{ + if (map == NULL || key == NULL || !is_crypto_element_valid(value)) + return WAE_ERROR_INVALID_PARAMETER; + + crypto_element_map_s *last = *map; + size_t count = 0; + for (crypto_element_map_s *current = *map; current != NULL; current = current->next) { + if (strcmp(current->key, key) == 0) { + WAE_SLOGD("Update value to map on existing key(%s)", key); + crypto_element_destroy(current->value); + current->value = value; + return WAE_ERROR_NONE; + } + + ++count; + last = current; + } + + WAE_SLOGD("Add value to map on new key(%s)", key); + crypto_element_map_s *e = crypto_element_map_create(); + if (e == NULL) + return WAE_ERROR_MEMORY; + + e->key = strdup(key); + if (e->key == NULL) { + free(e); + return WAE_ERROR_MEMORY; + } + + e->value = value; + e->next = NULL; + + if (last == NULL) + *map = e; + else + last->next = e; + + if (count == MAX_MAP_ELEMENT_SIZE) { + WAE_SLOGD("Map size touched max! Remove one element from the front(%s)", + (*map)->key); + + crypto_element_map_s *next = (*map)->next; + + crypto_element_destroy((*map)->value); + free((*map)->key); + free(*map); + + *map = next; + } + + return WAE_ERROR_NONE; +} + +void crypto_element_map_remove(crypto_element_map_s **map, const char *key) +{ + if (map == NULL || key == NULL) + return; + + if (*map == NULL) { + WAE_SLOGD("Map is empty so remove operation ignored for key(%s)", key); + return; + } + + crypto_element_map_s *before = NULL; + crypto_element_map_s *current = *map; + while (current) { + if (strcmp(key, current->key) != 0) { + before = current; + current = current->next; + continue; + } + + WAE_SLOGD("Removing value mapped by key(%s)", key); + + crypto_element_map_s *next = current->next; + + free(current->key); + crypto_element_destroy(current->value); + free(current); + + if (before == NULL) + *map = next; + else + before->next = next; + + break; + } +} + +crypto_element_s *crypto_element_map_get(crypto_element_map_s *map, const char *key) +{ + if (map == NULL || key == NULL) { + WAE_SLOGD("Map is empty so nothing to get."); + return NULL; + } + + for (crypto_element_map_s *current = map; current != NULL; current = current->next) { + if (strcmp(key, current->key) == 0) { + WAE_SLOGD("Getting value mapped by key(%s)", key); + return current->value; + } + } + + WAE_SLOGD("Cannot get value mapped by key(%s). No mapped value!", key); + return NULL; +} diff --git a/srcs/types.h b/srcs/types.h new file mode 100644 index 0000000..7e27aeb --- /dev/null +++ b/srcs/types.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016 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 types.h + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief Type definitions + */ +#ifndef __WAE_TYPES_H +#define __WAE_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef struct _raw_buffer_s { + unsigned char *buf; + size_t size; +} raw_buffer_s; + +typedef struct _crypto_element_s { + raw_buffer_s *dek; + raw_buffer_s *iv; + bool is_migrated_app; +} crypto_element_s; + +typedef struct _crypto_element_map_s crypto_element_map_s; + +raw_buffer_s *buffer_create(size_t size); +raw_buffer_s *buffer_create_managed(unsigned char *buf, size_t size); +void buffer_destroy(raw_buffer_s *); +bool is_buffer_valid(const raw_buffer_s *); + +crypto_element_s *crypto_element_create(raw_buffer_s *dek, raw_buffer_s *iv); +void crypto_element_destroy(crypto_element_s *c); +bool is_crypto_element_valid(const crypto_element_s *); + +extern const size_t MAX_MAP_ELEMENT_SIZE; + +void crypto_element_map_destroy(crypto_element_map_s *); +int crypto_element_map_add(crypto_element_map_s **map, const char *key, crypto_element_s *value); +void crypto_element_map_remove(crypto_element_map_s **map, const char *key); +crypto_element_s *crypto_element_map_get(crypto_element_map_s *map, const char *key); + +#ifdef __cplusplus +} +#endif + +#endif /* __WAE_TYPES_H */ diff --git a/srcs/web_app_enc.c b/srcs/web_app_enc.c index 083addf..22da420 100644 --- a/srcs/web_app_enc.c +++ b/srcs/web_app_enc.c @@ -26,6 +26,7 @@ #include "decrypt_migrated_wgt.h" #include "key_handler.h" #include "crypto_service.h" +#include "types.h" #include "wae_log.h" int _wae_encrypt_downloaded_web_application( @@ -37,57 +38,65 @@ int _wae_encrypt_downloaded_web_application( pencrypted_data_len == NULL) return WAE_ERROR_INVALID_PARAMETER; - // get APP_DEK. - // if not exists, create APP_DEK - unsigned char *dek = NULL; - size_t dek_len = -1; - int ret = get_app_dek(pkg_id, app_type, &dek, &dek_len); + const crypto_element_s *e = NULL; + int ret = get_app_ce(pkg_id, app_type, false, &e); if (ret == WAE_ERROR_NO_KEY) - ret = create_app_dek(pkg_id, app_type, &dek, &dek_len); + ret = create_app_ce(pkg_id, app_type, &e); if (ret != WAE_ERROR_NONE) - goto error; + return ret; - // encrypt - ret = encrypt_aes_cbc(dek, dek_len, data, data_len, pencrypted_data, pencrypted_data_len); + raw_buffer_s _data; + _data.buf = (unsigned char *)data; + _data.size = data_len; -error: - free(dek); + raw_buffer_s *_encrypted_data = NULL; + ret = encrypt_aes_cbc(e, &_data, &_encrypted_data); + if (ret != WAE_ERROR_NONE) + return ret; + + *pencrypted_data = _encrypted_data->buf; + *pencrypted_data_len = _encrypted_data->size; - return ret; + free(_encrypted_data); + + return WAE_ERROR_NONE; } int _wae_decrypt_downloaded_web_application(const char *pkg_id, wae_app_type_e app_type, const unsigned char *data, size_t data_len, unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) { - if (pkg_id == NULL || data == NULL || data_len == 0 || pdecrypted_data == NULL || pdecrypted_data_len == NULL) return WAE_ERROR_INVALID_PARAMETER; - unsigned char *dek = NULL; - size_t dek_len = -1; - int ret = get_app_dek(pkg_id, app_type, &dek, &dek_len); + raw_buffer_s _data; + _data.buf = (unsigned char *)data; + _data.size = data_len; + + const crypto_element_s *ce = NULL; + int ret = get_app_ce(pkg_id, app_type, true, &ce); + + if (ret != WAE_ERROR_NONE) + return ret; - if (app_type == WAE_DOWNLOADED_GLOBAL_APP && ret == WAE_ERROR_NO_KEY) { - WAE_SLOGI("app dek for decrypt downloaded app(%s) doesn't exist. This case would be " - "needed secure-storage data migration.", pkg_id); + raw_buffer_s *_decrypted_data = NULL; + if (ce->is_migrated_app) + ret = decrypt_by_old_ss_algo(ce, &_data, &_decrypted_data); + else + ret = decrypt_aes_cbc(ce, &_data, &_decrypted_data); - ret = decrypt_by_old_ss_algo(pkg_id, data, data_len, pdecrypted_data, pdecrypted_data_len); - goto error; // always go to error to skip decyprt_aes_cbc - } else if (ret != WAE_ERROR_NONE) { - goto error; - } + if (ret != WAE_ERROR_NONE) + return ret; - // decrypt - ret = decrypt_aes_cbc(dek, dek_len, data, data_len, pdecrypted_data, pdecrypted_data_len); + *pdecrypted_data = _decrypted_data->buf; + *pdecrypted_data_len = _decrypted_data->size; -error: - free(dek); + free(_decrypted_data); - return ret; + return WAE_ERROR_NONE; } int _wae_encrypt_preloaded_web_application(const char *pkg_id, @@ -98,23 +107,31 @@ int _wae_encrypt_preloaded_web_application(const char *pkg_id, pencrypted_data_len == NULL) return WAE_ERROR_INVALID_PARAMETER; - unsigned char *dek = NULL; - size_t dek_len = -1; - int ret = get_preloaded_app_dek(pkg_id, &dek, &dek_len); + const crypto_element_s *e = NULL; + int ret = get_preloaded_app_ce(pkg_id, &e); if (ret == WAE_ERROR_NO_KEY) - ret = create_preloaded_app_dek(pkg_id, &dek, &dek_len); + ret = create_preloaded_app_ce(pkg_id, &e); if (ret != WAE_ERROR_NONE) - goto error; + return ret; - // encrypt - ret = encrypt_aes_cbc(dek, dek_len, data, data_len, pencrypted_data, pencrypted_data_len); + raw_buffer_s _data; + _data.buf = (unsigned char *)data; + _data.size = data_len; -error: - free(dek); + raw_buffer_s *_encrypted_data = NULL; + ret = encrypt_aes_cbc(e, &_data, &_encrypted_data); + + if (ret != WAE_ERROR_NONE) + return ret; - return ret; + *pencrypted_data = _encrypted_data->buf; + *pencrypted_data_len = _encrypted_data->size; + + free(_encrypted_data); + + return WAE_ERROR_NONE; } int _wae_decrypt_preloaded_web_application(const char *pkg_id, wae_app_type_e app_type, @@ -150,8 +167,7 @@ int wae_decrypt_web_application(const char *pkg_id, wae_app_type_e app_type, data, data_len, pdecrypted_data, pdecrypted_data_len); } - int wae_remove_app_dek(const char *pkg_id, wae_app_type_e app_type) { - return remove_app_dek(pkg_id, app_type); + return remove_app_ce(pkg_id, app_type); } diff --git a/tests/internals.cpp b/tests/internals.cpp index 257447b..b5c106d 100644 --- a/tests/internals.cpp +++ b/tests/internals.cpp @@ -22,6 +22,7 @@ */ #include "web_app_enc.h" +#include #include #include @@ -32,6 +33,51 @@ #include "test-common.h" +namespace { + +using rb_raii = std::unique_ptr; +using ce_raii = std::unique_ptr; +using map_raii = std::unique_ptr; + +inline rb_raii _safe(raw_buffer_s *ptr) +{ + return rb_raii(ptr, buffer_destroy); +} + +inline ce_raii _safe(crypto_element_s *ptr) +{ + return ce_raii(ptr, crypto_element_destroy); +} + +inline map_raii _safe(crypto_element_map_s *ptr) +{ + return map_raii(ptr, crypto_element_map_destroy); +} + +crypto_element_s *_create_ce(void) +{ + raw_buffer_s *dek = buffer_create(32); + raw_buffer_s *iv = buffer_create(16); + crypto_element_s *ce = crypto_element_create(dek, iv); + + if (ce == nullptr) { + buffer_destroy(dek); + buffer_destroy(iv); + } else if (_get_random(ce->dek) != WAE_ERROR_NONE) { + crypto_element_destroy(ce); + ce = nullptr; + } else if (_get_random(ce->iv) != WAE_ERROR_NONE) { + crypto_element_destroy(ce); + ce = nullptr; + } + + BOOST_REQUIRE(ce != nullptr); + + return ce; +} + +} + BOOST_AUTO_TEST_SUITE(SYSTEM) BOOST_AUTO_TEST_SUITE(INTERNALS) @@ -78,29 +124,37 @@ BOOST_AUTO_TEST_CASE(encrypt_decrypt_app_dek) "+wIDAQAB\n" "-----END PUBLIC KEY-----"; - std::vector dek(32, 0); + raw_buffer_s *dek = buffer_create(32); + + auto _raii1 = _safe(dek); + + BOOST_REQUIRE_MESSAGE(dek != nullptr && dek->size == 32, "Failed to create buffer"); + BOOST_REQUIRE_MESSAGE(_get_random(dek) == WAE_ERROR_NONE, "Failed to get random"); + + raw_buffer_s pubkey; + + pubkey.buf = (unsigned char *)public_key; + pubkey.size = strlen(public_key); + + raw_buffer_s *encrypted = nullptr; + int ret = encrypt_app_dek(&pubkey, dek, &encrypted); - unsigned char *_encrypted = nullptr; - size_t _encrypted_len = 0; - int ret = encrypt_app_dek(reinterpret_cast(public_key), - strlen(public_key), dek.data(), dek.size(), &_encrypted, - &_encrypted_len); - auto encrypted = Wae::Test::bytearr_to_vec(_encrypted, _encrypted_len); - free(_encrypted); + auto _raii2 = _safe(encrypted); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to encrypt_app_dek. ec: " << ret); - unsigned char *_decrypted = nullptr; - size_t _decrypted_len = 0; - ret = decrypt_app_dek(reinterpret_cast(private_key), - strlen(private_key), nullptr, encrypted.data(), encrypted.size(), - &_decrypted, &_decrypted_len); - auto decrypted = Wae::Test::bytearr_to_vec(_decrypted, _decrypted_len); - free(_decrypted); + raw_buffer_s prikey; + prikey.buf = (unsigned char *)private_key; + prikey.size = strlen(private_key); + + raw_buffer_s *decrypted = nullptr; + ret = decrypt_app_dek(&prikey, nullptr, encrypted, &decrypted); + + auto _raii3 = _safe(decrypted); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to decrypt_app_dek. ec: " << ret); - BOOST_REQUIRE_MESSAGE(dek == decrypted, + BOOST_REQUIRE_MESSAGE(Wae::Test::bytes_to_hex(dek) == Wae::Test::bytes_to_hex(decrypted), "encrypted/decrypted dek isn't valid. " "dek(" << Wae::Test::bytes_to_hex(dek) << ") " "decrypted(" << Wae::Test::bytes_to_hex(decrypted) << ")"); @@ -108,37 +162,32 @@ BOOST_AUTO_TEST_CASE(encrypt_decrypt_app_dek) BOOST_AUTO_TEST_CASE(encrypt_decrypt_aes_cbc) { - std::vector plaintext = { - 'a', 'b', 'c', 'a', 'b', 'c', 'x', 'y', - 'o', 'q', '2', 'e', 'v', '0', '1', 'x' - }; + raw_buffer_s *data = buffer_create(16); + + auto _raii1 = _safe(data); - size_t dek_len = 32; - std::vector dek(dek_len, 0); + BOOST_REQUIRE_MESSAGE(data != nullptr && data->size == 16, "Failed to create buffer"); - int ret = _get_random(dek.size(), dek.data()); - BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to get random"); + crypto_element_s *ce = _create_ce(); - unsigned char *_encrypted = nullptr; - size_t _encrypted_len = 0; - ret = encrypt_aes_cbc(dek.data(), dek.size(), plaintext.data(), plaintext.size(), - &_encrypted, &_encrypted_len); - auto encrypted = Wae::Test::bytearr_to_vec(_encrypted, _encrypted_len); - free(_encrypted); + auto _raii2 = _safe(ce); + + raw_buffer_s *encrypted = nullptr; + int ret = encrypt_aes_cbc(ce, data, &encrypted); + + auto _raii3 = _safe(encrypted); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to encrypt_aes_cbc. ec: " << ret); - unsigned char *_decrypted = nullptr; - size_t _decrypted_len = 0; - ret = decrypt_aes_cbc(dek.data(), dek.size(), encrypted.data(), encrypted.size(), - &_decrypted, &_decrypted_len); - auto decrypted = Wae::Test::bytearr_to_vec(_decrypted, _decrypted_len); - free(_decrypted); + raw_buffer_s *decrypted = nullptr; + ret = decrypt_aes_cbc(ce, encrypted, &decrypted); + + auto _raii4 = _safe(decrypted); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to decrypt_aes_cbc. ec: " << ret); - BOOST_REQUIRE_MESSAGE(plaintext == decrypted, + BOOST_REQUIRE_MESSAGE(Wae::Test::bytes_to_hex(data) == Wae::Test::bytes_to_hex(decrypted), "decrypted plaintext isn't valid. " - "plaintext(" << Wae::Test::bytes_to_hex(plaintext) << ") " + "plaintext(" << Wae::Test::bytes_to_hex(data) << ") " "decrypted(" << Wae::Test::bytes_to_hex(decrypted) << ")"); } @@ -149,90 +198,79 @@ BOOST_AUTO_TEST_CASE(cache) const char *pkg3 = "pkg3"; const char *pkgDummy = "dummy"; - std::vector dek1(32, 1); - std::vector dek2(32, 2); - std::vector dek3(32, 3); + auto ce1 = _create_ce(); + auto ce2 = _create_ce(); + auto ce3 = _create_ce(); - _initialize_cache(); + crypto_element_map_s *map = nullptr; - _add_app_dek_to_cache(pkg1, dek1.data()); - _add_app_dek_to_cache(pkg2, dek2.data()); - _add_app_dek_to_cache(pkg3, dek3.data()); + int tmp = crypto_element_map_add(&map, pkg1, ce1); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to add ce to map. ret: " << tmp); - size_t dek_len = 32; - const unsigned char *_cached = _get_app_dek_from_cache(pkg1); - auto cached = Wae::Test::bytearr_to_vec(_cached, dek_len); + tmp = crypto_element_map_add(&map, pkg2, ce2); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to add ce to map. ret: " << tmp); - BOOST_REQUIRE_MESSAGE(cached == dek1, - "cached dek isn't valid! " - "dek(" << Wae::Test::bytes_to_hex(dek1) << ") " - "cached(" << Wae::Test::bytes_to_hex(cached) << ")"); + tmp = crypto_element_map_add(&map, pkg3, ce3); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to add ce to map. ret: " << tmp); - _cached = _get_app_dek_from_cache(pkg2); - cached = Wae::Test::bytearr_to_vec(_cached, dek_len); + BOOST_REQUIRE_MESSAGE(crypto_element_map_get(map, pkg1) == ce1, + "cached ce has different address with actual."); + BOOST_REQUIRE_MESSAGE(crypto_element_map_get(map, pkg2) == ce2, + "cached ce has different address with actual."); + BOOST_REQUIRE_MESSAGE(crypto_element_map_get(map, pkg3) == ce3, + "cached ce has different address with actual."); + BOOST_REQUIRE_MESSAGE(crypto_element_map_get(map, pkgDummy) == nullptr, + "something returned with pkg dummy from map which should be null."); - BOOST_REQUIRE_MESSAGE(cached == dek2, - "cached dek isn't valid! " - "dek(" << Wae::Test::bytes_to_hex(dek2) << ") " - "cached(" << Wae::Test::bytes_to_hex(cached) << ")"); + crypto_element_map_remove(&map, pkg3); - _cached = _get_app_dek_from_cache(pkg3); - cached = Wae::Test::bytearr_to_vec(_cached, dek_len); + BOOST_REQUIRE_MESSAGE(crypto_element_map_get(map, pkg3) == nullptr, + "removed pkg(" << pkg3 << ") is returned from map which should be null."); - BOOST_REQUIRE_MESSAGE(cached == dek3, - "cached dek isn't valid! " - "dek(" << Wae::Test::bytes_to_hex(dek3) << ") " - "cached(" << Wae::Test::bytes_to_hex(cached) << ")"); + auto ce4 = _create_ce(); + tmp = crypto_element_map_add(&map, pkg1, ce4); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to update ce to map. ret: " << tmp); - _cached = _get_app_dek_from_cache(pkgDummy); - if (_cached) { - cached = Wae::Test::bytearr_to_vec(_cached, dek_len); - BOOST_REQUIRE_MESSAGE(false, - "wrong cached val is extracted by dummy pkg id. " - "val(" << Wae::Test::bytes_to_hex(cached) << ")"); - } + BOOST_REQUIRE_MESSAGE(crypto_element_map_get(map, pkg1) == ce4, + "cached ce has different address with actual."); - _remove_app_dek_from_cache(pkg3); + crypto_element_map_destroy(map); +} - _cached = _get_app_dek_from_cache(pkg3); - if (_cached) { - cached = Wae::Test::bytearr_to_vec(_cached, dek_len); - BOOST_REQUIRE_MESSAGE(false, - "app dek removed from cache but it's remained! " - "val(" << Wae::Test::bytes_to_hex(cached) << ")"); - } +BOOST_AUTO_TEST_CASE(cache_max) +{ + crypto_element_map_s *map = nullptr; - _initialize_cache(); + for (size_t i = 0; i < MAX_MAP_ELEMENT_SIZE + 1; ++i) { + BOOST_REQUIRE(crypto_element_map_add(&map, std::to_string(i).c_str(), _create_ce()) == WAE_ERROR_NONE); + } - _add_app_dek_to_cache(pkg1, dek1.data()); + BOOST_REQUIRE(crypto_element_map_get(map, "0") == nullptr); - _cached = nullptr; - _cached = _get_app_dek_from_cache(pkg2); - if (_cached) { - cached = Wae::Test::bytearr_to_vec(_cached, dek_len); - BOOST_REQUIRE_MESSAGE(false, - "cache is initialized but something is remained! " - "val(" << Wae::Test::bytes_to_hex(cached) << ")"); - } + crypto_element_map_destroy(map); } BOOST_AUTO_TEST_CASE(read_write_encrypted_app_dek) { const char *pkg_id = "write_test_pkg"; - std::vector dek(256, 0); + raw_buffer_s *dek = buffer_create(256); - int ret = _write_encrypted_app_dek_to_file(pkg_id, dek.data(), dek.size()); + auto raii1 = _safe(dek); + + BOOST_REQUIRE(dek != nullptr); + BOOST_REQUIRE(_get_random(dek) == WAE_ERROR_NONE); + + int ret = _write_encrypted_app_dek_to_file(pkg_id, dek); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to write_encrypted_app_dek_to_file. ec: " << ret); - unsigned char *_readed = nullptr; - size_t _readed_len = 0; - ret = _read_encrypted_app_dek_from_file(pkg_id, &_readed, &_readed_len); - auto readed = Wae::Test::bytearr_to_vec(_readed, _readed_len); - free(_readed); + raw_buffer_s *readed = nullptr; + ret = _read_encrypted_app_dek_from_file(pkg_id, &readed); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to read_encrypted_app_dek_from_file. ec: " << ret); - BOOST_REQUIRE_MESSAGE(dek == readed, + auto raii2 = _safe(readed); + + BOOST_REQUIRE_MESSAGE(Wae::Test::bytes_to_hex(dek) == Wae::Test::bytes_to_hex(readed), "dek isn't match after write/read file. " "dek(" << Wae::Test::bytes_to_hex(dek) << ") " "readed(" << Wae::Test::bytes_to_hex(readed) << ")"); @@ -242,35 +280,23 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1) { const char *pkg_id = "TEST_PKG_ID_FOR_CREATE"; - unsigned char *_readed = nullptr; - size_t _readed_len = 0; - int ret = get_preloaded_app_dek(pkg_id, &_readed, &_readed_len); - auto readed = Wae::Test::bytearr_to_vec(_readed, _readed_len); - free(_readed); + const crypto_element_s *readed = nullptr; + int ret = get_preloaded_app_ce(pkg_id, &readed); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NO_KEY, - "preloaded app dek to create is already exist. ec: " << ret); + "preloaded app ce to create is already exist. ec: " << ret); - unsigned char *_dek = nullptr; - size_t _dek_len = 0; - ret = create_preloaded_app_dek(pkg_id, &_dek, &_dek_len); - auto dek = Wae::Test::bytearr_to_vec(_dek, _dek_len); + const crypto_element_s *ce = nullptr; + ret = create_preloaded_app_ce(pkg_id, &ce); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, - "Failed to create_preloaded_app_dek. ec: " << ret); - - _readed = nullptr; - ret = get_preloaded_app_dek(pkg_id, &_readed, &_readed_len); - readed = Wae::Test::bytearr_to_vec(_readed, _readed_len); - free(_readed); + "Failed to create_preloaded_app_ce. ec: " << ret); + ret = get_preloaded_app_ce(pkg_id, &readed); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, - "Failed to get_preloaded_app_dek. ec: " << ret); + "Failed to get_preloaded_app_ce. ec: " << ret); - BOOST_REQUIRE_MESSAGE(dek == readed, - "created/loaded dek is not matched! " - "created(" << Wae::Test::bytes_to_hex(dek) << ") " - "loaded(" << Wae::Test::bytes_to_hex(readed) << ")"); + BOOST_REQUIRE_MESSAGE(readed == ce, "cached ce address and actual is different!"); } BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) @@ -284,67 +310,42 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) _get_preloaded_app_dek_file_path(pkg_id2, sizeof(path2), path2); // remove old test data - remove_app_dek(pkg_id1, WAE_PRELOADED_APP); - remove_app_dek(pkg_id2, WAE_PRELOADED_APP); + remove_app_ce(pkg_id1, WAE_PRELOADED_APP); + remove_app_ce(pkg_id2, WAE_PRELOADED_APP); unlink(path1); unlink(path2); - // create 2 deks for preloaded app - unsigned char *_dek1 = nullptr; - size_t _dek_len1 = 0; - int ret = create_preloaded_app_dek(pkg_id1, &_dek1, &_dek_len1); - auto dek1 = Wae::Test::bytearr_to_vec(_dek1, _dek_len1); - free(_dek1); - + // create 2 ces for preloaded app + const crypto_element_s *ce1 = nullptr; + int ret = create_preloaded_app_ce(pkg_id1, &ce1); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, - "Failed to create_preloaded_app_dek. ec: " << ret); - - unsigned char *_dek2 = nullptr; - size_t _dek_len2 = 0; - ret = create_preloaded_app_dek(pkg_id2, &_dek2, &_dek_len2); - auto dek2 = Wae::Test::bytearr_to_vec(_dek2, _dek_len2); - free(_dek2); + "Failed to create_preloaded_app_ce. ec: " << ret); + const crypto_element_s *ce2 = nullptr; + ret = create_preloaded_app_ce(pkg_id2, &ce2); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, - "Failed to create_preloaded_app_dek. ec: " << ret); + "Failed to create_preloaded_app_ce. ec: " << ret); ret = load_preloaded_app_deks(true); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to load_preloaded_app_deks. ec: " << ret); - unsigned char *_readed1 = nullptr; - size_t _readed_len1 = 0; - ret = get_app_dek(pkg_id1, WAE_PRELOADED_APP, &_readed1, &_readed_len1); - auto readed1 = Wae::Test::bytearr_to_vec(_readed1, _readed_len1); - free(_readed1); - + const crypto_element_s *readed1 = nullptr; + ret = get_app_ce(pkg_id1, WAE_PRELOADED_APP, false, &readed1); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to get_app_dek. ec: " << ret); - unsigned char *_readed2 = nullptr; - size_t _readed_len2 = 0; - ret = get_app_dek(pkg_id2, WAE_PRELOADED_APP, &_readed2, &_readed_len2); - auto readed2 = Wae::Test::bytearr_to_vec(_readed2, _readed_len2); - free(_readed2); - + const crypto_element_s *readed2 = nullptr; + ret = get_app_ce(pkg_id2, WAE_PRELOADED_APP, false, &readed2); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to get_app_dek. ec: " << ret); - BOOST_REQUIRE_MESSAGE(dek1 == readed1, - "readed dek and original isn't matched! " - "original(" << Wae::Test::bytes_to_hex(dek1) << ") " - "readed(" << Wae::Test::bytes_to_hex(readed1) << ")"); + BOOST_REQUIRE_MESSAGE(readed1 == ce1, "cached ce and actual address is different!"); + BOOST_REQUIRE_MESSAGE(readed2 == ce2, "cached ce and actual address is different!"); - BOOST_REQUIRE_MESSAGE(dek2 == readed2, - "readed dek and original isn't matched! " - "original(" << Wae::Test::bytes_to_hex(dek2) << ") " - "readed(" << Wae::Test::bytes_to_hex(readed2) << ")"); + ret = remove_app_ce(pkg_id1, WAE_PRELOADED_APP); + BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed remove app ce. ec: " << ret); - ret = remove_app_dek(pkg_id1, WAE_PRELOADED_APP); - BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, - "Failed remove app dek after used. ec: " << ret); - - ret = remove_app_dek(pkg_id2, WAE_PRELOADED_APP); - BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, - "Failed remove app dek after used. ec: " << ret); + ret = remove_app_ce(pkg_id2, WAE_PRELOADED_APP); + BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed remove app ce. ec: " << ret); } BOOST_AUTO_TEST_SUITE_END() // INTERNALS diff --git a/tests/non-normals.cpp b/tests/non-normals.cpp index 8667bfc..81c0173 100644 --- a/tests/non-normals.cpp +++ b/tests/non-normals.cpp @@ -32,12 +32,12 @@ BOOST_AUTO_TEST_SUITE(GLOBAL_APP) BOOST_AUTO_TEST_CASE(add_get_remove_dek) { - Wae::Test::add_get_remove_dek(WAE_DOWNLOADED_GLOBAL_APP); + Wae::Test::add_get_remove_ce(WAE_DOWNLOADED_GLOBAL_APP); } BOOST_AUTO_TEST_CASE(create_app_dek) { - Wae::Test::create_app_dek(WAE_DOWNLOADED_GLOBAL_APP); + Wae::Test::create_app_ce(WAE_DOWNLOADED_GLOBAL_APP); } BOOST_AUTO_TEST_CASE(encrypt_decrypt) @@ -52,12 +52,12 @@ BOOST_AUTO_TEST_SUITE(PRELOADED_APP) BOOST_AUTO_TEST_CASE(add_get_remove_dek) { - Wae::Test::add_get_remove_dek(WAE_PRELOADED_APP); + Wae::Test::add_get_remove_ce(WAE_PRELOADED_APP); } BOOST_AUTO_TEST_CASE(create_app_dek) { - Wae::Test::create_app_dek(WAE_PRELOADED_APP); + Wae::Test::create_app_ce(WAE_PRELOADED_APP); } BOOST_AUTO_TEST_CASE(encrypt_decrypt) diff --git a/tests/normals.cpp b/tests/normals.cpp index 2ce272e..5d67910 100644 --- a/tests/normals.cpp +++ b/tests/normals.cpp @@ -32,12 +32,12 @@ BOOST_AUTO_TEST_SUITE(DOWNLOADED_APP); BOOST_AUTO_TEST_CASE(add_get_remove_dek) { - Wae::Test::add_get_remove_dek(WAE_DOWNLOADED_NORMAL_APP); + Wae::Test::add_get_remove_ce(WAE_DOWNLOADED_NORMAL_APP); } BOOST_AUTO_TEST_CASE(create_app_dek) { - Wae::Test::create_app_dek(WAE_DOWNLOADED_NORMAL_APP); + Wae::Test::create_app_ce(WAE_DOWNLOADED_NORMAL_APP); } BOOST_AUTO_TEST_CASE(encrypt_decrypt_normal_app) diff --git a/tests/test-common.cpp b/tests/test-common.cpp index 3e9e331..3157ca6 100644 --- a/tests/test-common.cpp +++ b/tests/test-common.cpp @@ -38,15 +38,42 @@ std::string bytes_to_hex(const std::vector &bytes) return ss.str(); } -std::vector bytearr_to_vec(const unsigned char *bytes, size_t len) +std::string bytes_to_hex(const raw_buffer_s *rb) { - if (bytes == nullptr || len == 0) + if (!is_buffer_valid(rb)) + return std::string(); + + return bytes_to_hex(rb->buf, rb->size); +} + +std::string bytes_to_hex(const unsigned char *ptr, size_t len) +{ + std::stringstream ss; + ss << std::hex; + + for (size_t i = 0; i < len; ++i) + ss << std::setw(2) << std::setfill('0') << static_cast(ptr[i]); + + return ss.str(); +} + +std::vector bytearr_to_vec(const raw_buffer_s *rb) +{ + if (!is_buffer_valid(rb)) + return std::vector(); + + return bytearr_to_vec(rb->buf, rb->size); +} + +std::vector bytearr_to_vec(const unsigned char *ptr, size_t len) +{ + if (ptr == nullptr || len == 0) return std::vector(); - std::vector vec; + std::vector vec(len); for (size_t i = 0; i < len; ++i) - vec.push_back(bytes[i]); + vec[i] = ptr[i]; return vec; } diff --git a/tests/test-common.h b/tests/test-common.h index 2c4c54e..57bf83b 100644 --- a/tests/test-common.h +++ b/tests/test-common.h @@ -28,6 +28,8 @@ #include "colour_log_formatter.h" +#include "types.h" + /* fixtures should be declared on outside of namespace */ struct TestConfig { TestConfig() @@ -45,7 +47,10 @@ namespace Wae { namespace Test { std::string bytes_to_hex(const std::vector &bytes); -std::vector bytearr_to_vec(const unsigned char *bytes, size_t len); +std::string bytes_to_hex(const unsigned char *ptr, size_t len); +std::string bytes_to_hex(const raw_buffer_s *rb); +std::vector bytearr_to_vec(const unsigned char *ptr, size_t len); +std::vector bytearr_to_vec(const raw_buffer_s *); } // namespace Test } // namespace Wae diff --git a/tests/test-helper.cpp b/tests/test-helper.cpp index 144299a..f303b75 100644 --- a/tests/test-helper.cpp +++ b/tests/test-helper.cpp @@ -25,78 +25,64 @@ #include "key_handler.h" #include "crypto_service.h" +#include "types.h" +#include "key_manager.h" #include "test-common.h" namespace Wae { namespace Test { -void add_get_remove_dek(wae_app_type_e app_type) +void add_get_remove_ce(wae_app_type_e app_type) { const char *pkg_id = "TEST_PKG_ID"; - std::vector dek(32, 0); - - BOOST_REQUIRE(_get_random(dek.size(), dek.data()) == WAE_ERROR_NONE); - - remove_app_dek(pkg_id, app_type); - - int tmp = _add_dek_to_key_manager(pkg_id, app_type, dek.data(), dek.size()); - BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, - "Failed to _add_dek_to_key_manager. ec: " << tmp); - - unsigned char *_stored_dek = nullptr; - size_t _stored_dek_len = 0; - tmp = get_app_dek(pkg_id, app_type, &_stored_dek, &_stored_dek_len); - BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, - "Failed to get_app_dek. ec: " << tmp); - - auto stored_dek = Wae::Test::bytearr_to_vec(_stored_dek, _stored_dek_len); - free(_stored_dek); - - BOOST_REQUIRE_MESSAGE(stored_dek == dek, "stored dek and dek isn't matched!"); - - tmp = remove_app_dek(pkg_id, app_type); - BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to remove_app_dek. ec: " << tmp); - - _stored_dek = nullptr; - tmp = get_app_dek(pkg_id, app_type, &_stored_dek, &_stored_dek_len); - if (_stored_dek) - free(_stored_dek); - - BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NO_KEY, - "dek removed but it's remained still. ec: " << tmp); + const crypto_element_s *ce = nullptr; + int tmp = create_app_ce(pkg_id, app_type, &ce); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to create_app_ce. ec: " << tmp); + + const crypto_element_s *stored_ce = nullptr; + tmp = get_app_ce(pkg_id, app_type, true, &stored_ce); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to get_app_ce. ec: " << tmp); + + BOOST_REQUIRE_MESSAGE(ce == stored_ce, + "ce(" << ce << ") and cached ce(" << stored_ce << ") pointer addr is different!"); + + tmp = remove_app_ce(pkg_id, app_type); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to remove_app_ce. ec: " << tmp); + + if (app_type == WAE_DOWNLOADED_GLOBAL_APP) { + tmp = get_app_ce(pkg_id, app_type, true, &stored_ce); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE && stored_ce->is_migrated_app, + "when getting app ce which is there isn't, it should be migrated case! " + "ret("<< tmp << ") and is_migrated_app(" << stored_ce->is_migrated_app << ")"); + } else { + tmp = get_app_ce(pkg_id, app_type, false, &stored_ce); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NO_KEY, + "removed app ce is still remaining. ret(" << tmp << ")"); + } } -void create_app_dek(wae_app_type_e app_type) +void create_app_ce(wae_app_type_e app_type) { const char *pkg_id = "TEST_PKG_ID"; - remove_app_dek(pkg_id, app_type); - - unsigned char *_dek = nullptr; - size_t _dek_len = 0; + remove_app_ce(pkg_id, app_type); - int tmp = create_app_dek(pkg_id, app_type, &_dek, &_dek_len); - BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, - "Failed to create_app_dek. ec: " << tmp); + const crypto_element_s *ce = nullptr; - auto dek = Wae::Test::bytearr_to_vec(_dek, _dek_len); - free(_dek); + int tmp = create_app_ce(pkg_id, app_type, &ce); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to create_app_ce. ec: " << tmp); - unsigned char *_stored_dek = nullptr; - size_t _stored_dek_len = 0; - tmp = get_app_dek(pkg_id, app_type, &_stored_dek, &_stored_dek_len); - BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to get_app_dek. ec: " << tmp); - auto stored_dek = bytearr_to_vec(_stored_dek, _stored_dek_len); - free(_stored_dek); + const crypto_element_s *stored_ce = nullptr; + tmp = get_app_ce(pkg_id, app_type, false, &stored_ce); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to get_app_ce. ec: " << tmp); - BOOST_REQUIRE_MESSAGE(stored_dek == dek, - "stored dek and dek isn't matched! " - "stored_dek(" << Wae::Test::bytes_to_hex(stored_dek) << ") " - "dek(" << Wae::Test::bytes_to_hex(dek) << ")"); + BOOST_REQUIRE_MESSAGE(ce == stored_ce, + "ce(" << ce << ") and cached ce(" << stored_ce << ") pointer addr is different!"); - remove_app_dek(pkg_id, app_type); + tmp = remove_app_ce(pkg_id, app_type); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to remove_app_ce. ec: " << tmp); } void encrypt_decrypt_web_app(wae_app_type_e app_type) @@ -125,7 +111,7 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) wae_remove_app_dek(pkg_id, app_type); if (app_type == WAE_PRELOADED_APP) - _clear_app_deks_loaded(); + clear_app_deks_loaded_from_key_manager(); std::vector plaintext = { 'a', 'b', 'c', 'a', 'b', 'c', 'x', 'y', @@ -150,7 +136,7 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) auto encrypted = bytearr_to_vec(_encrypted, _enc_len); free(_encrypted); - _remove_app_dek_from_cache(pkg_id); + _remove_app_ce_from_cache(pkg_id); if (app_type == WAE_PRELOADED_APP) load_preloaded_app_deks(true); @@ -166,8 +152,8 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) BOOST_REQUIRE_MESSAGE(plaintext == decrypted, "plaintext and decrypted isn't matched! " - "plaintext(" << Wae::Test::bytes_to_hex(plaintext) << ") " - "decrypted(" << Wae::Test::bytes_to_hex(decrypted) << ")"); + "plaintext(" << bytes_to_hex(plaintext) << ") " + "decrypted(" << bytes_to_hex(decrypted) << ")"); tmp = wae_remove_app_dek(pkg_id, app_type); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, diff --git a/tests/test-helper.h b/tests/test-helper.h index 132ceae..c0c77f6 100644 --- a/tests/test-helper.h +++ b/tests/test-helper.h @@ -25,8 +25,8 @@ namespace Wae { namespace Test { -void add_get_remove_dek(wae_app_type_e app_type); -void create_app_dek(wae_app_type_e app_type); +void add_get_remove_ce(wae_app_type_e app_type); +void create_app_ce(wae_app_type_e app_type); void encrypt_decrypt_web_app(wae_app_type_e app_type); } // namespace Test -- 2.7.4 From a025df2ca4ae9a4e13b5b803674da4dd1bd133e9 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Wed, 3 Aug 2016 13:17:17 +0900 Subject: [PATCH 05/16] Set uid/gid to wae initializer service Change-Id: I15ee0cb42c05cf19d875b4b9acf96e78939a240f Signed-off-by: Kyungwook Tak --- systemd/webappenc-initializer.service.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/systemd/webappenc-initializer.service.in b/systemd/webappenc-initializer.service.in index 976a877..768552e 100644 --- a/systemd/webappenc-initializer.service.in +++ b/systemd/webappenc-initializer.service.in @@ -5,6 +5,8 @@ Requires=central-key-manager.service After=central-key-manager.service [Service] +User=security_fw +Group=security_fw Type=oneshot ExecStart=/usr/bin/wae_initializer SmackProcessLabel=System -- 2.7.4 From cc76acebe224f4b8a273752b2400190ab0aab679 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Wed, 27 Jul 2016 16:54:50 +0900 Subject: [PATCH 06/16] [API changed] Add uid parameter Installer will be run as system (from user) so we cannot retrieve user id from client credential(by key-manager). Change-Id: I1e091bfc0b88fce418cd209a7a1adab021b6c0d2 Signed-off-by: Kyungwook Tak --- CMakeLists.txt | 1 - include/web_app_enc.h | 109 +++++++++++++++++---- packaging/libwebappenc-test.manifest.in | 2 +- packaging/libwebappenc.spec | 4 +- srcs/key_handler.c | 165 ++++++++++++++++++++++---------- srcs/key_handler.h | 14 +-- srcs/key_manager.c | 50 ++++------ srcs/key_manager.h | 8 +- srcs/types.h | 9 ++ srcs/web_app_enc.c | 70 ++++++++++---- tests/internals.cpp | 12 +-- tests/non-normals.cpp | 3 +- tests/normals.cpp | 3 +- tests/test-helper.cpp | 77 +++++++++++---- tests/test-helper.h | 2 +- 15 files changed, 362 insertions(+), 167 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 84dd0d5..436eb74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,6 @@ ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"") ADD_DEFINITIONS("-DSMACK_ENABLED") ADD_DEFINITIONS("-DSQLCIPHER_HAS_CODEC") ADD_DEFINITIONS("-DBINDIR=\"${BINDIR}\"") -ADD_DEFINITIONS("-DINSTALLER_LABEL=\"${INSTALLER_LABEL}\"") # IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") ADD_DEFINITIONS("-DTIZEN_DEBUG_ENABLE") diff --git a/include/web_app_enc.h b/include/web_app_enc.h index c876792..47cbe78 100644 --- a/include/web_app_enc.h +++ b/include/web_app_enc.h @@ -14,7 +14,7 @@ * limitations under the License * * @file web_app_enc.h - * @version 1.0 + * @version 2.0 * @brief APIs of WEB_APP_ENC module. */ #ifndef __WEB_APP_ENC__ @@ -25,6 +25,8 @@ extern "C" { #endif #include +#include +#include /** * @addtogroup CAPI_WEB_APP_ENC_MODULE @@ -49,24 +51,40 @@ typedef enum { } wae_error_e; /** - * @brief Application Type. + * @brief Encrypts web application data + * * @since_tizen 3.0 + * @param[in] uid User id of the application being encrypted + * @param[in] pkg_id The package id of an application + * @param[in] data The data block to be encrypted + * @param[in] data_len The length of @a data + * @param[out] pencrypted_data The encrypted data block which must be freed by free() + * @param[out] pencrypted_data_len The length of data pointed by @a pencrypted_data + * + * @return #WAE_ERROR_NONE on success, otherwise a negative error value + * @retval #WAE_ERROR_INVALID_PARAMETER Invalid input parameter + * @retval #WAE_ERROR_PERMISSION_DENIED Non-authenticated application request + * @retval #WAE_ERROR_NO_KEY No internal key + * @retval #WAE_ERROR_KEY_MANAGER key-manager internal error + * @retval #WAE_ERROR_CRYPTO failed in crypto operation + * @retval #WAE_ERROR_UNKNOWN Failed with unknown reason + * + * @see wae_decrypt_web_application() + * @see wae_remove_app_dek() */ -typedef enum { - WAE_DOWNLOADED_NORMAL_APP = 0, /**< Downloaded Normal Application*/ - WAE_DOWNLOADED_GLOBAL_APP = 1, /**< Downloaded Global Application*/ - WAE_PRELOADED_APP = 2 /**< Preloaded Application*/ -} wae_app_type_e; +int wae_encrypt_web_application(uid_t uid, const char *pkg_id, + const unsigned char *data, size_t data_len, + unsigned char **pencrypted_data, size_t *pencrypted_data_len); /** - * @brief Encrypts web application data with internal key(APP DEK: Application Data Encryption Key). + * @brief Encrypts global web application data * * @since_tizen 3.0 * @param[in] pkg_id The package id of an application - * @param[in] app_type The application type + * @param[in] is_preloaded Whether the package is preloaded or not * @param[in] data The data block to be encrypted * @param[in] data_len The length of @a data - * @param[out] pencrypted_data The data block contaning encrypted data block which must be freed by free() + * @param[out] pencrypted_data The encrypted data block which must be freed by free() * @param[out] pencrypted_data_len The length of data pointed by @a pencrypted_data * * @return #WAE_ERROR_NONE on success, otherwise a negative error value @@ -77,21 +95,22 @@ typedef enum { * @retval #WAE_ERROR_CRYPTO failed in crypto operation * @retval #WAE_ERROR_UNKNOWN Failed with unknown reason * - * @see wae_decrypt_web_application() + * @see wae_decrypt_global_web_application() + * @see wae_remove_global_app_dek() */ -int wae_encrypt_web_application(const char *pkg_id, wae_app_type_e app_type, - const unsigned char *data, size_t data_len, - unsigned char **pencrypted_data, size_t *pencrypted_data_len); +int wae_encrypt_global_web_application(const char *pkg_id, bool is_preloaded, + const unsigned char *data, size_t data_len, + unsigned char **pencrypted_data, size_t *pencrypted_data_len); /** - * @brief Encrypts web application data with internal key. + * @brief Decrypts web application data. * * @since_tizen 3.0 + * @param[in] uid User id of the application being decrypted * @param[in] pkg_id The package id of an application - * @param[in] app_type The application type * @param[in] data The data block to be decrypted * @param[in] data_len The length of @a data - * @param[out] pdecrypted_data Data block contaning decrypted data block which must be freed by free() + * @param[out] pdecrypted_data The decrypted data block which must be freed by free() * @param[out] pdecrypted_data_len The length of data pointed by @a pdecrypted_data * * @return #WAE_ERROR_NONE on success, otherwise a negative error value @@ -103,17 +122,44 @@ int wae_encrypt_web_application(const char *pkg_id, wae_app_type_e app_type, * @retval #WAE_ERROR_UNKNOWN Failed with unknown reason * * @see wae_encrypt_web_application() + * @see wae_remove_app_dek() */ -int wae_decrypt_web_application(const char *pkg_id, wae_app_type_e app_type, +int wae_decrypt_web_application(uid_t uid, const char *pkg_id, const unsigned char *data, size_t data_len, unsigned char **pdecrypted_data, size_t *pdecrypted_data_len); /** - * @brief Remove a APP DEK(Application Data Encryption Key) used for encrytpion and decryption of a web application. + * @brief Decrypts global web application data. + * + * @since_tizen 3.0 + * @param[in] pkg_id The package id of an application + * @param[in] is_preloaded Whether the package is preloaded or not + * @param[in] data The data block to be decrypted + * @param[in] data_len The length of @a data + * @param[out] pdecrypted_data The decrypted data block which must be freed by free() + * @param[out] pdecrypted_data_len The length of data pointed by @a pdecrypted_data + * + * @return #WAE_ERROR_NONE on success, otherwise a negative error value + * @retval #WAE_ERROR_INVALID_PARAMETER Invalid input parameter + * @retval #WAE_ERROR_PERMISSION_DENIED Non-authenticated application request + * @retval #WAE_ERROR_NO_KEY No internal key + * @retval #WAE_ERROR_KEY_MANAGER key-manager internal error + * @retval #WAE_ERROR_CRYPTO failed in crypto operation + * @retval #WAE_ERROR_UNKNOWN Failed with unknown reason + * + * @see wae_encrypt_global_web_application() + * @see wae_remove_global_app_dek() + */ +int wae_decrypt_global_web_application(const char *pkg_id, bool is_preloaded, + const unsigned char *data, size_t data_len, + unsigned char **pdecrypted_data, size_t *pdecrypted_data_len); + +/** + * @brief Remove key used for encryption the web application. * * @since_tizen 3.0 + * @param[in] uid User id of the application being uninstalled * @param[in] pkg_id The package id of an application - * @param[in] app_type The application type * * @return #WAE_ERROR_NONE on success, otherwise a negative error value * @retval #WAE_ERROR_INVALID_PARAMETER Invalid input parameter @@ -122,8 +168,29 @@ int wae_decrypt_web_application(const char *pkg_id, wae_app_type_e app_type, * @retval #WAE_ERROR_KEY_MANAGER key-manager internal error * @retval #WAE_ERROR_UNKNOWN Failed with unknown reason * + * @see wae_encrypt_web_application() + * @see wae_decrypt_web_application() + */ +int wae_remove_app_dek(uid_t uid, const char *pkg_id); + +/** + * @brief Remove key used for encryption the global web application. + * + * @since_tizen 3.0 + * @param[in] pkg_id The package id of an application + * @param[in] is_preloaded Whether the package is preloaded or not + * + * @return #WAE_ERROR_NONE on success, otherwise a negative error value + * @retval #WAE_ERROR_INVALID_PARAMETER Invalid input parameter + * @retval #WAE_ERROR_PERMISSION_DENIED Non-authenticated application request + * @retval #WAE_ERROR_NO_KEY No internal key + * @retval #WAE_ERROR_KEY_MANAGER key-manager internal error + * @retval #WAE_ERROR_UNKNOWN Failed with unknown reason + * + * @see wae_encrypt_global_web_application() + * @see wae_decrypt_global_web_application() */ -int wae_remove_app_dek(const char *pkg_id, wae_app_type_e app_type); +int wae_remove_global_app_dek(const char *pkg_id, bool is_preloaded); /** * @} diff --git a/packaging/libwebappenc-test.manifest.in b/packaging/libwebappenc-test.manifest.in index 13d4d92..0e22627 100644 --- a/packaging/libwebappenc-test.manifest.in +++ b/packaging/libwebappenc-test.manifest.in @@ -3,6 +3,6 @@ - + diff --git a/packaging/libwebappenc.spec b/packaging/libwebappenc.spec index ed5434a..7d796f9 100644 --- a/packaging/libwebappenc.spec +++ b/packaging/libwebappenc.spec @@ -37,7 +37,6 @@ Requires: %{name} = %{version}-%{release} %description test Web application encryption and decryption service (test) -%define installer_label "User" %define bin_dir %TZ_SYS_BIN %define rw_share_dir %TZ_SYS_SHARE @@ -53,8 +52,7 @@ Web application encryption and decryption service (test) -DSYSTEMD_UNIT_DIR=%{_unitdir} \ -DCMAKE_BUILD_TYPE=%{build_type} \ -DRW_SHARE_DIR=%rw_share_dir \ - -DBINDIR=%bin_dir \ - -DINSTALLER_LABEL=%installer_label + -DBINDIR=%bin_dir make %{?jobs:-j%jobs} diff --git a/srcs/key_handler.c b/srcs/key_handler.c index af7280b..cf3de1d 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -29,6 +29,7 @@ #include +#include "web_app_enc.h" #include "wae_log.h" #include "crypto_service.h" #include "key_manager.h" @@ -56,19 +57,28 @@ static void deinit_lib(void) crypto_element_map_destroy(_map); } -static const crypto_element_s *_get_app_ce_from_cache(const char *pkg_id) +char *_create_map_key(uid_t uid, const char *pkg_id) { - return crypto_element_map_get(_map, pkg_id); + char *key = NULL; + + int ret = asprintf(&key, "%u-%s", uid, pkg_id); + + return (ret == -1) ? NULL : key; } -static int _add_app_ce_to_cache(const char *pkg_id, crypto_element_s *ce) +static const crypto_element_s *_get_app_ce_from_cache(const char *key) { - return crypto_element_map_add(&_map, pkg_id, ce); + return crypto_element_map_get(_map, key); } -void _remove_app_ce_from_cache(const char *pkg_id) +static int _add_app_ce_to_cache(const char *key, crypto_element_s *ce) { - crypto_element_map_remove(&_map, pkg_id); + return crypto_element_map_add(&_map, key, ce); +} + +void _remove_app_ce_from_cache(const char *key) +{ + crypto_element_map_remove(&_map, key); } int _get_random(raw_buffer_s *rb) @@ -110,13 +120,13 @@ static const char *_get_dek_store_path() static int _write_to_file(const char *path, const raw_buffer_s *data) { - if (path == NULL || data == NULL || data->buf == NULL || data->size == 0) + if (path == NULL || !is_buffer_valid(data)) return WAE_ERROR_INVALID_PARAMETER; FILE *f = fopen(path, "w"); if (f == NULL) { - WAE_SLOGE("WAE: Fail to open a file. file=%s", path); + WAE_SLOGE("Failed to open a file(%s)", path); return WAE_ERROR_FILE; } @@ -125,7 +135,7 @@ static int _write_to_file(const char *path, const raw_buffer_s *data) fclose(f); if (write_len != (int)data->size) { - WAE_SLOGE("WAE: Fail to write a file. file=%s", path); + WAE_SLOGE("Failed to write a file(%s)", path); return WAE_ERROR_FILE; } @@ -226,110 +236,145 @@ int _write_encrypted_app_dek_to_file(const char *pkg_id, const raw_buffer_s *enc return _write_to_file(path, encrypted); } -int get_app_ce(const char *pkg_id, wae_app_type_e app_type, bool create_for_migrated_app, - const crypto_element_s **pce) +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) { if (pkg_id == NULL || pce == NULL) return WAE_ERROR_INVALID_PARAMETER; - const crypto_element_s *cached_ce = _get_app_ce_from_cache(pkg_id); + if (uid == 0 && app_type == WAE_DOWNLOADED_NORMAL_APP) + return WAE_ERROR_INVALID_PARAMETER; + + const char *key = NULL; + char *_key_per_user = NULL; + + if (app_type == WAE_DOWNLOADED_NORMAL_APP) { + _key_per_user = _create_map_key(uid, pkg_id); + if (_key_per_user == NULL) + return WAE_ERROR_MEMORY; + + key = _key_per_user; + } else { + key = pkg_id; + } + + int ret = WAE_ERROR_NONE; + const crypto_element_s *cached_ce = _get_app_ce_from_cache(key); if (cached_ce != NULL) { - WAE_SLOGD("cache hit of app ce for pkg_id(%s)", pkg_id); + WAE_SLOGD("cache hit of app ce for key(%s)", key); *pce = cached_ce; - return WAE_ERROR_NONE; + goto finish; } - WAE_SLOGD("cache miss of app ce for pkg_id(%s)", pkg_id); + WAE_SLOGD("cache miss of app ce for key(%s)", key); crypto_element_s *ce = NULL; - int ret = get_from_key_manager(pkg_id, app_type, &ce); + ret = get_from_key_manager(key, app_type, &ce); if (create_for_migrated_app && (ret == WAE_ERROR_NO_KEY && app_type == WAE_DOWNLOADED_GLOBAL_APP)) { - WAE_SLOGI("No dek found for pkg_id(%s)! It should be migrated app.", pkg_id); + WAE_SLOGI("No dek found for key(%s)! It should be migrated app.", key); - if ((ret = get_old_ss_crypto_element(pkg_id, &ce)) != WAE_ERROR_NONE) - goto error; + if ((ret = get_old_ss_crypto_element(key, &ce)) != WAE_ERROR_NONE) + goto finish; // (k.tak) disable to save ce to key-maanger for migrated app because of permission issue. - //ret = save_to_key_manager(pkg_id, app_type, ce); + //ret = save_to_key_manager(key, pkg_id, app_type, ce); //if (ret != WAE_ERROR_NONE) { // WAE_SLOGW("Failed to save migrated app ce to key-manager with ret(%d). " // "Ignore this error because we can create ce later again.", ret); // ret = WAE_ERROR_NONE; //} } else if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to get crypto element from key-manager. pkg_id=%s, ret=%d", - pkg_id, ret); - goto error; + WAE_SLOGE("Failed to get crypto element from key-manager. key(%s) ret(%d)", + key, ret); + goto finish; } - ret = _add_app_ce_to_cache(pkg_id, ce); + ret = _add_app_ce_to_cache(key, ce); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret); - goto error; + WAE_SLOGE("Failed to add ce to cache for key(%s) ret(%d)", key, ret); + goto finish; } *pce = ce; - WAE_SLOGD("Successfully get ce! pkgid(%s)", pkg_id); + WAE_SLOGD("Successfully get ce! key(%s)", key); - return WAE_ERROR_NONE; +finish: + free(_key_per_user); -error: - crypto_element_destroy(ce); + if (ret != WAE_ERROR_NONE) + crypto_element_destroy(ce); return ret; } -int create_app_ce(const char *pkg_id, wae_app_type_e app_type, const crypto_element_s **pce) +int create_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type, + const crypto_element_s **pce) { raw_buffer_s *dek = buffer_create(DEK_LEN); raw_buffer_s *iv = buffer_create(IV_LEN); crypto_element_s *ce = crypto_element_create(dek, iv); int ret = WAE_ERROR_NONE; + const char *key = NULL; + char *_key_per_user = NULL; if (ce == NULL) { ret = WAE_ERROR_MEMORY; goto error; } + if (app_type == WAE_DOWNLOADED_NORMAL_APP) { + _key_per_user = _create_map_key(uid, pkg_id); + if (_key_per_user == NULL) { + ret = WAE_ERROR_MEMORY; + goto error; + } + + key = _key_per_user; + } else { + key = pkg_id; + } + memcpy(ce->iv->buf, AES_CBC_IV, ce->iv->size); ret = _get_random(dek); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to get random for dek. pkg_id(%s) ret(%d)", pkg_id, ret); + WAE_SLOGE("Failed to get random for dek. key(%s) ret(%d)", key, ret); goto error; } - ret = save_to_key_manager(pkg_id, app_type, ce); + ret = save_to_key_manager(key, pkg_id, app_type, ce); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to save ce to key-manager. pkg_id(%s) app_type(%d) ret(%d)", - pkg_id, app_type, ret); + WAE_SLOGE("Failed to save ce to key-manager. key(%s) app_type(%d) ret(%d)", + key, app_type, ret); goto error; } - ret = _add_app_ce_to_cache(pkg_id, ce); + ret = _add_app_ce_to_cache(key, ce); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret); + WAE_SLOGE("Failed to add ce to cache for key(%s) ret(%d)", key, ret); goto error; } *pce = ce; - WAE_SLOGI("Success to create dek/iv and store it in key-manager. pkg_id(%s)", pkg_id); - - return WAE_ERROR_NONE; + WAE_SLOGI("Success to create dek/iv and store it in key-manager. key(%s)", key); error: - if (ce == NULL) { - buffer_destroy(dek); - buffer_destroy(iv); - } else { - crypto_element_destroy(ce); + if (ret != WAE_ERROR_NONE) { + if (ce == NULL) { + buffer_destroy(dek); + buffer_destroy(iv); + } else { + crypto_element_destroy(ce); + } } + free(_key_per_user); + return ret; } @@ -542,7 +587,7 @@ int load_preloaded_app_deks(bool reload) continue; } - ret = save_to_key_manager(pkg_id, WAE_PRELOADED_APP, ce); + ret = save_to_key_manager(pkg_id, pkg_id, WAE_PRELOADED_APP, ce); if (ret == WAE_ERROR_KEY_EXISTS) { WAE_SLOGI("Key Manager already has dek. It will be ignored. file=%s", @@ -574,16 +619,34 @@ error: return ret; } -int remove_app_ce(const char *pkg_id, wae_app_type_e app_type) +int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type) { - int ret = remove_from_key_manager(pkg_id, app_type); + if (uid == 0 && app_type == WAE_DOWNLOADED_NORMAL_APP) + return WAE_ERROR_INVALID_PARAMETER; + + const char *key = NULL; + char *_key_per_user = NULL; + + if (app_type == WAE_DOWNLOADED_NORMAL_APP) { + _key_per_user = _create_map_key(uid, pkg_id); + if (_key_per_user == NULL) + return WAE_ERROR_MEMORY; + + key = _key_per_user; + } else { + key = pkg_id; + } + + int ret = remove_from_key_manager(key, app_type); if (ret != WAE_ERROR_NONE) - WAE_SLOGE("Failed to remove app ce for pkg_id(%s) ret(%d)", pkg_id, ret); + WAE_SLOGE("Failed to remove app ce for key(%s) ret(%d)", key, ret); else - WAE_SLOGI("Success to remove app ce for pkg_id(%s)", pkg_id); + WAE_SLOGI("Success to remove app ce for key(%s)", key); + + _remove_app_ce_from_cache(key); - _remove_app_ce_from_cache(pkg_id); + free(_key_per_user); return ret; } diff --git a/srcs/key_handler.h b/srcs/key_handler.h index e64d81c..791e149 100644 --- a/srcs/key_handler.h +++ b/srcs/key_handler.h @@ -28,28 +28,30 @@ extern "C" { #include #include +#include -#include "web_app_enc.h" #include "types.h" #define MAX_PATH_LEN 512 /* functions with "_" prefix are internal static functions but declared here for testing */ -void _remove_app_ce_from_cache(const char *pkg_id); +char *_create_map_key(uid_t uid, const char *pkg_id); +void _remove_app_ce_from_cache(const char *key); int _get_random(raw_buffer_s *rb); 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); /* functions for interface */ -int get_app_ce(const char *pkg_id, wae_app_type_e app_type, bool create_for_migrated_app, - const crypto_element_s **pce); -int create_app_ce(const char *pkg_id, wae_app_type_e app_type, +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); +int create_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type, const crypto_element_s **pce); +int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type); + 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); int load_preloaded_app_deks(bool reload); -int remove_app_ce(const char *pkg_id, wae_app_type_e app_type); #ifdef __cplusplus } diff --git a/srcs/key_manager.c b/srcs/key_manager.c index 4ef5b8a..aeee748 100644 --- a/srcs/key_manager.c +++ b/srcs/key_manager.c @@ -27,6 +27,7 @@ #include +#include "web_app_enc.h" #include "wae_log.h" #define MAX_ALIAS_LEN 256 @@ -192,28 +193,14 @@ error: return ret; } -static void _get_alias(const char *pkg_id, wae_app_type_e type, bool forSave, +static void _get_alias(const char *name, UNUSED wae_app_type_e type, UNUSED bool forSave, char *alias, size_t buff_len) { - if (type == WAE_DOWNLOADED_NORMAL_APP) { - if (forSave) { - snprintf(alias, buff_len, "%s%s", - APP_DEK_ALIAS_PFX, - pkg_id); - } else { - snprintf(alias, buff_len, "%c%s%s%s%s", - '/', INSTALLER_LABEL, - ckmc_owner_id_separator, - APP_DEK_ALIAS_PFX, - pkg_id); - } - } else { // system alias - snprintf(alias, buff_len, "%s%s%s%s", - ckmc_owner_id_system, - ckmc_owner_id_separator, - APP_DEK_ALIAS_PFX, - pkg_id); - } + snprintf(alias, buff_len, "%s%s%s%s", + ckmc_owner_id_system, + ckmc_owner_id_separator, + APP_DEK_ALIAS_PFX, + name); } static void _get_dek_loading_done_alias(char *alias, size_t buff_len) @@ -276,16 +263,17 @@ int clear_app_deks_loaded_from_key_manager() return _to_wae_error(ckmc_remove_alias(alias)); } -int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce) +int save_to_key_manager(const char *name, const char *pkg_id, wae_app_type_e type, + const crypto_element_s *ce) { char alias[MAX_ALIAS_LEN] = {0, }; - _get_alias(pkg_id, type, true, alias, sizeof(alias)); + _get_alias(name, type, true, alias, sizeof(alias)); ckmc_raw_buffer_s *buf = NULL; int ret = _serialize(ce, &buf); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to serialize crypto element of pkg_id: %s", pkg_id); + WAE_SLOGE("Failed to serialize crypto element of name(%s)", name); return ret; } @@ -298,8 +286,8 @@ int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_el ckmc_buffer_free(buf); if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Failed to add crypto element to ckm: pkg_id(%s) alias(%s) ret(%d)", - pkg_id, alias, ret); + WAE_SLOGE("Failed to add crypto element to ckm: name(%s) alias(%s) ret(%d)", + name, alias, ret); return ret; } @@ -312,19 +300,19 @@ int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_el return ret; } - WAE_SLOGI("Success to save crypto element to key-manager. pkg_id(%s)", pkg_id); + WAE_SLOGI("Success to save crypto element to key-manager. name(%s)", name); return WAE_ERROR_NONE; } -int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element_s **pce) +int get_from_key_manager(const char *name, wae_app_type_e type, crypto_element_s **pce) { - if (pkg_id == NULL || pce == NULL) + if (name == NULL || pce == NULL) return WAE_ERROR_INVALID_PARAMETER; char alias[MAX_ALIAS_LEN] = {0, }; - _get_alias(pkg_id, type, false, alias, sizeof(alias)); + _get_alias(name, type, false, alias, sizeof(alias)); ckmc_raw_buffer_s *buf = NULL; int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf)); @@ -338,11 +326,11 @@ int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element return ret; } -int remove_from_key_manager(const char *pkg_id, wae_app_type_e type) +int remove_from_key_manager(const char *name, wae_app_type_e type) { char alias[MAX_ALIAS_LEN] = {0, }; - _get_alias(pkg_id, type, true, alias, sizeof(alias)); + _get_alias(name, type, true, alias, sizeof(alias)); return _to_wae_error(ckmc_remove_alias(alias)); } diff --git a/srcs/key_manager.h b/srcs/key_manager.h index ec84561..4566b09 100644 --- a/srcs/key_manager.h +++ b/srcs/key_manager.h @@ -28,12 +28,12 @@ extern "C" { #include -#include "web_app_enc.h" #include "types.h" -int save_to_key_manager(const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce); -int get_from_key_manager(const char *pkg_id, wae_app_type_e type, crypto_element_s **pce); -int remove_from_key_manager(const char *pkg_id, wae_app_type_e type); +int save_to_key_manager(const char *name, const char *pkg_id, wae_app_type_e type, + const crypto_element_s *ce); +int get_from_key_manager(const char *name, wae_app_type_e type, crypto_element_s **pce); +int remove_from_key_manager(const char *name, wae_app_type_e type); bool is_app_deks_loaded_in_key_manager(); int set_app_deks_loaded_to_key_manager(); diff --git a/srcs/types.h b/srcs/types.h index 7e27aeb..51ed9fc 100644 --- a/srcs/types.h +++ b/srcs/types.h @@ -29,6 +29,15 @@ extern "C" { #include #include +#define API __attribute__ ((visibility("default"))) +#define UNUSED __attribute__ ((unused)) + +typedef enum { + WAE_DOWNLOADED_NORMAL_APP = 0, + WAE_DOWNLOADED_GLOBAL_APP = 1, + WAE_PRELOADED_APP = 2 +} wae_app_type_e; + typedef struct _raw_buffer_s { unsigned char *buf; size_t size; diff --git a/srcs/web_app_enc.c b/srcs/web_app_enc.c index 22da420..5846105 100644 --- a/srcs/web_app_enc.c +++ b/srcs/web_app_enc.c @@ -30,7 +30,7 @@ #include "wae_log.h" int _wae_encrypt_downloaded_web_application( - const char *pkg_id, wae_app_type_e app_type, + uid_t uid, const char *pkg_id, wae_app_type_e app_type, const unsigned char *data, size_t data_len, unsigned char **pencrypted_data, size_t *pencrypted_data_len) { @@ -39,10 +39,10 @@ int _wae_encrypt_downloaded_web_application( return WAE_ERROR_INVALID_PARAMETER; const crypto_element_s *e = NULL; - int ret = get_app_ce(pkg_id, app_type, false, &e); + int ret = get_app_ce(uid, pkg_id, app_type, false, &e); if (ret == WAE_ERROR_NO_KEY) - ret = create_app_ce(pkg_id, app_type, &e); + ret = create_app_ce(uid, pkg_id, app_type, &e); if (ret != WAE_ERROR_NONE) return ret; @@ -64,7 +64,8 @@ int _wae_encrypt_downloaded_web_application( return WAE_ERROR_NONE; } -int _wae_decrypt_downloaded_web_application(const char *pkg_id, wae_app_type_e app_type, +int _wae_decrypt_downloaded_web_application( + uid_t uid, const char *pkg_id, wae_app_type_e app_type, const unsigned char *data, size_t data_len, unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) { @@ -77,7 +78,7 @@ int _wae_decrypt_downloaded_web_application(const char *pkg_id, wae_app_type_e a _data.size = data_len; const crypto_element_s *ce = NULL; - int ret = get_app_ce(pkg_id, app_type, true, &ce); + int ret = get_app_ce(uid, pkg_id, app_type, true, &ce); if (ret != WAE_ERROR_NONE) return ret; @@ -134,40 +135,69 @@ int _wae_encrypt_preloaded_web_application(const char *pkg_id, return WAE_ERROR_NONE; } -int _wae_decrypt_preloaded_web_application(const char *pkg_id, wae_app_type_e app_type, +int _wae_decrypt_preloaded_web_application(const char *pkg_id, const unsigned char *data, size_t data_len, unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) { // same with the decryption of downloaded web application - return _wae_decrypt_downloaded_web_application(pkg_id, app_type, + return _wae_decrypt_downloaded_web_application(0, pkg_id, WAE_PRELOADED_APP, data, data_len, pdecrypted_data, pdecrypted_data_len); } -int wae_encrypt_web_application(const char *pkg_id, wae_app_type_e app_type, - const unsigned char *data, size_t data_len, - unsigned char **pencrypted_data, size_t *pencrypted_data_len) +int wae_encrypt_web_application( + uid_t uid, const char *pkg_id, + const unsigned char *data, size_t data_len, + unsigned char **pencrypted_data, size_t *pencrypted_data_len) { - if (app_type == WAE_PRELOADED_APP) + return _wae_encrypt_downloaded_web_application( + uid, pkg_id, WAE_DOWNLOADED_NORMAL_APP, + data, data_len, pencrypted_data, pencrypted_data_len); +} + +int wae_encrypt_global_web_application( + const char *pkg_id, bool is_preloaded, + const unsigned char *data, size_t data_len, + unsigned char **pencrypted_data, size_t *pencrypted_data_len) +{ + if (is_preloaded) return _wae_encrypt_preloaded_web_application(pkg_id, data, data_len, pencrypted_data, pencrypted_data_len); else - return _wae_encrypt_downloaded_web_application(pkg_id, app_type, + return _wae_encrypt_downloaded_web_application( + 0, pkg_id, WAE_DOWNLOADED_GLOBAL_APP, data, data_len, pencrypted_data, pencrypted_data_len); } -int wae_decrypt_web_application(const char *pkg_id, wae_app_type_e app_type, - const unsigned char *data, size_t data_len, - unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) +int wae_decrypt_web_application( + uid_t uid, const char *pkg_id, + const unsigned char *data, size_t data_len, + unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) +{ + return _wae_decrypt_downloaded_web_application( + uid, pkg_id, WAE_DOWNLOADED_NORMAL_APP, + data, data_len, pdecrypted_data, pdecrypted_data_len); +} + +int wae_decrypt_global_web_application( + const char *pkg_id, bool is_preloaded, + const unsigned char *data, size_t data_len, + unsigned char **pdecrypted_data, size_t *pdecrypted_data_len) { - if (app_type == WAE_PRELOADED_APP) - return _wae_decrypt_preloaded_web_application(pkg_id, app_type, + if (is_preloaded) + return _wae_decrypt_preloaded_web_application(pkg_id, data, data_len, pdecrypted_data, pdecrypted_data_len); else - return _wae_decrypt_downloaded_web_application(pkg_id, app_type, + return _wae_decrypt_downloaded_web_application( + 0, pkg_id, WAE_DOWNLOADED_GLOBAL_APP, data, data_len, pdecrypted_data, pdecrypted_data_len); } -int wae_remove_app_dek(const char *pkg_id, wae_app_type_e app_type) +int wae_remove_app_dek(uid_t uid, const char *pkg_id) +{ + return remove_app_ce(uid, pkg_id, WAE_DOWNLOADED_NORMAL_APP); +} + +int wae_remove_global_app_dek(const char *pkg_id, bool is_preloaded) { - return remove_app_ce(pkg_id, app_type); + return remove_app_ce(0, pkg_id, is_preloaded ? WAE_PRELOADED_APP : WAE_DOWNLOADED_GLOBAL_APP); } diff --git a/tests/internals.cpp b/tests/internals.cpp index b5c106d..1fa9aff 100644 --- a/tests/internals.cpp +++ b/tests/internals.cpp @@ -310,8 +310,8 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) _get_preloaded_app_dek_file_path(pkg_id2, sizeof(path2), path2); // remove old test data - remove_app_ce(pkg_id1, WAE_PRELOADED_APP); - remove_app_ce(pkg_id2, WAE_PRELOADED_APP); + remove_app_ce(0, pkg_id1, WAE_PRELOADED_APP); + remove_app_ce(0, pkg_id2, WAE_PRELOADED_APP); unlink(path1); unlink(path2); @@ -331,20 +331,20 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) "Failed to load_preloaded_app_deks. ec: " << ret); const crypto_element_s *readed1 = nullptr; - ret = get_app_ce(pkg_id1, WAE_PRELOADED_APP, false, &readed1); + ret = get_app_ce(0, pkg_id1, WAE_PRELOADED_APP, false, &readed1); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to get_app_dek. ec: " << ret); const crypto_element_s *readed2 = nullptr; - ret = get_app_ce(pkg_id2, WAE_PRELOADED_APP, false, &readed2); + ret = get_app_ce(0, pkg_id2, WAE_PRELOADED_APP, false, &readed2); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to get_app_dek. ec: " << ret); BOOST_REQUIRE_MESSAGE(readed1 == ce1, "cached ce and actual address is different!"); BOOST_REQUIRE_MESSAGE(readed2 == ce2, "cached ce and actual address is different!"); - ret = remove_app_ce(pkg_id1, WAE_PRELOADED_APP); + ret = remove_app_ce(0, pkg_id1, WAE_PRELOADED_APP); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed remove app ce. ec: " << ret); - ret = remove_app_ce(pkg_id2, WAE_PRELOADED_APP); + ret = remove_app_ce(0, pkg_id2, WAE_PRELOADED_APP); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed remove app ce. ec: " << ret); } diff --git a/tests/non-normals.cpp b/tests/non-normals.cpp index 81c0173..78c2197 100644 --- a/tests/non-normals.cpp +++ b/tests/non-normals.cpp @@ -20,10 +20,9 @@ * @version 2.0 * @brief API test for preloaded/global apps */ -#include "web_app_enc.h" - #include +#include "types.h" #include "test-helper.h" BOOST_AUTO_TEST_SUITE(SYSTEM) diff --git a/tests/normals.cpp b/tests/normals.cpp index 5d67910..fad04f1 100644 --- a/tests/normals.cpp +++ b/tests/normals.cpp @@ -20,10 +20,9 @@ * @version 2.0 * @brief test for normal downloaded app */ -#include "web_app_enc.h" - #include +#include "types.h" #include "test-helper.h" BOOST_AUTO_TEST_SUITE(USER) diff --git a/tests/test-helper.cpp b/tests/test-helper.cpp index f303b75..d0ca263 100644 --- a/tests/test-helper.cpp +++ b/tests/test-helper.cpp @@ -23,6 +23,7 @@ #include #include +#include "web_app_enc.h" #include "key_handler.h" #include "crypto_service.h" #include "types.h" @@ -32,32 +33,39 @@ namespace Wae { namespace Test { +namespace { + +const uid_t UID_OWNER = 5001; + +} // namespace anonymous void add_get_remove_ce(wae_app_type_e app_type) { const char *pkg_id = "TEST_PKG_ID"; const crypto_element_s *ce = nullptr; - int tmp = create_app_ce(pkg_id, app_type, &ce); + uid_t uid = app_type == WAE_DOWNLOADED_NORMAL_APP ? UID_OWNER : 0; + + int tmp = create_app_ce(uid, pkg_id, app_type, &ce); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to create_app_ce. ec: " << tmp); const crypto_element_s *stored_ce = nullptr; - tmp = get_app_ce(pkg_id, app_type, true, &stored_ce); + tmp = get_app_ce(uid, pkg_id, app_type, true, &stored_ce); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to get_app_ce. ec: " << tmp); BOOST_REQUIRE_MESSAGE(ce == stored_ce, "ce(" << ce << ") and cached ce(" << stored_ce << ") pointer addr is different!"); - tmp = remove_app_ce(pkg_id, app_type); + tmp = remove_app_ce(uid, pkg_id, app_type); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to remove_app_ce. ec: " << tmp); if (app_type == WAE_DOWNLOADED_GLOBAL_APP) { - tmp = get_app_ce(pkg_id, app_type, true, &stored_ce); + tmp = get_app_ce(uid, pkg_id, app_type, true, &stored_ce); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE && stored_ce->is_migrated_app, "when getting app ce which is there isn't, it should be migrated case! " "ret("<< tmp << ") and is_migrated_app(" << stored_ce->is_migrated_app << ")"); } else { - tmp = get_app_ce(pkg_id, app_type, false, &stored_ce); + tmp = get_app_ce(uid, pkg_id, app_type, false, &stored_ce); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NO_KEY, "removed app ce is still remaining. ret(" << tmp << ")"); } @@ -65,28 +73,30 @@ void add_get_remove_ce(wae_app_type_e app_type) void create_app_ce(wae_app_type_e app_type) { + uid_t uid = app_type == WAE_DOWNLOADED_NORMAL_APP ? UID_OWNER : 0; const char *pkg_id = "TEST_PKG_ID"; - remove_app_ce(pkg_id, app_type); + remove_app_ce(uid, pkg_id, app_type); const crypto_element_s *ce = nullptr; - int tmp = create_app_ce(pkg_id, app_type, &ce); + int tmp = create_app_ce(uid, pkg_id, app_type, &ce); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to create_app_ce. ec: " << tmp); const crypto_element_s *stored_ce = nullptr; - tmp = get_app_ce(pkg_id, app_type, false, &stored_ce); + tmp = get_app_ce(uid, pkg_id, app_type, false, &stored_ce); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to get_app_ce. ec: " << tmp); BOOST_REQUIRE_MESSAGE(ce == stored_ce, "ce(" << ce << ") and cached ce(" << stored_ce << ") pointer addr is different!"); - tmp = remove_app_ce(pkg_id, app_type); + tmp = remove_app_ce(uid, pkg_id, app_type); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to remove_app_ce. ec: " << tmp); } void encrypt_decrypt_web_app(wae_app_type_e app_type) { + uid_t uid = app_type == WAE_DOWNLOADED_NORMAL_APP ? UID_OWNER : 0; const char *pkg_id1 = "testpkg_for_normal"; const char *pkg_id2 = "testpkg_for_global"; const char *pkg_id3 = "testpkg_for_preloaded"; @@ -108,7 +118,10 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) } // remove old test data - wae_remove_app_dek(pkg_id, app_type); + if (app_type == WAE_DOWNLOADED_NORMAL_APP) + wae_remove_app_dek(uid, pkg_id); + else + wae_remove_global_app_dek(pkg_id, app_type == WAE_PRELOADED_APP); if (app_type == WAE_PRELOADED_APP) clear_app_deks_loaded_from_key_manager(); @@ -121,30 +134,55 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) // test for downloaded web application unsigned char *_encrypted = nullptr; size_t _enc_len = 0; - int tmp = wae_encrypt_web_application(pkg_id, app_type, plaintext.data(), - plaintext.size(), &_encrypted, &_enc_len); + int tmp = 0; + if (app_type == WAE_DOWNLOADED_NORMAL_APP) + tmp = wae_encrypt_web_application(uid, pkg_id, plaintext.data(), plaintext.size(), + &_encrypted, &_enc_len); + else + tmp = wae_encrypt_global_web_application(pkg_id, app_type == WAE_PRELOADED_APP, + plaintext.data(), plaintext.size(), + &_encrypted, &_enc_len); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to wae_encrypt_web_application. ec: " << tmp); free(_encrypted); // encrypt test twice - tmp = wae_encrypt_web_application(pkg_id, app_type, plaintext.data(), - plaintext.size(), &_encrypted, &_enc_len); + if (app_type == WAE_DOWNLOADED_NORMAL_APP) + tmp = wae_encrypt_web_application(uid, pkg_id, plaintext.data(), + plaintext.size(), &_encrypted, &_enc_len); + else + tmp = wae_encrypt_global_web_application(pkg_id, app_type == WAE_PRELOADED_APP, + plaintext.data(), plaintext.size(), + &_encrypted, &_enc_len); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to wae_encrypt_web_application second time. ec: " << tmp); auto encrypted = bytearr_to_vec(_encrypted, _enc_len); free(_encrypted); - _remove_app_ce_from_cache(pkg_id); + if (app_type == WAE_DOWNLOADED_NORMAL_APP) { + char *key_per_user = _create_map_key(uid, pkg_id); + _remove_app_ce_from_cache(key_per_user); + free(key_per_user); + } else { + _remove_app_ce_from_cache(pkg_id); + } if (app_type == WAE_PRELOADED_APP) load_preloaded_app_deks(true); unsigned char *_decrypted = nullptr; size_t _dec_len = 0; - tmp = wae_decrypt_web_application(pkg_id, app_type, encrypted.data(), - encrypted.size(), &_decrypted, &_dec_len); + if (app_type == WAE_DOWNLOADED_NORMAL_APP) + tmp = wae_decrypt_web_application(uid, pkg_id, encrypted.data(), encrypted.size(), + &_decrypted, &_dec_len); + else + tmp = wae_decrypt_global_web_application(pkg_id, app_type == WAE_PRELOADED_APP, + encrypted.data(), encrypted.size(), + &_decrypted, &_dec_len); + BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to wae_decrypt_web_application. ec: " << tmp); @@ -155,7 +193,10 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) "plaintext(" << bytes_to_hex(plaintext) << ") " "decrypted(" << bytes_to_hex(decrypted) << ")"); - tmp = wae_remove_app_dek(pkg_id, app_type); + if (app_type == WAE_DOWNLOADED_NORMAL_APP) + tmp = wae_remove_app_dek(uid, pkg_id); + else + tmp = wae_remove_global_app_dek(pkg_id, app_type == WAE_PRELOADED_APP); BOOST_REQUIRE_MESSAGE(tmp == WAE_ERROR_NONE, "Failed to wae_remove_app_dek. ec: " << tmp); } diff --git a/tests/test-helper.h b/tests/test-helper.h index c0c77f6..b4d1f42 100644 --- a/tests/test-helper.h +++ b/tests/test-helper.h @@ -20,7 +20,7 @@ */ #pragma once -#include "web_app_enc.h" +#include "types.h" namespace Wae { namespace Test { -- 2.7.4 From f327e9fca40ad1cf62ac18e052f09c65debac72b Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Thu, 11 Aug 2016 15:15:12 +0900 Subject: [PATCH 07/16] [HOTFIX] Fix build break on 64bit arch [Problem] * EVP_Digest parameter type is unsigned int * size_t is differ between 32bit and 64bit [Solution] * Use unsigned int instead of size_t Change-Id: Ib398532c7148bcd9d736c7282e0b74c8042a2ede Signed-off-by: sangwan.kwon --- srcs/decrypt_migrated_wgt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/srcs/decrypt_migrated_wgt.c b/srcs/decrypt_migrated_wgt.c index 1012a35..4eae90b 100644 --- a/srcs/decrypt_migrated_wgt.c +++ b/srcs/decrypt_migrated_wgt.c @@ -82,11 +82,13 @@ static int _get_old_iv(const raw_buffer_s *src, raw_buffer_s **piv) if (iv == NULL) return WAE_ERROR_MEMORY; - if (EVP_Digest(src->buf, src->size, iv->buf, &iv->size, EVP_sha1(), NULL) != 1) { + unsigned int _size; + if (EVP_Digest(src->buf, src->size, iv->buf, &_size, EVP_sha1(), NULL) != 1) { buffer_destroy(iv); return WAE_ERROR_CRYPTO; } + iv->size = _size; *piv = iv; WAE_SLOGD("get old iv of length: %d", iv->size); -- 2.7.4 From 8ccec6785ee30fb7c9e06a3421f5b460364b2968 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Tue, 6 Sep 2016 15:55:08 +0900 Subject: [PATCH 08/16] Add upgrade script Change-Id: I4d38443cf3880b50215aa36e084445cc8bbb60be Signed-off-by: Kyungwook Tak --- CMakeLists.txt | 1 + packaging/libwebappenc.manifest.in | 5 +++++ packaging/libwebappenc.spec | 23 +++++++++++++++++---- resources/CMakeLists.txt | 35 +++++++++++++++++++++++++------- scripts/CMakeLists.txt | 16 +++++++++++++++ scripts/wae-upgrade.sh.in | 30 +++++++++++++++++++++++++++ systemd/CMakeLists.txt | 24 ++++++++++++++-------- systemd/webappenc-initializer.service.in | 8 ++++---- 8 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 scripts/CMakeLists.txt create mode 100755 scripts/wae-upgrade.sh.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 436eb74..96efdbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,3 +93,4 @@ ADD_SUBDIRECTORY(resources) ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(systemd) +ADD_SUBDIRECTORY(scripts) diff --git a/packaging/libwebappenc.manifest.in b/packaging/libwebappenc.manifest.in index 86dbb26..5451c22 100644 --- a/packaging/libwebappenc.manifest.in +++ b/packaging/libwebappenc.manifest.in @@ -2,4 +2,9 @@ + + + + + diff --git a/packaging/libwebappenc.spec b/packaging/libwebappenc.spec index 7d796f9..9f8faef 100644 --- a/packaging/libwebappenc.spec +++ b/packaging/libwebappenc.spec @@ -37,8 +37,14 @@ Requires: %{name} = %{version}-%{release} %description test Web application encryption and decryption service (test) -%define bin_dir %TZ_SYS_BIN -%define rw_share_dir %TZ_SYS_SHARE +%define user_name security_fw +%define group_name security_fw +%define smack_domain System +%define bin_dir %TZ_SYS_BIN +%define rw_share_dir %TZ_SYS_SHARE +%define upgrade_dir %TZ_SYS_RO_SHARE/upgrade +%define upgrade_script_dir %{upgrade_dir}/scripts +%define upgrade_data_dir %{upgrade_dir}/data %prep %setup -q @@ -52,6 +58,11 @@ Web application encryption and decryption service (test) -DSYSTEMD_UNIT_DIR=%{_unitdir} \ -DCMAKE_BUILD_TYPE=%{build_type} \ -DRW_SHARE_DIR=%rw_share_dir \ + -DUPGRADE_DATA_DIR=%upgrade_data_dir \ + -DUPGRADE_SCRIPT_DIR=%upgrade_script_dir \ + -DUSER_NAME=%user_name \ + -DGROUP_NAME=%group_name \ + -DSMACK_DOMAIN=%smack_domain \ -DBINDIR=%bin_dir make %{?jobs:-j%jobs} @@ -88,8 +99,12 @@ fi %{_unitdir}/webappenc-initializer.service %{_unitdir}/multi-user.target.wants/webappenc-initializer.service %{bin_dir}/wae_initializer -%{rw_share_dir}/wae/app_dek/WAE_APPDEK_KEK_PrivateKey.pem -%{rw_share_dir}/wae/app_dek/WAE_APPDEK_KEK_PublicKey.pem +%dir %attr(770, %user_name, %group_name) %{rw_share_dir}/wae +%dir %attr(770, %user_name, %group_name) %{rw_share_dir}/wae/app_dek +%attr(660, %user_name, %group_name) %{rw_share_dir}/wae/app_dek/* + +%attr(775,root,root) %{upgrade_script_dir}/wae-upgrade.sh +%{upgrade_data_dir}/wae/app_dek/* %files devel %{_includedir}/* diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index ae2bc8b..030553c 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -1,12 +1,33 @@ -################################################################################ -# for resource install -################################################################################ - +# Copyright (c) 2016 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 CMakeLists.txt +# @author Dongsun Lee (ds73.lee@samsung.com) +# @brief Resource install cmake +# INSTALL(FILES - ${PROJECT_SOURCE_DIR}/resources/WAE_APPDEK_KEK_PublicKey.pem - ${PROJECT_SOURCE_DIR}/resources/WAE_APPDEK_KEK_PrivateKey.pem - DESTINATION ${RW_SHARE_DIR}/wae/app_dek/ + WAE_APPDEK_KEK_PublicKey.pem + WAE_APPDEK_KEK_PrivateKey.pem + DESTINATION ${RW_SHARE_DIR}/wae/app_dek PERMISSIONS OWNER_READ OWNER_WRITE ) +INSTALL(FILES + WAE_APPDEK_KEK_PublicKey.pem + WAE_APPDEK_KEK_PrivateKey.pem + DESTINATION ${UPGRADE_DATA_DIR}/wae/app_dek + PERMISSIONS OWNER_READ + OWNER_WRITE +) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt new file mode 100644 index 0000000..c73467e --- /dev/null +++ b/scripts/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2016 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. +# +CONFIGURE_FILE(wae-upgrade.sh.in wae-upgrade.sh @ONLY) +INSTALL(FILES wae-upgrade.sh DESTINATION ${UPGRADE_SCRIPT_DIR}) diff --git a/scripts/wae-upgrade.sh.in b/scripts/wae-upgrade.sh.in new file mode 100755 index 0000000..652962b --- /dev/null +++ b/scripts/wae-upgrade.sh.in @@ -0,0 +1,30 @@ +#!/bin/bash +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +# Copyright (c) 2016 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-upgrade.sh.in +# @author Kyungwook Tak (k.tak@samsung.com) +# @brief Platform upgrade support + +WAE_DIR=@RW_SHARE_DIR@/wae + +mv @UPGRADE_DATA_DIR@/wae $WAE_DIR + +chsmack -a "@SMACK_DOMAIN@" $WAE_DIR -r +chown -R @USER_NAME@:@GROUP_NAME@ $WAE_DIR +chmod 770 $WAE_DIR +chmod 770 $WAE_DIR/app_dek +chmod 660 $WAE_DIR/app_dek/* diff --git a/systemd/CMakeLists.txt b/systemd/CMakeLists.txt index bf7bb79..99eafd5 100644 --- a/systemd/CMakeLists.txt +++ b/systemd/CMakeLists.txt @@ -1,8 +1,16 @@ -CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/webappenc-initializer.service.in - ${CMAKE_SOURCE_DIR}/systemd/webappenc-initializer.service @ONLY) - -INSTALL(FILES - ${CMAKE_SOURCE_DIR}/systemd/webappenc-initializer.service - DESTINATION - ${SYSTEMD_UNIT_DIR} -) +# Copyright (c) 2016 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. +# +CONFIGURE_FILE(webappenc-initializer.service.in webappenc-initializer.service @ONLY) +INSTALL(FILES webappenc-initializer.service DESTINATION ${SYSTEMD_UNIT_DIR}) diff --git a/systemd/webappenc-initializer.service.in b/systemd/webappenc-initializer.service.in index 768552e..ed0bebe 100644 --- a/systemd/webappenc-initializer.service.in +++ b/systemd/webappenc-initializer.service.in @@ -5,11 +5,11 @@ Requires=central-key-manager.service After=central-key-manager.service [Service] -User=security_fw -Group=security_fw +User=@USER_NAME@ +Group=@GROUP_NAME@ Type=oneshot -ExecStart=/usr/bin/wae_initializer -SmackProcessLabel=System +ExecStart=@BINDIR@/wae_initializer +SmackProcessLabel=@SMACK_DOMAIN@ [Install] WantedBy=multi-user.target -- 2.7.4 From 0780d62047e7d7472c65c791866e7a5fa9be7863 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Mon, 28 Nov 2016 20:25:03 +0900 Subject: [PATCH 09/16] Fix svace defects 1) Missing returned value checking. 2) variable misused (start -> end). 3) Dead code exist in preloaded app dek loading while loop. Make subroutine to simplify loop codes/resource managed. Change-Id: Ic775e336e6480dfb56539e382edf292f2101ec8b Signed-off-by: Kyungwook Tak --- srcs/key_handler.c | 147 +++++++++++++++++++++++++---------------------------- 1 file changed, 70 insertions(+), 77 deletions(-) diff --git a/srcs/key_handler.c b/srcs/key_handler.c index cf3de1d..4607fdd 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -211,7 +211,7 @@ static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id) start = start + strlen(APP_DEK_FILE_PFX) + 1; char *end = strstr(file_name, ".adek"); - if (start == NULL) { + if (end == NULL) { WAE_SLOGE("WAE: Fail to extract pkgid from APP_DEK file. file_name=%s", file_name); return WAE_ERROR_FILE; } @@ -236,6 +236,60 @@ 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) +{ + raw_buffer_s *encrypted_dek = NULL; + raw_buffer_s *dek = NULL; + raw_buffer_s *iv = NULL; + crypto_element_s *ce = NULL; + + int ret = _read_from_file(filepath, &encrypted_dek); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGW("Failed to read file. It will be ignored. file=%s", filepath); + return ret; + } + + ret = decrypt_app_dek(prikey, APP_DEK_KEK_PRIKEY_PASSWORD, encrypted_dek, &dek); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGW("Failed to decrypt dek. It will be ignored. file=%s", filepath); + goto finish; + } + + iv = buffer_create(IV_LEN); + if (iv == NULL) { + ret = WAE_ERROR_MEMORY; + goto finish; + } + + memcpy(iv->buf, AES_CBC_IV, iv->size); + + ce = crypto_element_create(dek, iv); + if (ce == NULL) { + ret = WAE_ERROR_MEMORY; + goto finish; + } + + ret = save_to_key_manager(pkg_id, pkg_id, WAE_PRELOADED_APP, ce); + if (ret == WAE_ERROR_KEY_EXISTS) { + WAE_SLOGI("Key Manager already has dek. It will be ignored. file=%s", filepath); + } else if (ret != WAE_ERROR_NONE) { + WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s", filepath); + } + +finish: + buffer_destroy(encrypted_dek); + + if (ce == NULL) { + buffer_destroy(dek); + buffer_destroy(iv); + } else { + crypto_element_destroy(ce); + } + + return ret; +} + 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) { @@ -438,7 +492,7 @@ int create_preloaded_app_ce(const char *pkg_id, const crypto_element_s **pce) } // store APP_DEK in cache - _add_app_ce_to_cache(pkg_id, ce); + ret = _add_app_ce_to_cache(pkg_id, ce); if (ret != WAE_ERROR_NONE) { WAE_SLOGE("Failed to add ce to cache for pkg_id(%s) ret(%d)", pkg_id, ret); goto error; @@ -479,15 +533,7 @@ int load_preloaded_app_deks(bool reload) int ret = WAE_ERROR_NONE; char pkg_id[MAX_PKGID_LEN] = {0, }; - char file_path_buff[MAX_PATH_LEN]; - raw_buffer_s *encrypted_dek = NULL; - raw_buffer_s *dek = NULL; - raw_buffer_s *iv = NULL; - raw_buffer_s *prikey = NULL; - crypto_element_s *ce = NULL; - - int error_during_loading = 0; if (!reload) { // check if all deks were already loaded into key-manager. @@ -497,6 +543,7 @@ int load_preloaded_app_deks(bool reload) return ret; } + raw_buffer_s *prikey = NULL; ret = _get_app_dek_kek(&prikey); if (ret != WAE_ERROR_NONE) { @@ -508,6 +555,7 @@ int load_preloaded_app_deks(bool reload) if (dir == NULL) { WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path()); + buffer_destroy(prikey); return WAE_ERROR_FILE; } @@ -515,11 +563,9 @@ int load_preloaded_app_deks(bool reload) struct dirent *result = NULL; while (true) { - int error = readdir_r(dir, &entry, &result); - - if (error != 0) { + if (readdir_r(dir, &entry, &result) != 0) { ret = WAE_ERROR_FILE; - goto error; + break; } // readdir_r returns NULL in *result if the end @@ -537,7 +583,7 @@ int load_preloaded_app_deks(bool reload) if (ret < 0) { WAE_SLOGE("Failed to make file path by snprintf."); ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ - goto error; + break; } ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id); @@ -548,75 +594,22 @@ int load_preloaded_app_deks(bool reload) continue; } - ret = _read_from_file(file_path_buff, &encrypted_dek); - - if (ret != WAE_ERROR_NONE || encrypted_dek == NULL) { - ++error_during_loading; - WAE_SLOGW("Failed to read file. It will be ignored. file=%s", file_path_buff); - continue; - } - - ret = decrypt_app_dek(prikey, APP_DEK_KEK_PRIKEY_PASSWORD, encrypted_dek, &dek); - - buffer_destroy(encrypted_dek); - encrypted_dek = NULL; - - if (ret != WAE_ERROR_NONE || dek == NULL) { - ++error_during_loading; - WAE_SLOGW("Failed to decrypt dek. It will be ignored. file=%s", - file_path_buff); - continue; - } - iv = buffer_create(IV_LEN); - if (iv == NULL) { - ++error_during_loading; - buffer_destroy(dek); - dek = NULL; - continue; - } - - memcpy(iv->buf, AES_CBC_IV, iv->size); - - ce = crypto_element_create(dek, iv); - if (ce == NULL) { - ++error_during_loading; - buffer_destroy(iv); - iv = NULL; - buffer_destroy(dek); - dek = NULL; - continue; - } - - ret = save_to_key_manager(pkg_id, pkg_id, WAE_PRELOADED_APP, ce); - - if (ret == WAE_ERROR_KEY_EXISTS) { - WAE_SLOGI("Key Manager already has dek. It will be ignored. file=%s", - file_path_buff); - } else if (ret != WAE_ERROR_NONE) { - ++error_during_loading; - WAE_SLOGW("Fail to add APP DEK to key-manager. file=%s", file_path_buff); - } - - crypto_element_destroy(ce); - ce = NULL; - } - - ret = set_app_deks_loaded_to_key_manager(); - -error: - if (ret != WAE_ERROR_NONE) { - if (ce) { - crypto_element_destroy(ce); + ret = _load_preloaded_app_dek(prikey, file_path_buff, pkg_id); + if (ret != WAE_ERROR_NONE && ret != WAE_ERROR_KEY_EXISTS) { + WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret); } else { - buffer_destroy(dek); - buffer_destroy(iv); + WAE_SLOGI("Successfully load app dek(%s)", file_path_buff); + ret = WAE_ERROR_NONE; } } buffer_destroy(prikey); closedir(dir); - return ret; + if (ret != WAE_ERROR_NONE) + return ret; + else + return set_app_deks_loaded_to_key_manager(); } int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type) -- 2.7.4 From 99e3231e9112039e45e42c186ed8d77a939ae0a7 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Mon, 5 Dec 2016 17:10:20 +0900 Subject: [PATCH 10/16] Numbering upgrade script wae-upgrade.sh -> 200.wae.sh Change-Id: I77f59c43be20cdb7eb808ca5e7a754287bcdfcb0 Signed-off-by: Kyungwook Tak --- packaging/libwebappenc.spec | 2 +- scripts/{wae-upgrade.sh.in => 200.wae.sh.in} | 2 +- scripts/CMakeLists.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename scripts/{wae-upgrade.sh.in => 200.wae.sh.in} (96%) diff --git a/packaging/libwebappenc.spec b/packaging/libwebappenc.spec index 9f8faef..760f3e2 100644 --- a/packaging/libwebappenc.spec +++ b/packaging/libwebappenc.spec @@ -103,7 +103,7 @@ fi %dir %attr(770, %user_name, %group_name) %{rw_share_dir}/wae/app_dek %attr(660, %user_name, %group_name) %{rw_share_dir}/wae/app_dek/* -%attr(775,root,root) %{upgrade_script_dir}/wae-upgrade.sh +%attr(775,root,root) %{upgrade_script_dir}/200.wae.sh %{upgrade_data_dir}/wae/app_dek/* %files devel diff --git a/scripts/wae-upgrade.sh.in b/scripts/200.wae.sh.in similarity index 96% rename from scripts/wae-upgrade.sh.in rename to scripts/200.wae.sh.in index 652962b..5552f74 100755 --- a/scripts/wae-upgrade.sh.in +++ b/scripts/200.wae.sh.in @@ -15,7 +15,7 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin # See the License for the specific language governing permissions and # limitations under the License. # -# @file wae-upgrade.sh.in +# @file 200.wae.sh.in # @author Kyungwook Tak (k.tak@samsung.com) # @brief Platform upgrade support diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index c73467e..f4098fc 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -12,5 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. # -CONFIGURE_FILE(wae-upgrade.sh.in wae-upgrade.sh @ONLY) -INSTALL(FILES wae-upgrade.sh DESTINATION ${UPGRADE_SCRIPT_DIR}) +CONFIGURE_FILE(200.wae.sh.in 200.wae.sh @ONLY) +INSTALL(FILES 200.wae.sh DESTINATION ${UPGRADE_SCRIPT_DIR}) -- 2.7.4 From 0778e0964f8fecd8ce06c307eddc2ccf1632fc2b Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Mon, 5 Dec 2016 17:13:40 +0900 Subject: [PATCH 11/16] Use cp instead of mv in upgrade script RO partition shouldn't be modified Change-Id: I70b8de4051cd4295b5431b77fd5eb82f1e518731 Signed-off-by: Kyungwook Tak --- scripts/200.wae.sh.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/200.wae.sh.in b/scripts/200.wae.sh.in index 5552f74..29d9497 100755 --- a/scripts/200.wae.sh.in +++ b/scripts/200.wae.sh.in @@ -21,7 +21,7 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin WAE_DIR=@RW_SHARE_DIR@/wae -mv @UPGRADE_DATA_DIR@/wae $WAE_DIR +cp -rf @UPGRADE_DATA_DIR@/wae $WAE_DIR chsmack -a "@SMACK_DOMAIN@" $WAE_DIR -r chown -R @USER_NAME@:@GROUP_NAME@ $WAE_DIR -- 2.7.4 From 9efcb91aed4e7365aa945fc9c6ffe2d111ca1496 Mon Sep 17 00:00:00 2001 From: Bartlomiej Kunikowski Date: Mon, 5 Dec 2016 08:49:59 +0100 Subject: [PATCH 12/16] Fix for wae_initializer There is a bug in if statement, it don't allow to properly work of this initializer if there are no --reload flag. Other way to do it is simply use wae_initializer always as it is with --reload flag. Change-Id: I9622373c914f8c0f1f22d3f810417251cced81ba Signed-off-by: Bartlomiej Kunikowski (cherry picked from commit 1fcac8945420537f89d24a0e8e52ec99cc432674) --- srcs/key_handler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srcs/key_handler.c b/srcs/key_handler.c index 4607fdd..905538e 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -539,8 +539,8 @@ int load_preloaded_app_deks(bool reload) // check if all deks were already loaded into key-manager. ret = is_app_deks_loaded_in_key_manager(); - if (ret == WAE_ERROR_NONE) - return ret; + if (ret == true) + return WAE_ERROR_NONE; } raw_buffer_s *prikey = NULL; -- 2.7.4 From 66f4515064566676869fd3c3a8970fcf24b00b5f Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Wed, 7 Dec 2016 17:22:40 +0900 Subject: [PATCH 13/16] Remove reload option to wae initializer service Reload option is not needed anymore. To be secure, remove all KEKs from dek store (also adek) after loading preloaded adeks once. Loaded adeks are stored in key-manager so they're useless. Related test cases are added. (load preloaded app deks) (TODO) To use key-manager initial value feature is highly considered to store KEK private key more securely. Change-Id: I2f6c645398277968cd7d480236d1802a07fa33df Signed-off-by: Kyungwook Tak --- packaging/libwebappenc.spec | 1 + srcs/key_handler.c | 164 +++++++++++++++++++++++++++++++---------- srcs/key_handler.h | 6 +- srcs/key_manager.c | 61 --------------- srcs/wae_initializer.c | 9 +-- tests/CMakeLists.txt | 2 + tests/internals.cpp | 103 ++++++++++++++++++++++---- tests/resources/CMakeLists.txt | 19 +++++ tests/resources/prikey.pem | 30 ++++++++ tests/resources/pubkey.pem | 9 +++ tests/test-helper.cpp | 72 ++++++++++++++++-- tests/test-helper.h | 3 + 12 files changed, 352 insertions(+), 127 deletions(-) create mode 100644 tests/resources/CMakeLists.txt create mode 100644 tests/resources/prikey.pem create mode 100644 tests/resources/pubkey.pem diff --git a/packaging/libwebappenc.spec b/packaging/libwebappenc.spec index 760f3e2..4184b84 100644 --- a/packaging/libwebappenc.spec +++ b/packaging/libwebappenc.spec @@ -117,3 +117,4 @@ fi %license LICENSE.BSL-1.0 %{bin_dir}/wae_tests %{_libdir}/libwae_tests_common.so* +%attr(660, %user_name, %group_name) %{rw_share_dir}/wae/test/app_dek/* diff --git a/srcs/key_handler.c b/srcs/key_handler.c index 905538e..d77016f 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -103,17 +103,17 @@ int _get_random(raw_buffer_s *rb) return WAE_ERROR_NONE; } -static const char *_get_dek_kek_pub_key_path() +const char *_get_dek_kek_pub_key_path() { return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PublicKey.pem"); } -static const char *_get_dek_kek_pri_key_path() +const char *_get_dek_kek_pri_key_path() { return tzplatform_mkpath4(TZ_SYS_SHARE, "wae", "app_dek", "WAE_APPDEK_KEK_PrivateKey.pem"); } -static const char *_get_dek_store_path() +const char *_get_dek_store_path() { return tzplatform_mkpath3(TZ_SYS_SHARE, "wae", "app_dek"); } @@ -188,6 +188,52 @@ error: return ret; } +static void _remove_file(const char *path) +{ + unlink(path); +} + +void _remove_directory(const char *path) +{ + char file_path_buff[MAX_PATH_LEN] = {0, }; + DIR *dir = opendir(path); + if (dir == NULL) { + if (errno == ENOENT) + WAE_SLOGI("directory is not exist already(%s)", path); + else + WAE_SLOGE("Failed to open dir(%s)", path); + + return; + } + + struct dirent entry; + struct dirent *result = NULL; + while (true) { + if (readdir_r(dir, &entry, &result) != 0) { + break; + } else if (result == NULL) { + break; + } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) { + continue; + } + + if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry.d_name) + < 0) + continue; + + if (entry.d_type == DT_DIR) { + _remove_directory(file_path_buff); + } else { + WAE_SLOGD("remove file(%s)", file_path_buff); + _remove_file(file_path_buff); + } + } + + WAE_SLOGD("remove directory(%s)", path); + closedir(dir); + rmdir(path); +} + int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path) { int ret = snprintf(path, size, "%s/%s_%s.adek", @@ -528,43 +574,53 @@ int _get_app_dek_kek(raw_buffer_s **pdek_kek) #endif } -int load_preloaded_app_deks(bool reload) +int load_preloaded_app_deks() { - int ret = WAE_ERROR_NONE; + WAE_SLOGI("load_preloaded_app_deks start"); - char pkg_id[MAX_PKGID_LEN] = {0, }; - char file_path_buff[MAX_PATH_LEN]; + int global_ret = WAE_ERROR_NONE; - if (!reload) { - // check if all deks were already loaded into key-manager. - ret = is_app_deks_loaded_in_key_manager(); + char pkg_id[MAX_PKGID_LEN] = {0, }; + char file_path_buff[MAX_PATH_LEN] = {0, }; - if (ret == true) - return WAE_ERROR_NONE; - } + const char *dek_store_path = _get_dek_store_path(); + const char *dek_kek_pub_key_path = _get_dek_kek_pub_key_path(); + const char *dek_kek_pri_key_path = _get_dek_kek_pri_key_path(); raw_buffer_s *prikey = NULL; - ret = _get_app_dek_kek(&prikey); + DIR *dir = NULL; - if (ret != WAE_ERROR_NONE) { - WAE_SLOGE("Fail to get APP_DEK_KEK Private Key"); - return ret; + // check if all deks were already loaded into key-manager. + // TODO: instead of checking key-manager, check based on file existance + dir = opendir(dek_store_path); + if (dir == NULL) { + if (errno == ENOENT) { + WAE_SLOGI( + "dek store doesn't exist. " + "It might be loading preloaded app deks already done"); + + return WAE_ERROR_NONE; + } else { + WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path); + global_ret = WAE_ERROR_FILE; + goto out; + } } - DIR *dir = opendir(_get_dek_store_path()); + global_ret = _get_app_dek_kek(&prikey); - if (dir == NULL) { - WAE_SLOGE("Fail to open dir. dir=%s", _get_dek_store_path()); - buffer_destroy(prikey); - return WAE_ERROR_FILE; + if (global_ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to get APP_DEK_KEK Private Key"); + goto out; } struct dirent entry; struct dirent *result = NULL; while (true) { + int ret = WAE_ERROR_NONE; if (readdir_r(dir, &entry, &result) != 0) { - ret = WAE_ERROR_FILE; + global_ret = WAE_ERROR_FILE; break; } @@ -573,43 +629,77 @@ int load_preloaded_app_deks(bool reload) 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) + if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) continue; - ret = snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", - _get_dek_store_path(), entry.d_name); - - if (ret < 0) { + if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", + dek_store_path, entry.d_name) < 0) { WAE_SLOGE("Failed to make file path by snprintf."); - ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ + global_ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ break; } + // skip for KEKs. They'll be deleted after all akek loaded to key-manager. + if (strcmp(file_path_buff, dek_kek_pub_key_path) == 0 || + strcmp(file_path_buff, dek_kek_pri_key_path) == 0) { + WAE_SLOGD("Skip KEK file...(%s)", file_path_buff); + continue; + } + + // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX + // clear all invalid cases silently + if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL) { + if (entry.d_type == DT_DIR) { + WAE_SLOGW( + "Invalid file in dek store(%s). Directory shouldn't be here.", + dek_store_path); + global_ret = WAE_ERROR_FILE; + } else { + WAE_SLOGW( + "Invalid file in dek store(%s). " + "Not regular file or prefix(%s) is invalid.", + dek_store_path, APP_DEK_FILE_PFX); + global_ret = WAE_ERROR_FILE; + } + + continue; + } + ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id); if (ret != WAE_ERROR_NONE) { WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s", file_path_buff); + global_ret = ret; continue; } ret = _load_preloaded_app_dek(prikey, file_path_buff, pkg_id); if (ret != WAE_ERROR_NONE && ret != WAE_ERROR_KEY_EXISTS) { WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret); + global_ret = ret; } else { WAE_SLOGI("Successfully load app dek(%s)", file_path_buff); - ret = WAE_ERROR_NONE; } } - buffer_destroy(prikey); - closedir(dir); +out: + if (prikey != NULL) + buffer_destroy(prikey); - if (ret != WAE_ERROR_NONE) - return ret; - else - return set_app_deks_loaded_to_key_manager(); + 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 global_ret; } int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type) diff --git a/srcs/key_handler.h b/srcs/key_handler.h index 791e149..f5ce3e4 100644 --- a/srcs/key_handler.h +++ b/srcs/key_handler.h @@ -41,6 +41,10 @@ int _get_random(raw_buffer_s *rb); 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, @@ -51,7 +55,7 @@ int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type); 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); -int load_preloaded_app_deks(bool reload); +int load_preloaded_app_deks(); #ifdef __cplusplus } diff --git a/srcs/key_manager.c b/srcs/key_manager.c index aeee748..ac42db2 100644 --- a/srcs/key_manager.c +++ b/srcs/key_manager.c @@ -32,7 +32,6 @@ #define MAX_ALIAS_LEN 256 #define APP_DEK_ALIAS_PFX "APP_DEK_" -#define APP_DEK_LOADING_DONE_ALIAS "APP_DEKS_LOADING_FINISHED" #define APP_DEK_KEK_ALIAS "WAE_APP_DEK_KEK" static int _to_wae_error(int key_manager_error) @@ -203,66 +202,6 @@ static void _get_alias(const char *name, UNUSED wae_app_type_e type, UNUSED bool name); } -static void _get_dek_loading_done_alias(char *alias, size_t buff_len) -{ - snprintf(alias, buff_len, "%s%s%s", - ckmc_owner_id_system, - ckmc_owner_id_separator, - APP_DEK_LOADING_DONE_ALIAS); -} - -bool is_app_deks_loaded_in_key_manager() -{ - char alias[MAX_ALIAS_LEN] = {0, }; - - _get_dek_loading_done_alias(alias, sizeof(alias)); - - ckmc_raw_buffer_s *buf = NULL; - int ret = _to_wae_error(ckmc_get_data(alias, NULL, &buf)); - - ckmc_buffer_free(buf); - - switch (ret) { - case WAE_ERROR_NONE: - return true; - case WAE_ERROR_NO_KEY: - WAE_SLOGI("app dek loading isn't done yet"); - return false; - default: - WAE_SLOGE("Failed to get dek loading flag data from key-manager. ret(%d)", ret); - return false; - } -} - -int set_app_deks_loaded_to_key_manager() -{ - unsigned char dummy_data[1] = {0}; - ckmc_raw_buffer_s buf; - buf.data = dummy_data; - buf.size = sizeof(dummy_data); - - ckmc_policy_s policy; - policy.password = NULL; - policy.extractable = true; - - char alias[MAX_ALIAS_LEN] = {0, }; - _get_dek_loading_done_alias(alias, sizeof(alias)); - - int ret = _to_wae_error(ckmc_save_data(alias, buf, policy)); - if (ret == WAE_ERROR_KEY_EXISTS) - ret = WAE_ERROR_NONE; - - return ret; -} - -int clear_app_deks_loaded_from_key_manager() -{ - char alias[MAX_ALIAS_LEN] = {0, }; - _get_dek_loading_done_alias(alias, sizeof(alias)); - - return _to_wae_error(ckmc_remove_alias(alias)); -} - int save_to_key_manager(const char *name, const char *pkg_id, wae_app_type_e type, const crypto_element_s *ce) { diff --git a/srcs/wae_initializer.c b/srcs/wae_initializer.c index 956b04d..f01c8e8 100644 --- a/srcs/wae_initializer.c +++ b/srcs/wae_initializer.c @@ -23,14 +23,9 @@ #include "web_app_enc.h" #include "wae_log.h" -int main(int argc, char *argv[]) +int main() { - bool reload = false; - - if (argc == 2 && strcmp(argv[1], "--reload") == 0) - reload = true; - - int ret = load_preloaded_app_deks(reload); + int ret = load_preloaded_app_deks(); if (ret == WAE_ERROR_NONE) { WAE_SLOGI("WAE INITIALIZER was finished successfully."); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7c9e2c9..07d2082 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -97,3 +97,5 @@ INSTALL(TARGETS ${TARGET_WAE_TEST} WORLD_READ WORLD_EXECUTE ) + +ADD_SUBDIRECTORY(resources) diff --git a/tests/internals.cpp b/tests/internals.cpp index 1fa9aff..7a13df7 100644 --- a/tests/internals.cpp +++ b/tests/internals.cpp @@ -24,7 +24,12 @@ #include #include +#include +#include +#include #include +#include +#include #include @@ -32,6 +37,7 @@ #include "crypto_service.h" #include "test-common.h" +#include "test-helper.h" namespace { @@ -76,7 +82,7 @@ crypto_element_s *_create_ce(void) return ce; } -} +} // namespace anonymous BOOST_AUTO_TEST_SUITE(SYSTEM) @@ -261,6 +267,15 @@ BOOST_AUTO_TEST_CASE(read_write_encrypted_app_dek) BOOST_REQUIRE(dek != nullptr); BOOST_REQUIRE(_get_random(dek) == WAE_ERROR_NONE); + // precondition + // dek store is removed after preloaded app deks loaded so dek store + // does not exists as default. To test write/read app dek test(they're working on + // dek store), dek store directory should be made + Wae::Test::restore_dek_store(); + // make unique_ptr to remove directory automatically + std::unique_ptr> scoped_store( + reinterpret_cast(1), [](void *) { Wae::Test::remove_dek_store(); }); + int ret = _write_encrypted_app_dek_to_file(pkg_id, dek); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to write_encrypted_app_dek_to_file. ec: " << ret); @@ -276,7 +291,7 @@ BOOST_AUTO_TEST_CASE(read_write_encrypted_app_dek) "readed(" << Wae::Test::bytes_to_hex(readed) << ")"); } -BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1) +BOOST_AUTO_TEST_CASE(cache_create_preloaded_app_dek) { const char *pkg_id = "TEST_PKG_ID_FOR_CREATE"; @@ -287,7 +302,22 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1) "preloaded app ce to create is already exist. ec: " << ret); const crypto_element_s *ce = nullptr; - ret = create_preloaded_app_ce(pkg_id, &ce); + + { + // precondition: + // for create_preloaded_app_ce, public key(kek) is needed + Wae::Test::restore_dummy_preloaded_app_dek_keks(); + // postcondition: + // get_preloaded_app_ce retrieves app ce from cache which is created on + // create_preloaded_app_ce so private key in dek store shouldn't be needed + // make unique_ptr to remove directory automatically + std::unique_ptr> scoped_store( + reinterpret_cast(1), [](void *) { Wae::Test::remove_dek_store(); }); + + // created preloaded app ce is just written in file, not into key-manager repo so + // no need to call remove_app_ce. + ret = create_preloaded_app_ce(pkg_id, &ce); + } BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to create_preloaded_app_ce. ec: " << ret); @@ -299,22 +329,21 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_1) BOOST_REQUIRE_MESSAGE(readed == ce, "cached ce address and actual is different!"); } -BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) +BOOST_AUTO_TEST_CASE(load_preloaded_app_dek) { + // steps + // 1) restore KEKs : restore_dummy_preloaded_app_dek_keks + // 2) create app deks based on KEK (public key) : create_preloaded_app_ce + // -> originally this step runs in image server so result(adek) is written to file + // 3) load preloaded app deks (.adek) in file : load_preloaded_app_deks + // -> After load, pri/pub key pair and adek in file is no longer needed so they're + // automatically cleared by load_preloaded_app_deks() + // 4) clear app deks from key-manager for remove it (associated to TEST_PKG_ID_*) + Wae::Test::restore_dummy_preloaded_app_dek_keks(); + const char *pkg_id1 = "TEST_PKGID_1"; const char *pkg_id2 = "TEST_PKGID_2"; - char path1[MAX_PATH_LEN] = {0, }; - char path2[MAX_PATH_LEN] = {0, }; - _get_preloaded_app_dek_file_path(pkg_id1, sizeof(path1), path1); - _get_preloaded_app_dek_file_path(pkg_id2, sizeof(path2), path2); - - // remove old test data - remove_app_ce(0, pkg_id1, WAE_PRELOADED_APP); - remove_app_ce(0, pkg_id2, WAE_PRELOADED_APP); - unlink(path1); - unlink(path2); - // create 2 ces for preloaded app const crypto_element_s *ce1 = nullptr; int ret = create_preloaded_app_ce(pkg_id1, &ce1); @@ -326,7 +355,7 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to create_preloaded_app_ce. ec: " << ret); - ret = load_preloaded_app_deks(true); + ret = load_preloaded_app_deks(); BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed to load_preloaded_app_deks. ec: " << ret); @@ -348,6 +377,48 @@ BOOST_AUTO_TEST_CASE(get_create_preloaded_app_dek_2) BOOST_REQUIRE_MESSAGE(ret == WAE_ERROR_NONE, "Failed remove app ce. ec: " << ret); } +BOOST_AUTO_TEST_CASE(load_preloaded_app_dek_tolerances) +{ + std::function does_dek_store_exist = []() { + if (DIR *dir = opendir(_get_dek_store_path())) { + closedir(dir); + return true; + } else if (errno != ENOENT) { + return true; + } else { + return false; + } + }; + + // without dek store directory + BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_NONE); + BOOST_REQUIRE(does_dek_store_exist() == false); + + // without kek(private key) + Wae::Test::restore_dek_store(); + BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_FILE); + BOOST_REQUIRE(does_dek_store_exist() == false); + + // with invalid file in dek store + Wae::Test::restore_dummy_preloaded_app_dek_keks(); + std::ofstream dst; + dst.exceptions(std::ofstream::failbit | std::ofstream::badbit); + dst.open(std::string(_get_dek_store_path()) + "/invalids", std::ofstream::binary); + dst << "touch invalid file to dek store"; + // std::ofstream destructor will call close automatically so no need to handle + // close in the exception cases + dst.close(); + BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_FILE); + BOOST_REQUIRE(does_dek_store_exist() == false); + + // with invalid directory in dek store + Wae::Test::restore_dummy_preloaded_app_dek_keks(); + std::string invalid_dir = std::string(_get_dek_store_path()) + "/invalid_dir"; + mkdir(invalid_dir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); + BOOST_REQUIRE(load_preloaded_app_deks() == WAE_ERROR_FILE); + BOOST_REQUIRE(does_dek_store_exist() == false); +} + BOOST_AUTO_TEST_SUITE_END() // INTERNALS BOOST_AUTO_TEST_SUITE_END() // SYSTEM diff --git a/tests/resources/CMakeLists.txt b/tests/resources/CMakeLists.txt new file mode 100644 index 0000000..fa0856f --- /dev/null +++ b/tests/resources/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (c) 2016 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. +# +INSTALL( + FILES pubkey.pem prikey.pem + DESTINATION ${RW_SHARE_DIR}/wae/test/app_dek + PERMISSIONS OWNER_READ +) diff --git a/tests/resources/prikey.pem b/tests/resources/prikey.pem new file mode 100644 index 0000000..e27950c --- /dev/null +++ b/tests/resources/prikey.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,F4C783D75B0679F29398E9A3CAB4733D + +kxgW1wGX3TZZ/wtv3g4AOLlZCHoQ6uXVQ0h2ofWjnJs8tas/alR6o8UBRIqCw44t +znUvQ8HlThvzhGgxje/yDDSxCy9mqhgsi2XeTtAeUbMhFL6UArb3cs6M4a37lYoT +llZdFyYkRWJ3vRS33TDrhXDV6GjZWQ05SJ0OYdPJsmA1ENwdH+5NE/xLnqLdTtWr +O3Mn2vi6P9CVqZroCvYBzUaypGcmFhjTIbWmB6inXjoXyddzerh7PTDBDWWacBab +C7gcZC5SrK5YOt6f54ANsVQO8jnkLDx95gUSHYthX1hrQ3Da5Gb6nfYP9RNrHCum +O8RKxSOvv8zwbMlzqtld8xCOb7Nh04f8bofrzZVLZ0T92FcyFQmt1F4U6DNQqHsn +AAqxRxUWsC5k2dX9uZ6RCpEzNYWyPvNe24I/Kt01Geoh1NtCns8CVZcrxyMMtZRK +ZJnYhvNDXDQCDtMJjRBiEXXE++AdA2O6uFoGX3alKwtxAIjGI++pSRlz1GTps26x +5mmLil5wb3KGBfMN4L0R0heDOeiPQrNv7CwX8OlHtA1OKFBtViWdd/uZ2hAko1Tz +YkoYpHPQOV5LZ7dem/XNnwwel9g6AkHhLNJv5ih4Y0CQfPBSs+iiLbMHh/NaGDD9 ++kbcf5Lk4FQGVbJDW9nDAXT6jjMyliTI+hIh5fM2k22qbq6OqBkW6EbOQDMP/R2P +LhFqTgHceNt0mqpcDJdJQ0YKbxVpdkv5f1C4rW+pgUEeHDCQ7vPe4p44xQJ/Z/7Y +AtPwPKzPPJze2cfoUkZd9jXN9g2v2555xnQZU78IEm1nPVBA+hLIaqN1hu1Lkzxy +CwFNo7bMVh3FSBmZVtJlcLsyLxZ9UdoaSr+anfA0lWJPiBzE0whQljZp56l1rL1V +1K8m/dc9rLJ3uDQmYoSRmBZG5zZlVWCip+R9VAHMxRi1x29dFk1jbtQscr63dMI8 +0eOUf28Mw719WWUZVzD08b431DPqWiqrpexUKEXPW8EsrINPfIg180QYt1VUoshs +Tqi/LKM0OV6nlMGh9ieCK8WzVDW8F16krSLo6eJpIPYPZgkHE7fC7Jws1kpUrSnF +GgT6rBA97tJ0EalinuFXbip1X087Quz5USURq18f7/B6nFu0Kd4GhlICsR24j3eB +75SsTNmfUcko8s5QT4rwONEwtRffkGbbNEisCPcleJV68zHvN58mfD7Dl8W3zIO4 +Qk6B1Xy0C4EEniKFfjxIaMEaxrqntBIc+nZE6/+UoGp/Hj9r5ZdzQX2j4837IIdR +CxT4tjXiWBA6u3WaLAZUSM0W0SEORUF9NwzlId1b8A3WxA8XewhAKPaJEr677vzZ +083+neUOuXqqs597romLH1omuffxmHxBzmP+koUtemP78XxCBVWUAB1T+fBRJMz6 +9ZEgDWrMntJ1IaFoGdOWZELgwcXJ0KwWFuk+sieZ5WCCzNmFli9WPN/xSqwmdYw6 +RK9er5Vc8D9mAlmGlz2mpAmzNJHH30zYKT/d0XzBS8z6WBRthaTS3NLsiSeWdELH +b5+WEMOiKvZ19AXU2unHw/XpeVnAISOHhumAqFCwXkjVoMt8LMDawt6ra8N8G+gD +-----END RSA PRIVATE KEY----- diff --git a/tests/resources/pubkey.pem b/tests/resources/pubkey.pem new file mode 100644 index 0000000..f0dfcea --- /dev/null +++ b/tests/resources/pubkey.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0kWtjpRO7Zh2KX2naVE/ +BDJdrfwK9xexfNA0MkY2VJ4J2AKMYTj1D1jntceryupCEHOvP3rum+WsFvPXduz9 ++VKnSsSqj4jcTUubtpDUGA5G79IqLEPFuSBaqI8Uwkzd08pE+s30oaJDnNazMhSq +8JkqBPoCCwtUs73ruE9VbtsBO/kTlASIAfe8nXqcJLcDQgWYhizjJw0Pi6d74oCw +S2OTvQDNvsXfFnA0ZJEEYw/rZLirj7OHoOjz+Sh5N+1uA3Up6SPPEbHuP6L12Yxq +Hdy7gnJXodLhvE/cR4SN9VW7+qmCMBjmLkBejGrEX3STS9sLI7MZHu9Y26dwuYb4 ++wIDAQAB +-----END PUBLIC KEY----- diff --git a/tests/test-helper.cpp b/tests/test-helper.cpp index d0ca263..b7fdf6a 100644 --- a/tests/test-helper.cpp +++ b/tests/test-helper.cpp @@ -22,6 +22,9 @@ #include #include +#include +#include +#include #include "web_app_enc.h" #include "key_handler.h" @@ -37,6 +40,25 @@ namespace { const uid_t UID_OWNER = 5001; +void copy_file(const char *src_path, const char *dst_path) +{ + std::ifstream src; + std::ofstream dst; + + src.exceptions(std::ifstream::failbit | std::ifstream::badbit); + dst.exceptions(std::ofstream::failbit | std::ofstream::badbit); + + src.open(src_path, std::ifstream::binary); + dst.open(dst_path, std::ofstream::binary); + + dst << src.rdbuf(); + + // std::ofstream destructor will call close automatically so no need to handle + // close in the exception cases + src.close(); + dst.close(); +} + } // namespace anonymous void add_get_remove_ce(wae_app_type_e app_type) @@ -123,15 +145,29 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) else wae_remove_global_app_dek(pkg_id, app_type == WAE_PRELOADED_APP); - if (app_type == WAE_PRELOADED_APP) - clear_app_deks_loaded_from_key_manager(); - std::vector plaintext = { 'a', 'b', 'c', 'a', 'b', 'c', 'x', 'y', 'o', 'q', '2', 'e', 'v', '0', '1', 'x' }; - // test for downloaded web application + // precondition for preloaded app: + // for preloaded app encryption, preloaded app dek kek(pub) is needed. + // dek store is removed after preloaded app deks loaded so dek store + // does not exists as default. To test encrypt/decrypt(write/read ce) app test, + // dek store directory should be made. + std::unique_ptr> scoped_store( + reinterpret_cast(1), [](void *ptr) { + if (ptr == reinterpret_cast(1)) + return; + else + remove_dek_store(); // remove dek store automatically in case of error + }); + + if (app_type == WAE_PRELOADED_APP) { + restore_dummy_preloaded_app_dek_keks(); + scoped_store.reset(reinterpret_cast(2)); + } + unsigned char *_encrypted = nullptr; size_t _enc_len = 0; int tmp = 0; @@ -171,7 +207,7 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) } if (app_type == WAE_PRELOADED_APP) - load_preloaded_app_deks(true); + load_preloaded_app_deks(); unsigned char *_decrypted = nullptr; size_t _dec_len = 0; @@ -201,5 +237,31 @@ void encrypt_decrypt_web_app(wae_app_type_e app_type) "Failed to wae_remove_app_dek. ec: " << tmp); } +void restore_dek_store() +{ + mkdir( + _get_dek_store_path(), + S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP); +} + +void remove_dek_store() +{ + _remove_directory(_get_dek_store_path()); +} + +void restore_dummy_preloaded_app_dek_keks() +{ + // Generate pri/pub key pair. Private key is protected + // with assigned password: APP_DEK_KEK_PRIKEY_PASSWORD) which is same to password + // of real private key because it's built in source of srcs/key_handler.c + // It should be removed after private key goes into key-manager initial-value. + restore_dek_store(); + + copy_file("/opt/share/wae/test/app_dek/prikey.pem", _get_dek_kek_pri_key_path()); + copy_file("/opt/share/wae/test/app_dek/pubkey.pem", _get_dek_kek_pub_key_path()); + + BOOST_MESSAGE("copying dummy pri/pub key pair to dek store done"); +} + } // namespace Test } // namespace Wae diff --git a/tests/test-helper.h b/tests/test-helper.h index b4d1f42..cd2fae2 100644 --- a/tests/test-helper.h +++ b/tests/test-helper.h @@ -29,5 +29,8 @@ void add_get_remove_ce(wae_app_type_e app_type); void create_app_ce(wae_app_type_e app_type); void encrypt_decrypt_web_app(wae_app_type_e app_type); +void remove_dek_store(); +void restore_dek_store(); +void restore_dummy_preloaded_app_dek_keks(); } // namespace Test } // namespace Wae -- 2.7.4 From 9fddab9e58ccd9acdecdbfcf12770c50feac4d2b Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Thu, 8 Dec 2016 10:12:11 +0900 Subject: [PATCH 14/16] Refine directory traversing: registering callback There's two part of directory traversing(removing all files in directory and loading preloaded app deks). So duplicated code can be compressed to traverse_directory with entry callback registered. Change-Id: I654bed7f3b4efff75b2853fceb3f9d97b51a85b5 Signed-off-by: Kyungwook Tak --- srcs/key_handler.c | 218 +++++++++++++++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 108 deletions(-) diff --git a/srcs/key_handler.c b/srcs/key_handler.c index d77016f..cdc96af 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -188,61 +188,87 @@ error: return ret; } -static void _remove_file(const char *path) +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) { - unlink(path); -} - -void _remove_directory(const char *path) -{ - char file_path_buff[MAX_PATH_LEN] = {0, }; DIR *dir = opendir(path); if (dir == NULL) { - if (errno == ENOENT) - WAE_SLOGI("directory is not exist already(%s)", path); - else + if (errno == ENOENT) { + // it's not error for current cases of using traverse_directory. + // To open dek store directory for load/remove can be occured in some + // exception(or attacked) cases but we can just ignore it if it isn't the + // first time call load_preloaded_app_deks. + WAE_SLOGI("directory isn't exist(%s).", path); + return WAE_ERROR_NONE; + } else { WAE_SLOGE("Failed to open dir(%s)", path); - - return; + return WAE_ERROR_FILE; + } } + int ret = WAE_ERROR_NONE; struct dirent entry; struct dirent *result = NULL; while (true) { if (readdir_r(dir, &entry, &result) != 0) { + WAE_SLOGE("readdir_r error on dir(%s) errno(%d)", path, errno); break; } else if (result == NULL) { - break; + break; // end of directory } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) { continue; } - if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry.d_name) - < 0) - continue; + int _ret = ecb(path, result, user_data); + if (_ret != WAE_ERROR_NONE) + ret = _ret; + } - if (entry.d_type == DT_DIR) { - _remove_directory(file_path_buff); - } else { - WAE_SLOGD("remove file(%s)", file_path_buff); - _remove_file(file_path_buff); - } + closedir(dir); + return ret; +} + +static void _remove_file(const char *path) +{ + unlink(path); +} + +static int _entry_callback_remove_all( + const char *path, const struct dirent *entry, void *user_data) +{ + (void) user_data; // TODO: use UNUSED macro + + char file_path_buff[MAX_PATH_LEN] = {0, }; + if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0) + return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ + + int ret = WAE_ERROR_NONE; + if (entry->d_type == DT_DIR) { + int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all, NULL); + if (_ret != WAE_ERROR_NONE) + ret = _ret; + rmdir(file_path_buff); + } else { + _remove_file(file_path_buff); } + return ret; +} + +void _remove_directory(const char *path) +{ + traverse_directory(path, _entry_callback_remove_all, NULL); WAE_SLOGD("remove directory(%s)", path); - closedir(dir); rmdir(path); } int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path) { - int ret = snprintf(path, size, "%s/%s_%s.adek", - _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id); - - if (ret < 0) + if (snprintf(path, size, "%s/%s_%s.adek", + _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id) < 0) return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ - - return WAE_ERROR_NONE; + else + return WAE_ERROR_NONE; } static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id) @@ -574,18 +600,56 @@ int _get_app_dek_kek(raw_buffer_s **pdek_kek) #endif } -int load_preloaded_app_deks() +static int _entry_callback_load_preloaded_adeks( + const char *path, const struct dirent *entry, void *prikey) { - WAE_SLOGI("load_preloaded_app_deks start"); + 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 (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0) + 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 */ - int global_ret = WAE_ERROR_NONE; + if (entry->d_type != DT_REG || strstr(entry->d_name, APP_DEK_FILE_PFX) == NULL) { + if (entry->d_type == DT_DIR) + WAE_SLOGW( + "Invalid file in dek store(%s). Directory shouldn't be here.", path); + else + WAE_SLOGW( + "Invalid file in dek store(%s). " + "Not regular file or prefix(%s) is invalid.", path, APP_DEK_FILE_PFX); + + return WAE_ERROR_FILE; + } char pkg_id[MAX_PKGID_LEN] = {0, }; - char file_path_buff[MAX_PATH_LEN] = {0, }; + int ret = _extract_pkg_id_from_file_name(entry->d_name, pkg_id); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGW("Failed to extract pkgid from file(%s). It will be ignored.", file_path_buff); + return ret; + } + + ret = _load_preloaded_app_dek((raw_buffer_s *)prikey, 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; + } else { + WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret); + return ret; + } +} + +int load_preloaded_app_deks() +{ + WAE_SLOGI("load_preloaded_app_deks start"); + + int ret = WAE_ERROR_NONE; const char *dek_store_path = _get_dek_store_path(); - const char *dek_kek_pub_key_path = _get_dek_kek_pub_key_path(); - const char *dek_kek_pri_key_path = _get_dek_kek_pri_key_path(); raw_buffer_s *prikey = NULL; DIR *dir = NULL; @@ -602,86 +666,24 @@ int load_preloaded_app_deks() return WAE_ERROR_NONE; } else { WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path); - global_ret = WAE_ERROR_FILE; + ret = WAE_ERROR_FILE; goto out; } } - global_ret = _get_app_dek_kek(&prikey); - - if (global_ret != WAE_ERROR_NONE) { - WAE_SLOGE("Fail to get APP_DEK_KEK Private Key"); + 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; } - struct dirent entry; - struct dirent *result = NULL; - - while (true) { - int ret = WAE_ERROR_NONE; - if (readdir_r(dir, &entry, &result) != 0) { - global_ret = WAE_ERROR_FILE; - break; - } - - // readdir_r returns NULL in *result if the end - // of the directory stream is reached - if (result == NULL) - break; - - if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) - continue; - - if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", - dek_store_path, entry.d_name) < 0) { - WAE_SLOGE("Failed to make file path by snprintf."); - global_ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ - break; - } - - // skip for KEKs. They'll be deleted after all akek loaded to key-manager. - if (strcmp(file_path_buff, dek_kek_pub_key_path) == 0 || - strcmp(file_path_buff, dek_kek_pri_key_path) == 0) { - WAE_SLOGD("Skip KEK file...(%s)", file_path_buff); - continue; - } - - // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX - // clear all invalid cases silently - if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL) { - if (entry.d_type == DT_DIR) { - WAE_SLOGW( - "Invalid file in dek store(%s). Directory shouldn't be here.", - dek_store_path); - global_ret = WAE_ERROR_FILE; - } else { - WAE_SLOGW( - "Invalid file in dek store(%s). " - "Not regular file or prefix(%s) is invalid.", - dek_store_path, APP_DEK_FILE_PFX); - global_ret = WAE_ERROR_FILE; - } - - continue; - } - - ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id); - - if (ret != WAE_ERROR_NONE) { - WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s", - file_path_buff); - global_ret = ret; - continue; - } + // close dek store dir fd not to affect the traverse_directory call + closedir(dir); + dir = NULL; - ret = _load_preloaded_app_dek(prikey, file_path_buff, pkg_id); - if (ret != WAE_ERROR_NONE && ret != WAE_ERROR_KEY_EXISTS) { - WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret); - global_ret = ret; - } else { - WAE_SLOGI("Successfully load app dek(%s)", file_path_buff); - } - } + ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks, prikey); + if (ret != WAE_ERROR_NONE) + WAE_SLOGE("Fail when traverse dek store directory. ret(%d)", ret); out: if (prikey != NULL) @@ -699,7 +701,7 @@ out: // initializer service failure. _remove_directory(dek_store_path); - return global_ret; + return ret; } int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type) -- 2.7.4 From 66e03d5f1993d5bdf9c0c0b778afdf99eefff847 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Tue, 20 Dec 2016 19:49:27 +0900 Subject: [PATCH 15/16] Replace deprecated readdir_r with readdir Change-Id: Ic5649cafedfcb3a91c839c33f261c6da7475a9a9 Signed-off-by: Kyungwook Tak --- srcs/key_handler.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/srcs/key_handler.c b/srcs/key_handler.c index cdc96af..c5a2f95 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -207,15 +208,15 @@ static int traverse_directory(const char *path, entry_callback ecb, void *user_d } int ret = WAE_ERROR_NONE; - struct dirent entry; - struct dirent *result = NULL; while (true) { - if (readdir_r(dir, &entry, &result) != 0) { - WAE_SLOGE("readdir_r error on dir(%s) errno(%d)", path, errno); + errno = 0; + struct dirent *result = readdir(dir); + if (result == NULL) { + if (errno != 0) + WAE_SLOGE("readdir error on dir(%s) errno(%d)", path, errno); break; - } else if (result == NULL) { - break; // end of directory - } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) { + } else if (strcmp(result->d_name, ".") == 0 || + strcmp(result->d_name, "..") == 0) { continue; } -- 2.7.4 From 0eecf5c7803707224969d71a7ca3c06838b787bd Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Fri, 12 May 2017 14:11:02 +0900 Subject: [PATCH 16/16] Fix log fomatter according to boost version upgrade Change-Id: I45ebc7ad1e47ae1c6be71be50a50d5ad4a1330c9 Signed-off-by: sangwan.kwon --- tests/colour_log_formatter.cpp | 112 ++++++++++++++++++++++++++++++++++++----- tests/colour_log_formatter.h | 10 ++++ tests/test-helper.h | 5 ++ 3 files changed, 115 insertions(+), 12 deletions(-) diff --git a/tests/colour_log_formatter.cpp b/tests/colour_log_formatter.cpp index 50bd43c..087951f 100644 --- a/tests/colour_log_formatter.cpp +++ b/tests/colour_log_formatter.cpp @@ -14,7 +14,12 @@ #include #include +#include +#if BOOST_VERSION >= 105900 +#include +#else #include +#endif #include #include #include @@ -37,11 +42,29 @@ const char *BOLD_YELLOW_BEGIN = "\033[1;33m"; const char *COLOR_END = "\033[m"; const_string +test_unit_type_name(const test_unit &tu) +{ +#if BOOST_VERSION >= 105900 + return const_string(tu.p_type_name); +#else + return tu.p_type_name.get(); +#endif +} + +const_string +test_unit_name(const test_unit &tu) +{ +#if BOOST_VERSION >= 105900 + return const_string(tu.p_name); +#else + return tu.p_name.get(); +#endif +} + +const_string test_phase_identifier() { - return framework::is_initialized() - ? const_string(framework::current_test_case().p_name.get()) - : BOOST_TEST_L("Test setup"); + return test_unit_name(framework::current_test_case()); } const_string @@ -56,6 +79,12 @@ get_basename(const std::string &file_name) return basename(file_name.c_str()); } +bool +test_unit_type_name_contains(const test_unit &tu, const std::string &substr) +{ + return test_unit_type_name(tu).find(const_string(substr)) == 0; +} + } // local namespace //____________________________________________________________________________// @@ -98,11 +127,12 @@ colour_log_formatter::test_unit_start( std::ostream &output, test_unit const &tu) { - if (tu.p_type_name->find(const_string("suite")) == 0) - output << "Starting test " << tu.p_type_name << " \"" << tu.p_name << "\"" << - std::endl; - else - output << "Running test " << tu.p_type_name << " \"" << tu.p_name << "\"" << + if (test_unit_type_name_contains(tu, "suite")) { + output << "Starting test "; + } else { + output << "Running test "; + } + output << test_unit_type_name(tu) << " \"" << test_unit_name(tu) << "\"" << std::endl; } @@ -114,8 +144,8 @@ colour_log_formatter::test_unit_finish( test_unit const &tu, unsigned long elapsed) { - if (tu.p_type_name->find(const_string("suite")) == 0) { - output << "Finished test " << tu.p_type_name << " \"" << tu.p_name << "\"" << + if (test_unit_type_name_contains(tu, "suite")) { + output << "Finished test " << test_unit_type_name(tu) << " \"" << test_unit_name(tu) << "\"" << std::endl; return; } @@ -152,8 +182,8 @@ colour_log_formatter::test_unit_skipped( std::ostream &output, test_unit const &tu) { - output << "Test " << tu.p_type_name << " \"" << tu.p_name << "\"" << - "is skipped" << std::endl; + output << "Test " << test_unit_type_name(tu) << " \"" << test_unit_name(tu) + << "\"" << "is skipped" << std::endl; } //____________________________________________________________________________// @@ -187,6 +217,41 @@ colour_log_formatter::log_exception( m_isTestCaseFailed = true; } +void +colour_log_formatter::log_exception_start( + std::ostream &output, + log_checkpoint_data const &checkpoint_data, + boost::execution_exception const &ex) +{ + boost::execution_exception::location const &loc = ex.where(); + output << '\t' << BOLD_YELLOW_BEGIN << get_basename(loc.m_file_name) + << '(' << loc.m_line_num << "), "; + + output << "fatal error in \"" + << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function) << + "\": "; + + output << COLOR_END << ex.what(); + + if (!checkpoint_data.m_file_name.is_empty()) { + output << '\n'; + output << "\tlast checkpoint : " << get_basename(checkpoint_data.m_file_name) + << '(' << checkpoint_data.m_line_num << ")"; + + if (!checkpoint_data.m_message.empty()) + output << ": " << checkpoint_data.m_message; + } + + output << std::endl; + m_isTestCaseFailed = true; +} + +void +colour_log_formatter::log_exception_finish(std::ostream &os) +{ + os.flush(); +} + //____________________________________________________________________________// void @@ -260,6 +325,29 @@ colour_log_formatter::log_entry_finish( //____________________________________________________________________________// +void +colour_log_formatter::entry_context_start( + std::ostream& output, + boost::unit_test::log_level l) +{ + output << (l == log_successful_tests ? "\nAssertion" : "\nFailure") + << " occurred in a following context:"; +} + +void +colour_log_formatter::log_entry_context( + std::ostream& output, + boost::unit_test::const_string value) +{ + output << "\n " << value; +} + +void +colour_log_formatter::entry_context_finish(std::ostream& output) +{ + output.flush(); +} + //____________________________________________________________________________// } // namespace Test } // namespace Wae diff --git a/tests/colour_log_formatter.h b/tests/colour_log_formatter.h index 7c5dee3..968f6be 100644 --- a/tests/colour_log_formatter.h +++ b/tests/colour_log_formatter.h @@ -41,6 +41,11 @@ public: std::ostream &, boost::unit_test::log_checkpoint_data const &, boost::execution_exception const &ex); + void log_exception_start( + std::ostream &, + boost::unit_test::log_checkpoint_data const &, + boost::execution_exception const &ex); + void log_exception_finish(std::ostream &os); void log_entry_start( std::ostream &, @@ -54,6 +59,11 @@ public: boost::unit_test::lazy_ostream const &value); void log_entry_finish(std::ostream &); + void entry_context_start(std::ostream& os, boost::unit_test::log_level l); + void log_entry_context(std::ostream& os, + boost::unit_test::const_string value); + void entry_context_finish(std::ostream& os); + private: bool m_isTestCaseFailed; }; diff --git a/tests/test-helper.h b/tests/test-helper.h index cd2fae2..8ec45c0 100644 --- a/tests/test-helper.h +++ b/tests/test-helper.h @@ -22,6 +22,11 @@ #include "types.h" +#ifndef BOOST_MESSAGE +#include +#define BOOST_MESSAGE(x) std::cout << x << std::endl; +#endif + namespace Wae { namespace Test { -- 2.7.4