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