2 * Copyright (c) 2016 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.
22 #include "crypto_service.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>
34 #include "web_app_enc.h"
37 #define AES_256_KEY_SIZE 32
39 static unsigned char AES_CBC_IV[16] = {
40 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
41 0x08, 0x39, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
44 static bool __initialized = false;
49 ERR_load_crypto_strings();
50 OpenSSL_add_all_algorithms();
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)
59 int ret = WAE_ERROR_NONE;
60 EVP_PKEY *pKey = NULL;
62 EVP_PKEY_CTX *ctx = NULL;
63 unsigned char *out = NULL;
68 bio = BIO_new(BIO_s_mem());
69 BIO_write(bio, rsaPublicKey, pubKeyLen);
70 pKey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
74 BIO_write(bio, rsaPublicKey, pubKeyLen);
75 pKey = d2i_PUBKEY_bio(bio, NULL);
80 WAE_SLOGE("Failt to convert to public key.");
84 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;
98 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
99 WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed");
100 ret = WAE_ERROR_CRYPTO;
104 /* Determine buffer length */
105 if (EVP_PKEY_encrypt(ctx, NULL, &outLen, dek, dekLen) <= 0) {
106 WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed");
107 ret = WAE_ERROR_CRYPTO;
111 out = OPENSSL_malloc(outLen);
114 WAE_SLOGE("Encrypt APP DEK Failed. OPENSSL_malloc failed");
115 ret = WAE_ERROR_MEMORY;
119 if (EVP_PKEY_encrypt(ctx, out, &outLen, dek, dekLen) <= 0) {
120 WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_encrypt failed");
121 ret = WAE_ERROR_CRYPTO;
126 *encryptedDekLen = outLen;
136 EVP_PKEY_CTX_free(ctx);
138 if (ret != WAE_ERROR_NONE && out != NULL)
144 int decrypt_app_dek(const unsigned char *rsaPrivateKey, size_t priKeyLen,
145 const char *priKeyPassword,
146 const unsigned char *encryptedDek, size_t dencryptedDekLen,
147 unsigned char **decryptedDek, size_t *decryptedDekLen)
149 int ret = WAE_ERROR_NONE;
150 EVP_PKEY *pKey = NULL;
152 EVP_PKEY_CTX *ctx = NULL;
153 unsigned char *out = NULL;
158 bio = BIO_new(BIO_s_mem());
159 BIO_write(bio, rsaPrivateKey, priKeyLen);
160 pKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)priKeyPassword);
164 BIO_write(bio, rsaPrivateKey, priKeyLen);
165 pKey = d2i_PrivateKey_bio(bio, NULL);
169 ret = WAE_ERROR_FILE;
170 WAE_SLOGE("Failt to convert to public key.");
174 ctx = EVP_PKEY_CTX_new(pKey, NULL);
177 WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_new failed");
178 ret = WAE_ERROR_CRYPTO;
182 if (EVP_PKEY_decrypt_init(ctx) <= 0) {
183 WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt_init failed");
184 ret = WAE_ERROR_CRYPTO;
188 if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) {
189 WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_CTX_set_rsa_padding failed");
190 ret = WAE_ERROR_CRYPTO;
194 /* Determine buffer length */
195 if (EVP_PKEY_decrypt(ctx, NULL, &outLen, encryptedDek, dencryptedDekLen) <= 0) {
196 WAE_SLOGE("Decrypt APP DEK Failed. EVP_PKEY_decrypt failed");
197 ret = WAE_ERROR_CRYPTO;
201 out = OPENSSL_malloc(outLen);
204 WAE_SLOGE("Decrypt APP DEK Failed. OPENSSL_malloc failed");
205 ret = WAE_ERROR_MEMORY;
209 if (EVP_PKEY_decrypt(ctx, out, &outLen, encryptedDek, dencryptedDekLen) <= 0) {
210 WAE_SLOGE("Encrypt APP DEK Failed. EVP_PKEY_decrypt failed");
211 ret = WAE_ERROR_CRYPTO;
216 *decryptedDekLen = outLen;
226 EVP_PKEY_CTX_free(ctx);
228 if (ret != WAE_ERROR_NONE && out != NULL)
235 int encrypt_aes_cbc(const unsigned char *pKey, size_t keyLen,
236 const unsigned char *pData, size_t dataLen,
237 unsigned char **ppEncryptedData, size_t *pEncDataLen)
241 unsigned char *ciphertext = NULL;
242 size_t ciphertext_len;
243 unsigned char *iv = AES_CBC_IV;
244 int ret = WAE_ERROR_NONE;
248 WAE_SLOGI("Encryption Started. size=%d", dataLen);
250 /* check input paramter */
252 WAE_SLOGE("Encryption Failed. Invalid Key Length. keyLen=%d", keyLen);
253 return WAE_ERROR_INVALID_PARAMETER;
256 // assing a enough memory for decryption.
257 ciphertext = (unsigned char *) malloc(dataLen + 32);
259 /* Create and initialise the context */
260 if (!(ctx = EVP_CIPHER_CTX_new())) {
261 WAE_SLOGE("Encryption Failed. EVP_CIPHER_CTX_new failed");
262 ret = WAE_ERROR_CRYPTO;
266 /* Initialise the encryption operation. IMPORTANT - ensure you use a key
267 * and IV size appropriate for your cipher
268 * In this example we are using 256 bit AES (i.e. a 256 bit key). The
269 * IV size for *most* modes is the same as the block size. For AES this
271 if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) {
272 WAE_SLOGE("Encryption Failed. EVP_EncryptInit_ex failed");
273 ret = WAE_ERROR_CRYPTO;
277 /* Provide the message to be encrypted, and obtain the encrypted output.
278 * EVP_EncryptUpdate can be called multiple times if necessary
280 if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, pData, dataLen)) {
281 WAE_SLOGE("Encryption Failed. EVP_EncryptUpdate failed");
282 ret = WAE_ERROR_CRYPTO;
286 ciphertext_len = len;
288 /* Finalise the encryption. Further ciphertext bytes may be written at
291 if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
292 WAE_SLOGE("Encryption Failed. EVP_EncryptFinal_ex failed");
293 ret = WAE_ERROR_CRYPTO;
297 ciphertext_len += len;
299 *ppEncryptedData = ciphertext;
300 *pEncDataLen = ciphertext_len;
302 ret = WAE_ERROR_NONE;
303 WAE_SLOGI("Encryption Ended Successfully. encrypted_len", ciphertext_len);
307 EVP_CIPHER_CTX_free(ctx);
309 if (ret != WAE_ERROR_NONE && ciphertext != NULL)
315 int decrypt_aes_cbc(const unsigned char *pKey, size_t keyLen,
316 const unsigned char *pData, size_t dataLen,
317 unsigned char **ppDecryptedData, size_t *pDecDataLen)
321 unsigned char *plaintext = NULL;
322 size_t plaintext_len;
323 unsigned char *iv = AES_CBC_IV;
324 int ret = WAE_ERROR_NONE;
328 WAE_SLOGI("Decryption Started. size=%d", dataLen);
330 /* check input paramter */
332 WAE_SLOGE("Decryption Failed. Invalid Key Length. keyLen=%d", keyLen);
333 return WAE_ERROR_INVALID_PARAMETER;
336 // assing a enough memory for decryption.
337 plaintext = (unsigned char *) malloc(dataLen);
339 /* Create and initialise the context */
340 if (!(ctx = EVP_CIPHER_CTX_new())) {
341 WAE_SLOGE("Decryption Failed. EVP_CIPHER_CTX_new failed");
342 ret = WAE_ERROR_CRYPTO;
346 /* Initialise the decryption operation. IMPORTANT - ensure you use a key
347 * and IV size appropriate for your cipher
348 * In this example we are using 256 bit AES (i.e. a 256 bit key). The
349 * IV size for *most* modes is the same as the block size. For AES this
351 if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, pKey, iv)) {
352 WAE_SLOGE("Decryption Failed. EVP_DecryptInit_ex failed");
353 ret = WAE_ERROR_CRYPTO;
357 /* Provide the message to be decrypted, and obtain the plaintext output.
358 * EVP_DecryptUpdate can be called multiple times if necessary
360 if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, pData, dataLen)) {
361 WAE_SLOGE("Decryption Failed. EVP_DecryptUpdate failed");
362 ret = WAE_ERROR_CRYPTO;
368 /* Finalise the decryption. Further plaintext bytes may be written at
371 if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) {
372 WAE_SLOGE("Decryption Failed. EVP_DecryptFinal_ex failed");
373 ret = WAE_ERROR_CRYPTO;
377 plaintext_len += len;
379 *ppDecryptedData = plaintext;
380 *pDecDataLen = plaintext_len;
382 ret = WAE_ERROR_NONE;
383 WAE_SLOGI("Decryption Ended Successfully. decrypted_len", plaintext_len);
387 EVP_CIPHER_CTX_free(ctx);
389 if (ret != WAE_ERROR_NONE && plaintext != NULL)