1c52cc5ec0b79da6b82cb27125406508b81372de
[platform/core/security/libwebappenc.git] / srcs / crypto_service.c
1 /*
2  *  Copyright (c) 2000 - 2015 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        crypto_service.c
18  * @author      Dongsun Lee (ds73.lee@samsung.com)
19  * @version     1.0
20  * @brief       provides encryption and decription operations.
21  */
22 #include "crypto_service.h"
23
24 #include <stdbool.h>
25 #include <openssl/evp.h>
26 #include <openssl/rand.h>
27 #include <openssl/crypto.h>
28 #include <openssl/err.h>
29 #include <openssl/bio.h>
30 #include <openssl/evp.h>
31 #include <openssl/pem.h>
32 #include <openssl/rsa.h>
33
34 #include "web_app_enc.h"
35 #include "wae_log.h"
36
37 #define AES_256_KEY_SIZE 32
38
39 static unsigned char AES_CBC_IV[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
40                                         0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
41
42 static bool __initialized = false;
43
44 void _initialize()
45 {
46     if(!__initialized) {
47         ERR_load_crypto_strings();
48         OpenSSL_add_all_algorithms();
49         __initialized = true;
50     }
51 }
52
53
54
55 int encrypt_app_dek(const unsigned char* rsaPublicKey, size_t pubKeyLen,
56                     const unsigned char* dek, size_t dekLen,
57                     unsigned char** encryptedDek, size_t* encryptedDekLen)
58 {
59     int ret = WAE_ERROR_NONE;
60     EVP_PKEY *pKey = NULL;
61     BIO* bio = NULL;
62     EVP_PKEY_CTX *ctx = NULL;
63     unsigned char* out = NULL;
64     size_t outLen = 0;
65
66     _initialize();
67
68     bio = BIO_new(BIO_s_mem());
69     BIO_write(bio, rsaPublicKey, pubKeyLen);
70     pKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
71
72     if(pKey == NULL){
73         BIO_reset(bio);
74         BIO_write(bio, rsaPublicKey, pubKeyLen);
75         pKey = d2i_PUBKEY_bio(bio, NULL);
76     }
77
78     if(pKey == NULL) {
79         ret = WAE_ERROR_FILE;
80         WAE_SLOGE("Failt to convert to public key.");
81         goto error;
82     }
83
84     ctx = EVP_PKEY_CTX_new(pKey, NULL);
85     if(ctx == NULL) {
86         WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
87         ret = WAE_ERROR_CRYPTO;
88         goto error;
89     }
90
91     if (EVP_PKEY_encrypt_init(ctx) <= 0) {
92         WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt_init failed");
93         ret = WAE_ERROR_CRYPTO;
94         goto error;
95     }
96     if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
97         WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed");
98         ret = WAE_ERROR_CRYPTO;
99         goto error;
100     }
101
102     /* Determine buffer length */
103     if (EVP_PKEY_encrypt(ctx, NULL, &outLen, dek, dekLen) <= 0) {
104         WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed");
105         ret = WAE_ERROR_CRYPTO;
106         goto error;
107     }
108
109     out = OPENSSL_malloc(outLen);
110     if(out == NULL) {
111         WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed");
112         ret = WAE_ERROR_MEMORY;
113         goto error;
114     }
115
116     if (EVP_PKEY_encrypt(ctx, out, &outLen, dek, dekLen) <= 0) {
117         WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed");
118         ret = WAE_ERROR_CRYPTO;
119         goto error;
120     }
121
122     *encryptedDek = out;
123     *encryptedDekLen = outLen;
124
125 error:
126     if(bio != NULL)
127         BIO_free(bio);
128     if(pKey != NULL)
129         EVP_PKEY_free(pKey);
130     if(ctx != NULL)
131         EVP_PKEY_CTX_free(ctx);
132     if(ret != WAE_ERROR_NONE && out != NULL)
133         OPENSSL_free(out);
134
135     return ret;
136 }
137
138 int decrypt_app_dek(const unsigned char* rsaPrivateKey, size_t priKeyLen,
139                     const char* priKeyPassword,
140                     const unsigned char* encryptedDek, size_t dencryptedDekLen,
141                     unsigned char** decryptedDek, size_t* decryptedDekLen)
142 {
143     int ret = WAE_ERROR_NONE;
144     EVP_PKEY *pKey = NULL;
145     BIO* bio = NULL;
146     EVP_PKEY_CTX *ctx = NULL;
147     unsigned char* out = NULL;
148     size_t outLen = 0;
149
150     _initialize();
151
152     bio = BIO_new(BIO_s_mem());
153     BIO_write(bio, rsaPrivateKey, priKeyLen);
154     pKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)priKeyPassword);
155
156     if(pKey == NULL) {
157         BIO_reset(bio);
158         BIO_write(bio, rsaPrivateKey, priKeyLen);
159         pKey = d2i_PrivateKey_bio(bio, NULL);
160     }
161
162     if(pKey == NULL) {
163         ret = WAE_ERROR_FILE;
164         WAE_SLOGE("Failt to convert to public key.");
165         goto error;
166     }
167
168     ctx = EVP_PKEY_CTX_new(pKey, NULL);
169     if(ctx == NULL) {
170         WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
171         ret = WAE_ERROR_CRYPTO;
172         goto error;
173     }
174
175     if (EVP_PKEY_decrypt_init(ctx) <= 0) {
176         WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt_init failed");
177         ret = WAE_ERROR_CRYPTO;
178         goto error;
179     }
180     if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
181         WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed");
182         ret = WAE_ERROR_CRYPTO;
183         goto error;
184     }
185
186     /* Determine buffer length */
187     if (EVP_PKEY_decrypt(ctx, NULL, &outLen, encryptedDek, dencryptedDekLen) <= 0) {
188         WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt failed");
189         ret = WAE_ERROR_CRYPTO;
190         goto error;
191     }
192
193     out = OPENSSL_malloc(outLen);
194     if(out == NULL) {
195         WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed");
196         ret = WAE_ERROR_MEMORY;
197         goto error;
198     }
199
200     if (EVP_PKEY_decrypt(ctx, out, &outLen, encryptedDek, dencryptedDekLen) <= 0) {
201         WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_decrypt failed");
202         ret = WAE_ERROR_CRYPTO;
203         goto error;
204     }
205
206     *decryptedDek = out;
207     *decryptedDekLen = outLen;
208
209 error:
210     if(bio != NULL)
211         BIO_free(bio);
212     if(pKey != NULL)
213         EVP_PKEY_free(pKey);
214     if(ctx != NULL)
215         EVP_PKEY_CTX_free(ctx);
216     if(ret != WAE_ERROR_NONE && out != NULL)
217         OPENSSL_free(out);
218
219     return ret;
220 }
221
222
223 int encrypt_aes_cbc(const unsigned char* pKey, size_t keyLen,
224                     const unsigned char* pData, size_t dataLen,
225                     unsigned char** ppEncryptedData, size_t* pEncDataLen)
226 {
227     EVP_CIPHER_CTX *ctx;
228     int len;
229     unsigned char *ciphertext = NULL;
230     size_t ciphertext_len;
231     unsigned char *iv = AES_CBC_IV;
232     int ret = WAE_ERROR_NONE;
233
234     _initialize();
235
236     WAE_SLOGI("Encryption Started. size=%d", dataLen);
237     /* check input paramter */
238     if( keyLen != 32 ) {
239         WAE_SLOGE("Encryption Failed. Invalid Key Length. keyLen=%d", keyLen);
240         return WAE_ERROR_INVALID_PARAMETER;
241     }
242
243     // assing a enough memory for decryption.
244     ciphertext = (unsigned char*) malloc(dataLen + 32);
245
246     /* Create and initialise the context */
247     if(!(ctx = EVP_CIPHER_CTX_new())) {
248         WAE_SLOGE("Encryption Failed. EVP_CIPHER_CTX_new failed");
249         ret = WAE_ERROR_CRYPTO;
250         goto error;
251     }
252
253     /* Initialise the encryption operation. IMPORTANT - ensure you use a key
254      * and IV size appropriate for your cipher
255      * In this example we are using 256 bit AES (i.e. a 256 bit key). The
256      * IV size for *most* modes is the same as the block size. For AES this
257      * is 128 bits */
258     if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) {
259         WAE_SLOGE("Encryption Failed. EVP_EncryptInit_ex failed");
260         ret = WAE_ERROR_CRYPTO;
261         goto error;
262     }
263
264     /* Provide the message to be encrypted, and obtain the encrypted output.
265      * EVP_EncryptUpdate can be called multiple times if necessary
266      */
267     if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, pData, dataLen)) {
268         WAE_SLOGE("Encryption Failed. EVP_EncryptUpdate failed");
269         ret = WAE_ERROR_CRYPTO;
270         goto error;
271     }
272     ciphertext_len = len;
273
274     /* Finalise the encryption. Further ciphertext bytes may be written at
275      * this stage.
276      */
277     if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
278         WAE_SLOGE("Encryption Failed. EVP_EncryptFinal_ex failed");
279         ret = WAE_ERROR_CRYPTO;
280         goto error;
281     }
282     ciphertext_len += len;
283
284     *ppEncryptedData = ciphertext;
285     *pEncDataLen = ciphertext_len;
286
287     ret = WAE_ERROR_NONE;
288     WAE_SLOGI("Encryption Ended Successfully. encrypted_len", ciphertext_len);
289 error:
290     if(ctx != NULL)
291         EVP_CIPHER_CTX_free(ctx);
292     if(ret != WAE_ERROR_NONE && ciphertext != NULL)
293         free(ciphertext);
294     return ret;
295 }
296
297 int decrypt_aes_cbc(const unsigned char* pKey, size_t keyLen,
298                     const unsigned char* pData, size_t dataLen,
299                     unsigned char** ppDecryptedData, size_t* pDecDataLen)
300 {
301     EVP_CIPHER_CTX *ctx;
302     int len;
303     unsigned char* plaintext = NULL;
304     size_t plaintext_len;
305     unsigned char *iv = AES_CBC_IV;
306     int ret = WAE_ERROR_NONE;
307
308     _initialize();
309
310     WAE_SLOGI("Decryption Started. size=%d", dataLen);
311
312     /* check input paramter */
313     if( keyLen != 32 ) {
314         WAE_SLOGE("Decryption Failed. Invalid Key Length. keyLen=%d", keyLen);
315         return WAE_ERROR_INVALID_PARAMETER;
316     }
317
318     // assing a enough memory for decryption.
319     plaintext = (unsigned char*) malloc(dataLen);
320
321     /* Create and initialise the context */
322     if(!(ctx = EVP_CIPHER_CTX_new())) {
323         WAE_SLOGE("Decryption Failed. EVP_CIPHER_CTX_new failed");
324         ret = WAE_ERROR_CRYPTO;
325         goto error;
326     }
327
328     /* Initialise the decryption operation. IMPORTANT - ensure you use a key
329      * and IV size appropriate for your cipher
330      * In this example we are using 256 bit AES (i.e. a 256 bit key). The
331      * IV size for *most* modes is the same as the block size. For AES this
332      * is 128 bits */
333     if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) {
334         WAE_SLOGE("Decryption Failed. EVP_DecryptInit_ex failed");
335         ret = WAE_ERROR_CRYPTO;
336         goto error;
337     }
338
339     /* Provide the message to be decrypted, and obtain the plaintext output.
340      * EVP_DecryptUpdate can be called multiple times if necessary
341      */
342     if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, pData, dataLen)) {
343         WAE_SLOGE("Decryption Failed. EVP_DecryptUpdate failed");
344         ret = WAE_ERROR_CRYPTO;
345         goto error;
346     }
347     plaintext_len = len;
348
349     /* Finalise the decryption. Further plaintext bytes may be written at
350      * this stage.
351      */
352     if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
353         WAE_SLOGE("Decryption Failed. EVP_DecryptFinal_ex failed");
354         ret = WAE_ERROR_CRYPTO;
355         goto error;
356     }
357     plaintext_len += len;
358
359     *ppDecryptedData = plaintext;
360     *pDecDataLen = plaintext_len;
361
362     ret = WAE_ERROR_NONE;
363     WAE_SLOGI("Decryption Ended Successfully. decrypted_len", plaintext_len);
364 error:
365     if(ctx != NULL)
366         EVP_CIPHER_CTX_free(ctx);
367     if(ret != WAE_ERROR_NONE && plaintext != NULL)
368         free(plaintext);
369     return ret;
370 }
371