d240fa421f559b6a8c7efa1751da7f229adf0c72
[platform/core/security/libwebappenc.git] / srcs / decrypt_migrated_wgt.c
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  *
16  *
17  * @file        decrypt_migrated_wgt.c
18  * @author      Kyungwook Tak (k.tak@samsung.com)
19  * @version     1.0
20  * @brief       Restore old encryption key for removed secure-storage
21  */
22 #include "decrypt_migrated_wgt.h"
23
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include <openssl/hmac.h>
28 #include <openssl/sha.h>
29 #include <openssl/evp.h>
30 #include <openssl/crypto.h>
31
32 #include "wae_log.h"
33 #include "web_app_enc.h"
34
35 #define DUK_LEN 16
36
37 static int _get_old_duk(const char *pkg_id, unsigned char **pduk, size_t *pduk_len)
38 {
39         unsigned char salt[32];
40
41         memset(salt, 0xFF, sizeof(salt));
42
43         unsigned char *duk = (unsigned char *)malloc(sizeof(unsigned char) * ((DUK_LEN * 2) + 1));
44         if (duk == NULL) {
45                 WAE_SLOGE("Failed to allocate memory for old duk.");
46                 return WAE_ERROR_MEMORY;
47         }
48
49         PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1, (DUK_LEN * 2), duk);
50         duk[DUK_LEN * 2] = '\0';
51
52         *pduk = duk;
53         *pduk_len = DUK_LEN;
54
55         WAE_SLOGD("get old duk of length: %d", *pduk_len);
56
57         return WAE_ERROR_NONE;
58 }
59
60 static int _get_old_iv(const unsigned char *src, size_t src_len, unsigned char **piv, size_t *piv_len)
61 {
62         unsigned char iv_buf[SHA_DIGEST_LENGTH] = {0, };
63         unsigned int iv_len = 0;
64
65         if (EVP_Digest(src, src_len, iv_buf, &iv_len, EVP_sha1(), NULL) != 1) {
66                 WAE_SLOGE("Failed to EVP_Digest for getting old iv");
67                 return WAE_ERROR_CRYPTO;
68         }
69
70         unsigned char *iv = (unsigned char *)malloc(sizeof(unsigned char) * sizeof(iv_buf));
71         if (iv == NULL)
72                 return WAE_ERROR_MEMORY;
73
74         memcpy(iv, iv_buf, sizeof(iv_buf));
75
76         *piv = iv;
77         *piv_len = iv_len;
78
79         WAE_SLOGD("get old iv of length: %d", *piv_len);
80
81         return WAE_ERROR_NONE;
82 }
83
84 static int _decrypt(const unsigned char *key, size_t key_len,
85                                         const unsigned char *iv, size_t iv_len,
86                                         const unsigned char *data, size_t data_len,
87                                         unsigned char **pdecrypted, size_t *pdecrypted_len)
88 {
89         if (key == NULL || iv == NULL || data == NULL || pdecrypted == NULL ||
90                         pdecrypted_len == 0)
91                 return WAE_ERROR_INVALID_PARAMETER;
92
93         if (key_len != 16 || iv_len < 16) {
94                 WAE_SLOGE("Invalid key or iv size for decrypt by aes_128_cbc algorithm. "
95                                   "key should be 16 bytes and iv should be bigger than 16 bytes");
96                 return WAE_ERROR_INVALID_PARAMETER;
97         }
98
99         const struct evp_cipher_st *algo = EVP_aes_128_cbc();
100
101         EVP_CIPHER_CTX ctx;
102
103         size_t tmp_len = (data_len / algo->block_size + 1) * algo->block_size;
104         int decrypted_len = 0;
105         int final_len = 0;
106
107         unsigned char *decrypted = (unsigned char *)calloc(tmp_len, 1);
108
109         if (decrypted == NULL)
110                 return WAE_ERROR_MEMORY;
111
112         EVP_CIPHER_CTX_init(&ctx);
113
114         int ret = EVP_CipherInit(&ctx, algo, key, iv, 0);
115
116         if (ret != 1) {
117                 ret = WAE_ERROR_CRYPTO;
118                 goto error;
119         }
120
121         ret = EVP_CIPHER_CTX_set_padding(&ctx, 1);
122
123         if (ret != 1) {
124                 ret = WAE_ERROR_CRYPTO;
125                 goto error;
126         }
127
128         ret = EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len);
129
130         if (ret != 1) {
131                 ret = WAE_ERROR_CRYPTO;
132                 goto error;
133         } else if (decrypted_len <= 0) {
134                 ret = WAE_ERROR_CRYPTO;
135                 goto error;
136         }
137
138         ret = EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len);
139
140         if (ret != 1) {
141                 ret = WAE_ERROR_CRYPTO;
142                 goto error;
143         } else if (final_len <= 0) {
144                 ret = WAE_ERROR_CRYPTO;
145                 goto error;
146         }
147
148         *pdecrypted = decrypted;
149         *pdecrypted_len = decrypted_len + final_len;
150
151         ret = WAE_ERROR_NONE;
152
153 error:
154         EVP_CIPHER_CTX_cleanup(&ctx);
155
156         return ret;
157 }
158
159 int decrypt_by_old_ss_algo(const char *pkg_id, const unsigned char *encrypted, size_t encrypted_len,
160                                                    unsigned char **pdecrypted, size_t *pdecrypted_len)
161 {
162         unsigned char *duk = NULL;
163         size_t duk_len = 0;
164         int ret = _get_old_duk(pkg_id, &duk, &duk_len);
165
166         if (ret != WAE_ERROR_NONE)
167                 return ret;
168
169         unsigned char *iv = NULL;
170         size_t iv_len = 0;
171         ret = _get_old_iv(duk, duk_len, &iv, &iv_len);
172
173         if (ret != WAE_ERROR_NONE)
174                 goto error;
175
176         ret = _decrypt(duk, duk_len, iv, iv_len, encrypted, encrypted_len, pdecrypted, pdecrypted_len);
177
178         WAE_SLOGI("decrypt with old ss algo success of pkg: %s", pkg_id);
179
180 error:
181         free(duk);
182         free(iv);
183
184         return WAE_ERROR_NONE;
185 }