Logging openssl log on crypto error cases
[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 #include <openssl/err.h>
32
33 #include "wae_log.h"
34 #include "web_app_enc.h"
35
36 #define DUK_LEN 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, unsigned char **pduk, size_t *pduk_len)
49 {
50         unsigned char salt[32];
51
52         memset(salt, 0xFF, sizeof(salt));
53
54         unsigned char *duk = (unsigned char *)malloc(sizeof(unsigned char) * ((DUK_LEN * 2) + 1));
55         if (duk == NULL) {
56                 WAE_SLOGE("Failed to allocate memory for old duk.");
57                 return WAE_ERROR_MEMORY;
58         }
59
60         if (PKCS5_PBKDF2_HMAC_SHA1(pkg_id, strlen(pkg_id), salt, sizeof(salt), 1,
61                                                            (DUK_LEN * 2), duk) != 1) {
62                 free(duk);
63                 return WAE_ERROR_CRYPTO;
64         }
65
66         duk[DUK_LEN * 2] = '\0';
67
68         *pduk = duk;
69         *pduk_len = DUK_LEN;
70
71         WAE_SLOGD("get old duk of length: %d", *pduk_len);
72
73         return WAE_ERROR_NONE;
74 }
75
76 static int _get_old_iv(const unsigned char *src, size_t src_len, unsigned char **piv, size_t *piv_len)
77 {
78         unsigned int iv_len = SHA_DIGEST_LENGTH;
79         unsigned char *iv = (unsigned char *)malloc(sizeof(unsigned char) * iv_len);
80         if (iv == NULL)
81                 return WAE_ERROR_MEMORY;
82
83         if (EVP_Digest(src, src_len, iv, &iv_len, EVP_sha1(), NULL) != 1) {
84                 free(iv);
85                 return WAE_ERROR_CRYPTO;
86         }
87
88         *piv = iv;
89         *piv_len = iv_len;
90
91         WAE_SLOGD("get old iv of length: %d", *piv_len);
92
93         return WAE_ERROR_NONE;
94 }
95
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)
100 {
101         if (key == NULL || iv == NULL || data == NULL || pdecrypted == NULL ||
102                         pdecrypted_len == 0)
103                 return WAE_ERROR_INVALID_PARAMETER;
104
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;
109         }
110
111         const struct evp_cipher_st *algo = EVP_aes_128_cbc();
112
113         EVP_CIPHER_CTX ctx;
114
115         size_t tmp_len = (data_len / algo->block_size + 1) * algo->block_size;
116         int decrypted_len = 0;
117         int final_len = 0;
118
119         unsigned char *decrypted = (unsigned char *)calloc(tmp_len, 1);
120
121         if (decrypted == NULL)
122                 return WAE_ERROR_MEMORY;
123
124         EVP_CIPHER_CTX_init(&ctx);
125
126         int ret = WAE_ERROR_NONE;
127
128         if (EVP_CipherInit(&ctx, algo, key, iv, 0) != 1) {
129                 ret = WAE_ERROR_CRYPTO;
130                 goto error;
131         }
132
133         if (EVP_CIPHER_CTX_set_padding(&ctx, 1) != 1) {
134                 ret = WAE_ERROR_CRYPTO;
135                 goto error;
136         }
137
138         if (EVP_CipherUpdate(&ctx, decrypted, &decrypted_len, data, data_len) != 1) {
139                 ret = WAE_ERROR_CRYPTO;
140                 goto error;
141         } else if (decrypted_len <= 0) {
142                 WAE_SLOGE("EVP_CipherUpdate success but returned decrypted_len(%d) <= 0",
143                                   decrypted_len);
144                 ret = WAE_ERROR_UNKNOWN;
145                 goto error;
146         }
147
148         if (EVP_CipherFinal(&ctx, decrypted + decrypted_len, &final_len) != 1) {
149                 ret = WAE_ERROR_CRYPTO;
150                 goto error;
151         } else if (final_len <= 0) {
152                 WAE_SLOGE("EVP_CipherFinal success but returned final_len(%d) <= 0",
153                                   final_len);
154                 ret = WAE_ERROR_UNKNOWN;
155                 goto error;
156         }
157
158         *pdecrypted = decrypted;
159         *pdecrypted_len = decrypted_len + final_len;
160
161 error:
162         EVP_CIPHER_CTX_cleanup(&ctx);
163
164         if (ret != WAE_ERROR_NONE)
165                 free(decrypted);
166
167         return ret;
168 }
169
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)
172 {
173         unsigned char *duk = NULL;
174         size_t duk_len = 0;
175         unsigned char *iv = NULL;
176         size_t iv_len = 0;
177
178         int ret = _get_old_duk(pkg_id, &duk, &duk_len);
179
180         if (ret != WAE_ERROR_NONE)
181                 goto error;
182
183         ret = _get_old_iv(duk, duk_len, &iv, &iv_len);
184
185         if (ret != WAE_ERROR_NONE)
186                 goto error;
187
188         ret = _decrypt(duk, duk_len, iv, iv_len, encrypted, encrypted_len, pdecrypted, pdecrypted_len);
189
190         WAE_SLOGI("decrypt with old ss algo success of pkg: %s", pkg_id);
191
192 error:
193         if (ret == WAE_ERROR_CRYPTO)
194                 _logging_openssl_err();
195
196         free(duk);
197         free(iv);
198
199         return WAE_ERROR_NONE;
200 }