2 * Copyright (c) 2016 - 2019 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, raw_buffer_s **pduk)
50 if (pkg_id == NULL || pduk == NULL)
51 return WAE_ERROR_INVALID_PARAMETER;
53 unsigned char salt[32];
55 memset(salt, 0xFF, sizeof(salt));
57 raw_buffer_s *duk = buffer_create(DUK_SIZE * 2);
59 return WAE_ERROR_MEMORY;
61 if (PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1,
62 duk->size, duk->buf) != 1) {
64 return WAE_ERROR_CRYPTO;
71 WAE_SLOGD("get old duk of length: %zu", duk->size);
73 return WAE_ERROR_NONE;
76 static int _get_old_iv(const raw_buffer_s *src, raw_buffer_s **piv)
78 if (!is_buffer_valid(src) || piv == NULL)
79 return WAE_ERROR_INVALID_PARAMETER;
81 raw_buffer_s *iv = buffer_create(SHA_DIGEST_LENGTH);
83 return WAE_ERROR_MEMORY;
86 if (EVP_Digest(src->buf, src->size, iv->buf, &_size, EVP_sha1(), NULL) != 1) {
88 return WAE_ERROR_CRYPTO;
94 WAE_SLOGD("get old iv of length: %zu", iv->size);
96 return WAE_ERROR_NONE;
99 static int _decrypt(const crypto_element_s *ce, const raw_buffer_s *data,
100 raw_buffer_s **pdecrypted)
102 if (!is_crypto_element_valid(ce) || !is_buffer_valid(data) || pdecrypted == NULL)
103 return WAE_ERROR_INVALID_PARAMETER;
105 if (ce->dek->size != DUK_SIZE || ce->iv->size < DUK_SIZE) {
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();
113 int in_len = data->size;
116 int ret = WAE_ERROR_NONE;
118 raw_buffer_s *decrypted = buffer_create(
119 (in_len / EVP_CIPHER_block_size(algo) + 1) * EVP_CIPHER_block_size(algo));
121 if (decrypted == NULL)
122 return WAE_ERROR_MEMORY;
124 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
126 ret = WAE_ERROR_MEMORY;
130 if (EVP_CipherInit(ctx, algo, ce->dek->buf, ce->iv->buf, 0) != 1) {
131 ret = WAE_ERROR_CRYPTO;
135 if (EVP_CIPHER_CTX_set_padding(ctx, 1) != 1) {
136 ret = WAE_ERROR_CRYPTO;
140 if (EVP_CipherUpdate(ctx, decrypted->buf, &out_len, data->buf, in_len) != 1) {
141 ret = WAE_ERROR_CRYPTO;
145 if (EVP_CipherFinal(ctx, decrypted->buf + out_len, &final_len) != 1) {
146 ret = WAE_ERROR_CRYPTO;
150 decrypted->size = out_len + final_len;
152 *pdecrypted = decrypted;
155 EVP_CIPHER_CTX_free(ctx);
157 if (ret != WAE_ERROR_NONE)
158 buffer_destroy(decrypted);
163 int get_old_ss_crypto_element(const char *pkg_id, crypto_element_s **pce)
165 if (pkg_id == NULL || pce == NULL)
166 return WAE_ERROR_INVALID_PARAMETER;
168 raw_buffer_s *duk = NULL;
169 raw_buffer_s *iv = NULL;
170 crypto_element_s *ce = NULL;
172 int ret = _get_old_duk(pkg_id, &duk);
173 if (ret != WAE_ERROR_NONE)
176 ret = _get_old_iv(duk, &iv);
177 if (ret != WAE_ERROR_NONE)
180 ce = crypto_element_create(duk, iv);
182 ret = WAE_ERROR_MEMORY;
186 ce->is_migrated_app = true;
190 return WAE_ERROR_NONE;
199 int decrypt_by_old_ss_algo(const crypto_element_s *ce, const raw_buffer_s *encrypted,
200 raw_buffer_s **pdecrypted)
202 if (!is_crypto_element_valid(ce) || !is_buffer_valid(encrypted) || pdecrypted == NULL)
203 return WAE_ERROR_INVALID_PARAMETER;
205 int ret = _decrypt(ce, encrypted, pdecrypted);
208 case WAE_ERROR_CRYPTO:
209 WAE_SLOGE("decrypt with old ss algo failed with crypto error below.");
210 _logging_openssl_err();
213 WAE_SLOGI("decrypt with old ss algo success!");
216 WAE_SLOGE("decrypt with old ss algo failed! ret(%d)", ret);