diff options
Diffstat (limited to 'srcs')
-rw-r--r-- | srcs/CMakeLists.txt | 2 | ||||
-rw-r--r-- | srcs/crypto_service.c | 187 | ||||
-rw-r--r-- | srcs/crypto_service.h | 25 | ||||
-rw-r--r-- | srcs/decrypt_migrated_wgt.c | 141 | ||||
-rw-r--r-- | srcs/decrypt_migrated_wgt.h | 16 | ||||
-rw-r--r-- | srcs/key_handler.c | 710 | ||||
-rw-r--r-- | srcs/key_handler.h | 38 | ||||
-rw-r--r-- | srcs/key_manager.c | 393 | ||||
-rw-r--r-- | srcs/key_manager.h | 46 | ||||
-rw-r--r-- | srcs/types.c | 255 | ||||
-rw-r--r-- | srcs/types.h | 65 | ||||
-rw-r--r-- | srcs/web_app_enc.c | 98 |
12 files changed, 1279 insertions, 697 deletions
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 <stddef.h> +#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 <stddef.h> +#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 <dirent.h> #include <unistd.h> -#include <ckmc/ckmc-manager.h> #include <tzplatform_config.h> #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 <stdbool.h> #include <stddef.h> + #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 <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <ckmc/ckmc-manager.h> + +#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 <stdbool.h> + +#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 <stdlib.h> +#include <string.h> + +#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 <stdbool.h> +#include <stddef.h> + +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); } |