summaryrefslogtreecommitdiff
path: root/srcs/decrypt_migrated_wgt.c
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/decrypt_migrated_wgt.c')
-rw-r--r--srcs/decrypt_migrated_wgt.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/srcs/decrypt_migrated_wgt.c b/srcs/decrypt_migrated_wgt.c
new file mode 100644
index 0000000..d240fa4
--- /dev/null
+++ b/srcs/decrypt_migrated_wgt.c
@@ -0,0 +1,185 @@
+/*
+ * 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 decrypt_migrated_wgt.c
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Restore old encryption key for removed secure-storage
+ */
+#include "decrypt_migrated_wgt.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#include <openssl/evp.h>
+#include <openssl/crypto.h>
+
+#include "wae_log.h"
+#include "web_app_enc.h"
+
+#define DUK_LEN 16
+
+static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_len)
+{
+ 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.");
+ return WAE_ERROR_MEMORY;
+ }
+
+ PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1, (DUK_LEN * 2), duk);
+ duk[DUK_LEN * 2] = '\0';
+
+ *pduk = duk;
+ *pduk_len = DUK_LEN;
+
+ WAE_SLOGD("get old duk of length: %d", *pduk_len);
+
+ return WAE_ERROR_NONE;
+}
+
+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));
+ if (iv == NULL)
+ return WAE_ERROR_MEMORY;
+
+ memcpy(iv, iv_buf, sizeof(iv_buf));
+
+ *piv = iv;
+ *piv_len = iv_len;
+
+ WAE_SLOGD("get old iv of length: %d", *piv_len);
+
+ 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)
+{
+ if (key == NULL || iv == NULL || data == NULL || pdecrypted == NULL ||
+ pdecrypted_len == 0)
+ return WAE_ERROR_INVALID_PARAMETER;
+
+ if (key_len != 16 || iv_len < 16) {
+ 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;
+ }
+
+ 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 final_len = 0;
+
+ unsigned char *decrypted = (unsigned char *)calloc(tmp_len, 1);
+
+ if (decrypted == NULL)
+ return WAE_ERROR_MEMORY;
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ int ret = EVP_CipherInit(&ctx, algo, key, iv, 0);
+
+ if (ret != 1) {
+ ret = WAE_ERROR_CRYPTO;
+ goto error;
+ }
+
+ ret = EVP_CIPHER_CTX_set_padding(&ctx, 1);
+
+ if (ret != 1) {
+ ret = WAE_ERROR_CRYPTO;
+ goto error;
+ }
+
+ ret = EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len);
+
+ if (ret != 1) {
+ ret = WAE_ERROR_CRYPTO;
+ goto error;
+ } else if (decrypted_len <= 0) {
+ ret = WAE_ERROR_CRYPTO;
+ goto error;
+ }
+
+ ret = EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len);
+
+ if (ret != 1) {
+ ret = WAE_ERROR_CRYPTO;
+ goto error;
+ } else if (final_len <= 0) {
+ ret = WAE_ERROR_CRYPTO;
+ goto error;
+ }
+
+ *pdecrypted = decrypted;
+ *pdecrypted_len = decrypted_len + final_len;
+
+ ret = WAE_ERROR_NONE;
+
+error:
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ 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)
+{
+ unsigned char *duk = NULL;
+ size_t duk_len = 0;
+ int ret = _get_old_duk(pkg_id, &duk, &duk_len);
+
+ if (ret != WAE_ERROR_NONE)
+ return ret;
+
+ unsigned char *iv = NULL;
+ size_t iv_len = 0;
+ ret = _get_old_iv(duk, duk_len, &iv, &iv_len);
+
+ if (ret != WAE_ERROR_NONE)
+ goto error;
+
+ ret = _decrypt(duk, duk_len, iv, iv_len, encrypted, encrypted_len, pdecrypted, pdecrypted_len);
+
+ WAE_SLOGI("decrypt with old ss algo success of pkg: %s", pkg_id);
+
+error:
+ free(duk);
+ free(iv);
+
+ return WAE_ERROR_NONE;
+}