2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file decrypt_migrated_wgt.c
18 * @author Kyungwook Tak (k.tak@samsung.com)
20 * @brief Restore old encryption key for removed secure-storage
22 #include "decrypt_migrated_wgt.h"
27 #include <openssl/hmac.h>
28 #include <openssl/sha.h>
29 #include <openssl/evp.h>
30 #include <openssl/crypto.h>
31 #include <openssl/err.h>
34 #include "web_app_enc.h"
38 static void _logging_openssl_err()
40 unsigned long e = ERR_get_error();
41 char buf[512] = {0, };
43 ERR_error_string_n(e, buf, 511);
45 WAE_SLOGE("Openssl err: %s", buf);
48 static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_len)
50 unsigned char salt[32];
52 memset(salt, 0xFF, sizeof(salt));
54 unsigned char *duk = (unsigned char *)malloc(sizeof(unsigned char) * ((DUK_LEN * 2) + 1));
56 WAE_SLOGE("Failed to allocate memory for old duk.");
57 return WAE_ERROR_MEMORY;
60 if (PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1,
61 (DUK_LEN * 2), duk) != 1) {
63 return WAE_ERROR_CRYPTO;
66 duk[DUK_LEN * 2] = '\0';
71 WAE_SLOGD("get old duk of length: %d", *pduk_len);
73 return WAE_ERROR_NONE;
76 static int _get_old_iv(const unsigned char *src, size_t src_len, unsigned char **piv, size_t *piv_len)
78 unsigned int iv_len = SHA_DIGEST_LENGTH;
79 unsigned char *iv = (unsigned char *)malloc(sizeof(unsigned char) * iv_len);
81 return WAE_ERROR_MEMORY;
83 if (EVP_Digest(src, src_len, iv, &iv_len, EVP_sha1(), NULL) != 1) {
85 return WAE_ERROR_CRYPTO;
91 WAE_SLOGD("get old iv of length: %d", *piv_len);
93 return WAE_ERROR_NONE;
96 static int _decrypt(const unsigned char *key, size_t key_len,
97 const unsigned char *iv, size_t iv_len,
98 const unsigned char *data, size_t data_len,
99 unsigned char **pdecrypted, size_t *pdecrypted_len)
101 if (key == NULL || iv == NULL || data == NULL || pdecrypted == NULL ||
103 return WAE_ERROR_INVALID_PARAMETER;
105 if (key_len != 16 || iv_len < 16) {
106 WAE_SLOGE("Invalid key or iv size for decrypt by aes_128_cbc algorithm. "
107 "key should be 16 bytes and iv should be bigger than 16 bytes");
108 return WAE_ERROR_INVALID_PARAMETER;
111 const struct evp_cipher_st *algo = EVP_aes_128_cbc();
115 size_t tmp_len = (data_len / algo->block_size + 1) * algo->block_size;
116 int decrypted_len = 0;
119 unsigned char *decrypted = (unsigned char *)calloc(tmp_len, 1);
121 if (decrypted == NULL)
122 return WAE_ERROR_MEMORY;
124 EVP_CIPHER_CTX_init(&ctx);
126 int ret = WAE_ERROR_NONE;
128 if (EVP_CipherInit(&ctx, algo, key, iv, 0) != 1) {
129 ret = WAE_ERROR_CRYPTO;
133 if (EVP_CIPHER_CTX_set_padding(&ctx, 1) != 1) {
134 ret = WAE_ERROR_CRYPTO;
138 if (EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len) != 1) {
139 ret = WAE_ERROR_CRYPTO;
141 } else if (decrypted_len <= 0) {
142 WAE_SLOGE("EVP_CipherUpdate success but returned decrypted_len(%d) <= 0",
144 ret = WAE_ERROR_UNKNOWN;
148 if (EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len) != 1) {
149 ret = WAE_ERROR_CRYPTO;
151 } else if (final_len <= 0) {
152 WAE_SLOGE("EVP_CipherFinal success but returned final_len(%d) <= 0",
154 ret = WAE_ERROR_UNKNOWN;
158 *pdecrypted = decrypted;
159 *pdecrypted_len = decrypted_len + final_len;
162 EVP_CIPHER_CTX_cleanup(&ctx);
164 if (ret != WAE_ERROR_NONE)
170 int decrypt_by_old_ss_algo(const char *pkg_id, const unsigned char *encrypted, size_t encrypted_len,
171 unsigned char **pdecrypted, size_t *pdecrypted_len)
173 unsigned char *duk = NULL;
175 unsigned char *iv = NULL;
178 int ret = _get_old_duk(pkg_id, &duk, &duk_len);
180 if (ret != WAE_ERROR_NONE)
183 ret = _get_old_iv(duk, duk_len, &iv, &iv_len);
185 if (ret != WAE_ERROR_NONE)
188 ret = _decrypt(duk, duk_len, iv, iv_len, encrypted, encrypted_len, pdecrypted, pdecrypted_len);
190 WAE_SLOGI("decrypt with old ss algo success of pkg: %s", pkg_id);
193 if (ret == WAE_ERROR_CRYPTO)
194 _logging_openssl_err();
199 return WAE_ERROR_NONE;