2 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 * @file crypto_service.c
18 * @author Dongsun Lee (ds73.lee@samsung.com)
20 * @brief provides encryption and decription operations.
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>
32 #include "web_app_enc.h"
35 #define AES_256_KEY_SIZE 32
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};
43 static int __initialized = WAE_FALSE;
47 if(__initialized != WAE_TRUE) {
48 ERR_load_crypto_strings();
49 OpenSSL_add_all_algorithms();
50 __initialized = WAE_TRUE;
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)
60 int ret = WAE_ERROR_NONE;
61 EVP_PKEY *pKey = NULL;
63 EVP_PKEY_CTX *ctx = NULL;
64 unsigned char* out = NULL;
69 bio = BIO_new(BIO_s_mem());
70 BIO_write(bio, rsaPublicKey, pubKeyLen);
71 pKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
75 BIO_write(bio, rsaPublicKey, pubKeyLen);
76 pKey = d2i_PUBKEY_bio(bio, NULL);
81 WAE_SLOGE("Failt to convert to public key.");
85 ctx = EVP_PKEY_CTX_new(pKey, NULL);
87 WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
88 ret = WAE_ERROR_CRYPTO;
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;
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;
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;
110 out = OPENSSL_malloc(outLen);
112 WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed");
113 ret = WAE_ERROR_MEMORY;
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;
124 *encryptedDekLen = outLen;
132 EVP_PKEY_CTX_free(ctx);
133 if(ret != WAE_ERROR_NONE && out != NULL)
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)
144 int ret = WAE_ERROR_NONE;
145 EVP_PKEY *pKey = NULL;
147 EVP_PKEY_CTX *ctx = NULL;
148 unsigned char* out = NULL;
153 bio = BIO_new(BIO_s_mem());
154 BIO_write(bio, rsaPrivateKey, priKeyLen);
155 pKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)priKeyPassword);
159 BIO_write(bio, rsaPrivateKey, priKeyLen);
160 pKey = d2i_PrivateKey_bio(bio, NULL);
164 ret = WAE_ERROR_FILE;
165 WAE_SLOGE("Failt to convert to public key.");
169 ctx = EVP_PKEY_CTX_new(pKey, NULL);
171 WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
172 ret = WAE_ERROR_CRYPTO;
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;
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;
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;
194 out = OPENSSL_malloc(outLen);
196 WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed");
197 ret = WAE_ERROR_MEMORY;
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;
208 *decryptedDekLen = outLen;
216 EVP_PKEY_CTX_free(ctx);
217 if(ret != WAE_ERROR_NONE && out != NULL)
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)
230 unsigned char *ciphertext = NULL;
231 size_t ciphertext_len;
232 unsigned char *iv = AES_CBC_IV;
233 int ret = WAE_ERROR_NONE;
237 WAE_SLOGI("Encryption Started. size=%d", dataLen);
238 /* check input paramter */
240 WAE_SLOGE("Encryption Failed. Invalid Key Length. keyLen=%d", keyLen);
241 return WAE_ERROR_INVALID_PARAMETER;
244 // assing a enough memory for decryption.
245 ciphertext = (unsigned char*) malloc(dataLen + 32);
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;
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
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;
265 /* Provide the message to be encrypted, and obtain the encrypted output.
266 * EVP_EncryptUpdate can be called multiple times if necessary
268 if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, pData, dataLen)) {
269 WAE_SLOGE("Encryption Failed. EVP_EncryptUpdate failed");
270 ret = WAE_ERROR_CRYPTO;
273 ciphertext_len = len;
275 /* Finalise the encryption. Further ciphertext bytes may be written at
278 if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
279 WAE_SLOGE("Encryption Failed. EVP_EncryptFinal_ex failed");
280 ret = WAE_ERROR_CRYPTO;
283 ciphertext_len += len;
285 *ppEncryptedData = ciphertext;
286 *pEncDataLen = ciphertext_len;
288 ret = WAE_ERROR_NONE;
289 WAE_SLOGI("Encryption Ended Successfully. encrypted_len", ciphertext_len);
292 EVP_CIPHER_CTX_free(ctx);
293 if(ret != WAE_ERROR_NONE && ciphertext != NULL)
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)
304 unsigned char* plaintext = NULL;
305 size_t plaintext_len;
306 unsigned char *iv = AES_CBC_IV;
307 int ret = WAE_ERROR_NONE;
311 WAE_SLOGI("Decryption Started. size=%d", dataLen);
313 /* check input paramter */
315 WAE_SLOGE("Decryption Failed. Invalid Key Length. keyLen=%d", keyLen);
316 return WAE_ERROR_INVALID_PARAMETER;
319 // assing a enough memory for decryption.
320 plaintext = (unsigned char*) malloc(dataLen);
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;
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
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;
340 /* Provide the message to be decrypted, and obtain the plaintext output.
341 * EVP_DecryptUpdate can be called multiple times if necessary
343 if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, pData, dataLen)) {
344 WAE_SLOGE("Decryption Failed. EVP_DecryptUpdate failed");
345 ret = WAE_ERROR_CRYPTO;
350 /* Finalise the decryption. Further plaintext bytes may be written at
353 if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
354 WAE_SLOGE("Decryption Failed. EVP_DecryptFinal_ex failed");
355 ret = WAE_ERROR_CRYPTO;
358 plaintext_len += len;
360 *ppDecryptedData = plaintext;
361 *pDecDataLen = plaintext_len;
363 ret = WAE_ERROR_NONE;
364 WAE_SLOGI("Decryption Ended Successfully. decrypted_len", plaintext_len);
367 EVP_CIPHER_CTX_free(ctx);
368 if(ret != WAE_ERROR_NONE && plaintext != NULL)