Migrate to openssl 1.1
[platform/core/security/libwebappenc.git] / srcs / decrypt_migrated_wgt.c
1 /*
2  *  Copyright (c) 2016 - 2019 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 #include <openssl/err.h>
32
33 #include "wae_log.h"
34 #include "web_app_enc.h"
35
36 #define DUK_SIZE 16
37
38 static void _logging_openssl_err()
39 {
40         unsigned long e = ERR_get_error();
41         char buf[512] = {0, };
42
43         ERR_error_string_n(e, buf, 511);
44
45         WAE_SLOGE("Openssl err: %s", buf);
46 }
47
48 static int _get_old_duk(const char *pkg_id, raw_buffer_s **pduk)
49 {
50         if (pkg_id == NULL || pduk == NULL)
51                 return WAE_ERROR_INVALID_PARAMETER;
52
53         unsigned char salt[32];
54
55         memset(salt, 0xFF, sizeof(salt));
56
57         raw_buffer_s *duk = buffer_create(DUK_SIZE * 2);
58         if (duk == NULL)
59                 return WAE_ERROR_MEMORY;
60
61         if (PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1,
62                                                            duk->size, duk->buf) != 1) {
63                 buffer_destroy(duk);
64                 return WAE_ERROR_CRYPTO;
65         }
66
67         duk->size = DUK_SIZE;
68
69         *pduk = duk;
70
71         WAE_SLOGD("get old duk of length: %zu", duk->size);
72
73         return WAE_ERROR_NONE;
74 }
75
76 static int _get_old_iv(const raw_buffer_s *src, raw_buffer_s **piv)
77 {
78         if (!is_buffer_valid(src) || piv == NULL)
79                 return WAE_ERROR_INVALID_PARAMETER;
80
81         raw_buffer_s *iv = buffer_create(SHA_DIGEST_LENGTH);
82         if (iv == NULL)
83                 return WAE_ERROR_MEMORY;
84
85         unsigned int _size;
86         if (EVP_Digest(src->buf, src->size, iv->buf, &_size, EVP_sha1(), NULL) != 1) {
87                 buffer_destroy(iv);
88                 return WAE_ERROR_CRYPTO;
89         }
90
91         iv->size = _size;
92         *piv = iv;
93
94         WAE_SLOGD("get old iv of length: %zu", iv->size);
95
96         return WAE_ERROR_NONE;
97 }
98
99 static int _decrypt(const crypto_element_s *ce, const raw_buffer_s *data,
100                                         raw_buffer_s **pdecrypted)
101 {
102         if (!is_crypto_element_valid(ce) || !is_buffer_valid(data) || pdecrypted == NULL)
103                 return WAE_ERROR_INVALID_PARAMETER;
104
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;
109         }
110
111         const struct evp_cipher_st *algo = EVP_aes_128_cbc();
112
113         int in_len = data->size;
114         int out_len = 0;
115         int final_len = 0;
116         int ret = WAE_ERROR_NONE;
117
118         raw_buffer_s *decrypted = buffer_create(
119                         (in_len / EVP_CIPHER_block_size(algo) + 1) * EVP_CIPHER_block_size(algo));
120
121         if (decrypted == NULL)
122                 return WAE_ERROR_MEMORY;
123
124         EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
125         if (!ctx) {
126                 ret = WAE_ERROR_MEMORY;
127                 goto error;
128         }
129
130         if (EVP_CipherInit(ctx, algo, ce->dek->buf, ce->iv->buf, 0) != 1) {
131                 ret = WAE_ERROR_CRYPTO;
132                 goto error;
133         }
134
135         if (EVP_CIPHER_CTX_set_padding(ctx, 1) != 1) {
136                 ret = WAE_ERROR_CRYPTO;
137                 goto error;
138         }
139
140         if (EVP_CipherUpdate(ctx, decrypted->buf, &out_len, data->buf, in_len) != 1) {
141                 ret = WAE_ERROR_CRYPTO;
142                 goto error;
143         }
144
145         if (EVP_CipherFinal(ctx, decrypted->buf + out_len, &final_len) != 1) {
146                 ret = WAE_ERROR_CRYPTO;
147                 goto error;
148         }
149
150         decrypted->size = out_len + final_len;
151
152         *pdecrypted = decrypted;
153
154 error:
155         EVP_CIPHER_CTX_free(ctx);
156
157         if (ret != WAE_ERROR_NONE)
158                 buffer_destroy(decrypted);
159
160         return ret;
161 }
162
163 int get_old_ss_crypto_element(const char *pkg_id, crypto_element_s **pce)
164 {
165         if (pkg_id == NULL || pce == NULL)
166                 return WAE_ERROR_INVALID_PARAMETER;
167
168         raw_buffer_s *duk = NULL;
169         raw_buffer_s *iv = NULL;
170         crypto_element_s *ce = NULL;
171
172         int ret = _get_old_duk(pkg_id, &duk);
173         if (ret != WAE_ERROR_NONE)
174                 return ret;
175
176         ret = _get_old_iv(duk, &iv);
177         if (ret != WAE_ERROR_NONE)
178                 goto error;
179
180         ce = crypto_element_create(duk, iv);
181         if (ce == NULL) {
182                 ret = WAE_ERROR_MEMORY;
183                 goto error;
184         }
185
186         ce->is_migrated_app = true;
187
188         *pce = ce;
189
190         return WAE_ERROR_NONE;
191
192 error:
193         buffer_destroy(duk);
194         buffer_destroy(iv);
195
196         return ret;
197 }
198
199 int decrypt_by_old_ss_algo(const crypto_element_s *ce, const raw_buffer_s *encrypted,
200                                                    raw_buffer_s **pdecrypted)
201 {
202         if (!is_crypto_element_valid(ce) || !is_buffer_valid(encrypted) || pdecrypted == NULL)
203                 return WAE_ERROR_INVALID_PARAMETER;
204
205         int ret = _decrypt(ce, encrypted, pdecrypted);
206
207         switch (ret) {
208         case WAE_ERROR_CRYPTO:
209                 WAE_SLOGE("decrypt with old ss algo failed with crypto error below.");
210                 _logging_openssl_err();
211                 break;
212         case WAE_ERROR_NONE:
213                 WAE_SLOGI("decrypt with old ss algo success!");
214                 break;
215         default:
216                 WAE_SLOGE("decrypt with old ss algo failed! ret(%d)", ret);
217                 break;
218         }
219
220         return ret;
221 }