diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:48:48 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:48:48 +0900 |
commit | e0eadfbda442a8a655185b2969889994004b8099 (patch) | |
tree | 2382a0f456cbcfd24a7a5d6a9a2375620fed6b9e /email-core/email-core-smime.c | |
parent | 4c73c3e1e4085d17f8f9cfe0ec4c41bc9e0cb826 (diff) | |
download | email-service-e0eadfbda442a8a655185b2969889994004b8099.tar.gz email-service-e0eadfbda442a8a655185b2969889994004b8099.tar.bz2 email-service-e0eadfbda442a8a655185b2969889994004b8099.zip |
Tizen 2.1 base
Diffstat (limited to 'email-core/email-core-smime.c')
-rwxr-xr-x | email-core/email-core-smime.c | 943 |
1 files changed, 943 insertions, 0 deletions
diff --git a/email-core/email-core-smime.c b/email-core/email-core-smime.c new file mode 100755 index 0000000..7783144 --- /dev/null +++ b/email-core/email-core-smime.c @@ -0,0 +1,943 @@ +/* +* email-service +* +* Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved. +* +* Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com> +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ + + + +/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *** + *File : email-core-smime.c + *Desc : MIME Operation + * + *Auth : + * + *History : + * 2011.04.14 : created + ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ***/ +#undef close + +#include <openssl/pkcs7.h> +#include <openssl/pkcs12.h> +#include <openssl/buffer.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +#include "email-utilities.h" +#include "email-core-global.h" +#include "email-core-utils.h" +#include "email-core-mail.h" +#include "email-core-smtp.h" +#include "email-storage.h" +#include "email-core-smime.h" +#include "email-core-cert.h" +#include "email-debug-log.h" + +/* /opt/share/cert-svc/certs is a base path */ + +#define SMIME_SIGNED_FILE "smime.p7s" +#define SMIME_ENCRYPT_FILE "smime.p7m" +#define DECRYPT_TEMP_FILE "decrypt_temp_file.eml" + +/* If not present then the default digest algorithm for signing key will be used SHA1 */ +static const EVP_MD *emcore_get_digest_algorithm(email_digest_type digest_type) +{ + const EVP_MD *digest_algo = NULL; + + switch (digest_type) { + case DIGEST_TYPE_MD5: + digest_algo = EVP_md5(); + break; + case DIGEST_TYPE_SHA1: + default: + digest_algo = EVP_sha1(); + break; + } + + return digest_algo; +} + +/* If not present then the default cipher algorithm for signing key will be used RC2(40) */ +static const EVP_CIPHER *emcore_get_cipher_algorithm(email_cipher_type cipher_type) +{ + const EVP_CIPHER *cipher = NULL; + + switch (cipher_type) { + case CIPHER_TYPE_RC2_128 : + cipher = EVP_rc2_cbc(); + break; + case CIPHER_TYPE_RC2_64 : + cipher = EVP_rc2_64_cbc(); + break; + case CIPHER_TYPE_DES3 : + cipher = EVP_des_ede3_cbc(); + break; + case CIPHER_TYPE_DES : + cipher = EVP_des_cbc(); + break; +#ifdef __FEATURE_USE_MORE_CIPHER_TYPE__ + case CIPHER_TYPE_SEED : + cipher = EVP_seed_cbc(); + break; + case CIPHER_TYPE_AES128 : + cipher = EVP_aes_128_cbc(); + break; + case CIPHER_TYPE_AES192 : + cipher = EVP_aes_192_cbc(); + break; + case CIPHER_TYPE_AES256 : + cipher = EVP_aes_256_cbc(); + break; +#ifndef OPENSSL_NO_CAMELLIA + case CIPHER_TYPE_CAMELLIA128 : + cipher = EVP_camellia_128_cbc(); + break; + case CIPHER_TYPE_CAMELLIA192 : + cipher = EVP_camellia_192_cbc(); + break; + case CIPHER_TYPE_CAMELLIA256 : + cipher = EVP_camellia_256_cbc(); + break; +#endif +#endif + case CIPHER_TYPE_RC2_40 : + default : + cipher = EVP_rc2_40_cbc(); + break; + } + + return cipher; +} + +static int get_x509_stack_of_recipient_certs(char *recipients, STACK_OF(X509) **output_recipient_certs, int *err_code) +{ + EM_DEBUG_FUNC_BEGIN("recipients : [%s], STACK_OF(X509) : [%p]", recipients, output_recipient_certs); + + int err = EMAIL_ERROR_NONE; + int ret = false; + int cert_size = 0; + char *temp_recipients = NULL; + char *token = NULL; + char *str = NULL; + char file_name[512] = {0, }; + const unsigned char *in_cert = NULL; + + X509 *x509_cert = NULL; + STACK_OF(X509) *temp_recipient_certs = NULL; + + CERT_CONTEXT *context = NULL; + emstorage_certificate_tbl_t *cert = NULL; + + if (!recipients || !output_recipient_certs) { + EM_DEBUG_EXCEPTION("Invalid parameter"); + err = EMAIL_ERROR_INVALID_PARAM; + goto FINISH_OFF; + } + + /* Initialize the variable */ + context = cert_svc_cert_context_init(); + temp_recipient_certs = sk_X509_new_null(); + + temp_recipients = EM_SAFE_STRDUP(recipients); + temp_recipients = em_replace_all_string(temp_recipients, ",", ";"); + token = strtok_r(temp_recipients, ";", &str); + + do { + if (!emstorage_get_certificate_by_email_address(token, &cert, false, 0, &err)) { + EM_DEBUG_EXCEPTION("emstorage_get_certificate_by_email_address failed : [%d]", err); + goto FINISH_OFF; + } + + SNPRINTF(file_name, sizeof(file_name), "%s", cert->filepath); + EM_DEBUG_LOG("file_name : [%s]", file_name); + err = cert_svc_load_file_to_context(context, file_name); + if (err != CERT_SVC_ERR_NO_ERROR) { + EM_DEBUG_EXCEPTION("cert_svc_load_file_to_context failed : [%d]", err); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + in_cert = context->certBuf->data; + cert_size = context->certBuf->size; + + if (d2i_X509(&x509_cert, &in_cert, cert_size) == NULL) { + EM_DEBUG_EXCEPTION("d2i_X509 failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + if (!sk_X509_push(temp_recipient_certs, x509_cert)) { + EM_DEBUG_EXCEPTION("sk_X509_push failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + x509_cert = NULL; + context = NULL; + emstorage_free_certificate(&cert, 1, NULL); + cert = NULL; + } while ((token = strtok_r(NULL, ";", &str))); + + *output_recipient_certs = temp_recipient_certs; + + ret = true; + +FINISH_OFF: + + if (!ret) { + if (x509_cert) + X509_free(x509_cert); + + if (temp_recipient_certs) + sk_X509_pop_free(temp_recipient_certs, X509_free); + } + + if (cert) + emstorage_free_certificate(&cert, 1, NULL); + + cert_svc_cert_context_final(context); + + EM_SAFE_FREE(temp_recipients); + + if (err_code) + *err_code = err; + + return ret; +} + +/* Opaque signed and encrypted method */ +/* +static PKCS7 *opaque_signed_and_encrypt(STACK_OF(X509) *recipients_cert, X509 *signer, EVP_PKEY *private_key, BIO *mime_entity, const EVP_CIPHER *cipher, const EVP_MD *md, int flags) +{ + EM_DEBUG_FUNC_BEGIN(); + int i = 0; + PKCS7 *pkcs7 = NULL; + BIO *p7bio = NULL; + X509 *x509; + + if (!(pkcs7 = PKCS7_new())) { + EM_DEBUG_EXCEPTION("PKCS7 malloc failed"); + return NULL; + } + + if (!PKCS7_set_type(pkcs7, NID_pkcs7_signedAndEnveloped)) { + EM_DEBUG_EXCEPTION("Set type failed"); + goto FINISH_OFF; + } + + if (!PKCS7_add_signature(pkcs7, signer, private_key, md)) { + EM_DEBUG_EXCEPTION("PKCS7_add_signature failed"); + goto FINISH_OFF; + } + + if (!PKCS7_add_certificate(pkcs7, signer)) { + EM_DEBUG_EXCEPTION("PKCS7_add_certificate failed"); + goto FINISH_OFF; + } + + for (i = 0; i < sk_X509_num(recipients_cert); i++) { + x509 = sk_X509_value(recipients_cert, i); + if (!PKCS7_add_recipient(pkcs7, x509)) { + EM_DEBUG_EXCEPTION("PKCS7_add_recipient failed"); + goto FINISH_OFF; + } + } + + if (!PKCS7_set_cipher(pkcs7, cipher)) { + EM_DEBUG_EXCEPTION("Cipher failed"); + goto FINISH_OFF; + } + + if (flags & PKCS7_STREAM) + return pkcs7; + + if (PKCS7_final(pkcs7, mime_entity, flags)) + return pkcs7; + +FINISH_OFF: + BIO_free_all(p7bio); + PKCS7_free(pkcs7); + return NULL; +} +*/ + +INTERNAL_FUNC int emcore_smime_set_signed_message(char *certificate, char *mime_entity, email_digest_type digest_type, char **file_path, int *err_code) +{ + EM_DEBUG_FUNC_BEGIN("certificate path : [%s], mime_entity : [%s]", certificate, mime_entity); + int err, ret = false; + char temp_smime_filepath[512]; + X509 *cert = NULL; + STACK_OF(X509) *other_certs = NULL; + EVP_PKEY *private_key = NULL; + const EVP_MD *digest = NULL; + BIO *bio_mime_entity = NULL, *bio_cert = NULL, *bio_prikey = NULL; + BIO *smime_attachment = NULL; + PKCS7 *signed_message = NULL; + int flags = PKCS7_DETACHED | PKCS7_PARTIAL; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + SNPRINTF(temp_smime_filepath, sizeof(temp_smime_filepath), "%s%s%s", MAILTEMP, DIR_SEPERATOR, SMIME_SIGNED_FILE); + EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_smime_filepath); + + smime_attachment = BIO_new_file(temp_smime_filepath, OUTMODE); + if (!smime_attachment) { + EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_smime_filepath); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* Load certificate for getting the certificate and private key */ + if (!emcore_load_PFX_file(certificate, &private_key, &cert, &other_certs, &err)) { + EM_DEBUG_EXCEPTION("Load the private certificate failed : [%d]", err); + goto FINISH_OFF; + } + + bio_mime_entity = BIO_new_file(mime_entity, READMODE); + if (!bio_mime_entity) { + EM_DEBUG_EXCEPTION("Cannot open file[%s]", mime_entity); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + signed_message = PKCS7_sign(NULL, NULL, other_certs, bio_mime_entity, flags); + if (!signed_message) { + EM_DEBUG_EXCEPTION("Error creating PKCS#7 structure"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* Get the digest algorithm */ + digest = emcore_get_digest_algorithm(digest_type); + + if (!PKCS7_sign_add_signer(signed_message, cert, private_key, digest, flags)) { + EM_DEBUG_EXCEPTION("PKCS7_sign_add_signer failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + if (!PKCS7_final(signed_message, bio_mime_entity, flags)) { + EM_DEBUG_EXCEPTION("PKCS7_final failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + if (!i2d_PKCS7_bio_stream(smime_attachment, signed_message, bio_mime_entity, flags)) { + EM_DEBUG_EXCEPTION("i2d_PKCS7_bio_stream failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + BIO_flush(smime_attachment); + ret = true; + +FINISH_OFF: + if (file_path && ret) + *file_path = EM_SAFE_STRDUP(temp_smime_filepath); + + X509_free(cert); + sk_X509_pop_free(other_certs, X509_free); + EVP_PKEY_free(private_key); + PKCS7_free(signed_message); + + BIO_free(bio_mime_entity); + BIO_free(bio_cert); + BIO_free(bio_prikey); + BIO_free_all(smime_attachment); + + EVP_cleanup(); + if (err_code != NULL) + *err_code = err; + + EM_DEBUG_FUNC_END("err [%d]", err); + return ret; +} + +INTERNAL_FUNC int emcore_smime_set_encrypt_message(char *recipient_list, char *mime_entity, email_cipher_type cipher_type, char **file_path, int *err_code) +{ + EM_DEBUG_FUNC_BEGIN("certificate path : [%p], mime_entity : [%p]", recipient_list, mime_entity); + char temp_smime_filepath[512]; + int err = EMAIL_ERROR_NONE, ret = false; +// int flags = PKCS7_DETACHED | PKCS7_STREAM; + int flags = 0; + + CERT_CONTEXT *loaded_cert = NULL; + STACK_OF(X509) *recipient_certs = NULL; + X509 *cert = NULL; + BIO *bio_mime_entity = NULL, *bio_cert = NULL; + BIO *smime_attachment = NULL; + PKCS7 *encrypt_message = NULL; + const EVP_CIPHER *cipher = NULL; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + loaded_cert = cert_svc_cert_context_init(); + + SNPRINTF(temp_smime_filepath, sizeof(temp_smime_filepath), "%s%s%s", MAILTEMP, DIR_SEPERATOR, SMIME_ENCRYPT_FILE); + EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_smime_filepath); + + smime_attachment = BIO_new_file(temp_smime_filepath, OUTMODE); + if (!smime_attachment) { + EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_smime_filepath); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + if (!get_x509_stack_of_recipient_certs(recipient_list, &recipient_certs, &err)) { + EM_DEBUG_EXCEPTION("get_x509_stack_of_recipient_certs failed [%d]", err); + goto FINISH_OFF; + } + + bio_mime_entity = BIO_new_file(mime_entity, READMODE); + if (!bio_mime_entity) { + EM_DEBUG_EXCEPTION("Cannot open file[%s]", mime_entity); + goto FINISH_OFF; + } + + /* Get cipher algorithm */ + cipher = emcore_get_cipher_algorithm(cipher_type); + + encrypt_message = PKCS7_encrypt(recipient_certs, bio_mime_entity, cipher, flags); + if (encrypt_message == NULL) { + EM_DEBUG_EXCEPTION("PKCS7_encrypt failed [%ld]", ERR_get_error()); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + if (!i2d_PKCS7_bio_stream(smime_attachment, encrypt_message, bio_mime_entity, flags)) { + EM_DEBUG_EXCEPTION("i2d_PKCS7_bio_stream failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + BIO_flush(smime_attachment); + + ret = true; + +FINISH_OFF: + if (file_path && ret) + *file_path = EM_SAFE_STRDUP(temp_smime_filepath); + + PKCS7_free(encrypt_message); + + X509_free(cert); + sk_X509_pop_free(recipient_certs, X509_free); + + BIO_free(bio_cert); + BIO_free(bio_mime_entity); + BIO_free_all(smime_attachment); + + cert_svc_cert_context_final(loaded_cert); + EVP_cleanup(); + if (err_code != NULL) + *err_code = err; + + EM_DEBUG_FUNC_END("err [%d]", err); + return ret; +} + +INTERNAL_FUNC int emcore_smime_set_signed_and_encrypt_message(char *recipient_list, char *certificate, char *mime_entity, email_cipher_type cipher_type, email_digest_type digest_type, char **file_path, int *err_code) +{ + EM_DEBUG_FUNC_BEGIN("certificate path : [%s], mime_entity : [%s]", recipient_list, mime_entity); + char temp_smime_filepath[512]; + int err = EMAIL_ERROR_NONE, ret = false; + int flags = PKCS7_DETACHED | PKCS7_PARTIAL | PKCS7_STREAM; + + STACK_OF(X509) *recipient_certs = NULL; + STACK_OF(X509) *other_certs = NULL; + BIO *bio_mime_entity = NULL, *bio_cert = NULL; + BIO *bio_signed_message = BIO_new(BIO_s_mem()); + BIO *smime_attachment = NULL; + PKCS7 *signed_message = NULL; + PKCS7 *encrypt_message = NULL; + const EVP_CIPHER *cipher = NULL; + const EVP_MD *digest = NULL; + + /* Variable for private certificate */ + EVP_PKEY *private_key = NULL; + X509 *cert = NULL; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + SNPRINTF(temp_smime_filepath, sizeof(temp_smime_filepath), "%s%s%s", MAILTEMP, DIR_SEPERATOR, SMIME_ENCRYPT_FILE); + EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_smime_filepath); + + smime_attachment = BIO_new_file(temp_smime_filepath, OUTMODE); + if (!smime_attachment) { + EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_smime_filepath); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* Signing the mail */ + /* 1. Load the private certificate */ + if (!emcore_load_PFX_file(certificate, &private_key, &cert, &other_certs, &err)) { + EM_DEBUG_EXCEPTION("Load the private certificate failed : [%d]", err); + goto FINISH_OFF; + } + + /* 2. Read mime entity */ + bio_mime_entity = BIO_new_file(mime_entity, READMODE); + if (!bio_mime_entity) { + EM_DEBUG_EXCEPTION("Cannot open file[%s]", mime_entity); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* 3. signing */ + signed_message = PKCS7_sign(NULL, NULL, other_certs, bio_mime_entity, flags); + if (!signed_message) { + EM_DEBUG_EXCEPTION("Error creating PKCS#7 structure"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* 4. Get the digest algorithm */ + digest = emcore_get_digest_algorithm(digest_type); + + /* 5. Apply a digest algorithm */ + if (!PKCS7_sign_add_signer(signed_message, cert, private_key, digest, flags)) { + EM_DEBUG_EXCEPTION("PKCS7_sign_add_signer failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* 6. Create signing message */ + if (!SMIME_write_PKCS7(bio_signed_message, signed_message, bio_mime_entity, flags | SMIME_OLDMIME | SMIME_CRLFEOL)) { + EM_DEBUG_EXCEPTION("SMIME_write_PKCS7 error"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* Encrypting the mail */ + /* 1. Get the recipient certs */ + if (!get_x509_stack_of_recipient_certs(recipient_list, &recipient_certs, &err)) { + EM_DEBUG_EXCEPTION("get_x509_stack_of_recipient_certs failed [%d]", err); + goto FINISH_OFF; + } + + /* 2. Get cipher algorithm */ + cipher = emcore_get_cipher_algorithm(cipher_type); + + flags = 0; + + /* 3. Encrypt the signing message */ + encrypt_message = PKCS7_encrypt(recipient_certs, bio_signed_message, cipher, flags); + if (encrypt_message == NULL) { + EM_DEBUG_EXCEPTION("PKCS7_encrypt failed [%ld]", ERR_get_error()); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* 4. Write the encrypt message in file */ + if (!i2d_PKCS7_bio_stream(smime_attachment, encrypt_message, bio_mime_entity, flags)) { + EM_DEBUG_EXCEPTION("i2d_PKCS7_bio_stream failed"); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + BIO_flush(smime_attachment); + + ret = true; + +FINISH_OFF: + if (file_path && ret) + *file_path = EM_SAFE_STRDUP(temp_smime_filepath); + + PKCS7_free(signed_message); + PKCS7_free(encrypt_message); + EVP_PKEY_free(private_key); + + X509_free(cert); + sk_X509_pop_free(other_certs, X509_free); + sk_X509_pop_free(recipient_certs, X509_free); + + BIO_free(bio_cert); + BIO_free(bio_mime_entity); + BIO_free(bio_signed_message); + BIO_free_all(smime_attachment); + + EVP_cleanup(); + if (err_code != NULL) + *err_code = err; + + EM_DEBUG_FUNC_END("err [%d]", err); + return ret; +} + + + +INTERNAL_FUNC int emcore_smime_set_decrypt_message(char *encrypt_message, char *certificate, char **decrypt_message, int *err_code) +{ + EM_DEBUG_FUNC_BEGIN("encrypt_file : [%s], certificate : [%s]", encrypt_message, certificate); + int ret = false; + int err = EMAIL_ERROR_NONE; + char temp_decrypt_filepath[512] = {0, }; + + X509 *cert = NULL; + EVP_PKEY *private_key = NULL; + BIO *infile = NULL, *out_buf = NULL; + PKCS7 *p7_encrypt_message = NULL; + STACK_OF(X509) *recipient_certs = NULL; + + OpenSSL_add_all_algorithms(); + + /* Load the encrypted message */ + infile = BIO_new_file(encrypt_message, INMODE); + if (infile == NULL) { + EM_DEBUG_EXCEPTION("Cannot open output file %s", encrypt_message); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + p7_encrypt_message = d2i_PKCS7_bio(infile, NULL); + if (!p7_encrypt_message) { + EM_DEBUG_EXCEPTION("Error reading S/MIME message"); + err = EMAIL_ERROR_INVALID_PARAM; + goto FINISH_OFF; + } + + /* Initialize the output file for decrypted message */ + SNPRINTF(temp_decrypt_filepath, sizeof(temp_decrypt_filepath), "%s%s%s", MAILTEMP, DIR_SEPERATOR, DECRYPT_TEMP_FILE); + EM_DEBUG_LOG("attachment file path of smime : [%s]", temp_decrypt_filepath); + + out_buf = BIO_new_file(temp_decrypt_filepath, OUTMODE); + if (!out_buf) { + EM_DEBUG_EXCEPTION("Cannot open output file %s", temp_decrypt_filepath); + err = EMAIL_ERROR_SYSTEM_FAILURE; + goto FINISH_OFF; + } + + /* Search private cert */ + if (!emcore_load_PFX_file(certificate, &private_key, &cert, NULL, &err)) { + EM_DEBUG_EXCEPTION("Load the private certificate failed : [%d]", err); + goto FINISH_OFF; + } + + if (!PKCS7_decrypt(p7_encrypt_message, private_key, cert, out_buf, 0)) { + EM_DEBUG_EXCEPTION("Decrpyt failed"); + err = EMAIL_ERROR_DECRYPT_FAILED; + goto FINISH_OFF; + } + + ret = true; + +FINISH_OFF: + + if (decrypt_message && ret) + *decrypt_message = EM_SAFE_STRDUP(temp_decrypt_filepath); + + EVP_cleanup(); + X509_free(cert); + EVP_PKEY_free(private_key); + BIO_free(out_buf); + BIO_free_all(infile); + sk_X509_pop_free(recipient_certs, X509_free); + + if (err_code != NULL) + *err_code = err; + + EM_DEBUG_FUNC_END("err [%d]", err); + return ret; +} + +/* +INTERNAL_FUNC int emcore_smime_verify_signed_message(char *signed_message, char *ca_file, char *ca_path, int *verify) +{ + int ret = false; + int temp_verify = 0; + BIO *indata = NULL; + BIO *content = NULL; + X509_STORE *store = NULL; + X509_LOOKUP *lookup = NULL; + PKCS7 *p7 = NULL; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + if (BIO_write(indata, signed_message, sizeof(signed_message)) <= 0) { + EM_DEBUG_EXCEPTION("Char to Bio failed"); + goto FINISH_OFF; + } + + p7 = SMIME_read_PKCS7(indata, &content); + if (!p7) { + EM_DEBUG_EXCEPTION("SMIME_read_PKCS7 failed"); + goto FINISH_OFF; + } + + if (!(store = X509_STORE_new())) { + EM_DEBUG_EXCEPTION("Initialize x509_store failed"); + goto FINISH_OFF; + } + + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) { + EM_DEBUG_EXCEPTION("Initialize lookup store failed"); + goto FINISH_OFF; + } + + if (ca_file) { + if (!X509_LOOKUP_load_file(lookup, ca_file, X509_FILETYPE_PEM)) { + EM_DEBUG_EXCEPTION("X509_LOOKUP_load_file failed"); + goto FINISH_OFF; + } + } else { + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + } + + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) { + EM_DEBUG_EXCEPTION("X509_STORE_add_lookup failed"); + goto FINISH_OFF; + } + + if (ca_path) { + if (!X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM)) { + EM_DEBUG_EXCEPTION("CA path load failed"); + goto FINISH_OFF; + } + } else { + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + } + + temp_verify = PKCS7_verify(p7, NULL, store, content, NULL, 0); + if (temp_verify) + EM_DEBUG_LOG("Verification Successful\n"); + + ret = true; + +FINISH_OFF: + if (store) + X509_STORE_free(store); + if (p7) + PKCS7_free(p7); + + if (indata) + BIO_free(indata); + + if (verify != NULL) + *verify = temp_verify; + + ERR_clear_error(); + EVP_cleanup(); + return ret; +} +*/ + +static char *emcore_set_mime_entity(char *mime_path) +{ + EM_DEBUG_FUNC_BEGIN("mime_path : [%s]", mime_path); + FILE *fp_read = NULL; + FILE *fp_write = NULL; + char *mime_entity = NULL; + char *mime_entity_path = NULL; + char temp_buffer[255] = {0,}; + int err; + int searched = 0; + + if (!emcore_get_temp_file_name(&mime_entity_path, &err)) { + EM_DEBUG_EXCEPTION(" em_core_get_temp_file_name failed[%d]", err); + goto FINISH_OFF; + } + + /* get mime entity */ + if (mime_path != NULL) { + fp_read = fopen(mime_path, "r"); + if (fp_read == NULL) { + EM_DEBUG_EXCEPTION("File open(read) is failed : filename [%s]", mime_path); + goto FINISH_OFF; + } + + fp_write = fopen(mime_entity_path, "w"); + if (fp_write == NULL) { + EM_DEBUG_EXCEPTION("File open(write) is failed : filename [%s]", mime_entity_path); + goto FINISH_OFF; + } + + fseek(fp_read, 0, SEEK_SET); + fseek(fp_write, 0, SEEK_SET); + + while (fgets(temp_buffer, 255, fp_read) != NULL) { + mime_entity = strcasestr(temp_buffer, "content-type"); + if (mime_entity != NULL && !searched) + searched = 1; + + if (searched) { + EM_DEBUG_LOG("temp_buffer : %s", temp_buffer); + fprintf(fp_write, "%s", temp_buffer); + } + } + } + +FINISH_OFF: + if (fp_read) + fclose(fp_read); + + if (fp_write) + fclose(fp_write); + + EM_SAFE_FREE(mime_entity); + EM_SAFE_FREE(mime_path); + + EM_DEBUG_FUNC_END(); + return mime_entity_path; +} + +INTERNAL_FUNC int emcore_convert_mail_data_to_smime_data(emstorage_account_tbl_t *account_tbl_item, email_mail_data_t *input_mail_data, email_attachment_data_t *input_attachment_data_list, int input_attachment_count, email_mail_data_t **output_mail_data, email_attachment_data_t **output_attachment_data_list, int *output_attachment_count) +{ + EM_DEBUG_FUNC_BEGIN("input_mail_data[%p], input_attachment_data_list [%p], input_attachment_count [%d], output_mail_data [%p], output_attachment_data_list [%p]", input_mail_data, input_attachment_data_list, input_attachment_count, output_mail_data, output_attachment_data_list); + + int ret = false; + int err = EMAIL_ERROR_NONE; + int smime_type = EMAIL_SMIME_NONE; + int address_length = 0; + int attachment_count = input_attachment_count; + int file_size = 0; + char *name = NULL; + char *rfc822_file = NULL; + char *mime_entity = NULL; + char *smime_file_path = NULL; + char *other_certificate_list = NULL; + email_attachment_data_t new_attachment_data = {0}; + email_attachment_data_t *new_attachment_list = NULL; + + /* Validating parameters */ + + if (!input_mail_data || !(input_mail_data->account_id) || !(input_mail_data->mailbox_id)) { + EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM"); + err = EMAIL_ERROR_INVALID_PARAM; + goto FINISH_OFF; + } + + if (!emcore_make_rfc822_file(input_mail_data, input_attachment_data_list, attachment_count, &rfc822_file, &err)) { + EM_DEBUG_EXCEPTION("emcore_make_rfc822_file failed [%d]", err); + goto FINISH_OFF; + } + + mime_entity = emcore_set_mime_entity(rfc822_file); + + smime_type = input_mail_data->smime_type; + if (!smime_type) + smime_type = account_tbl_item->smime_type; + + /* Signed and Encrypt the message */ + switch (smime_type) { + case EMAIL_SMIME_SIGNED: /* Clear signed message */ + if (!emcore_smime_set_signed_message(account_tbl_item->certificate_path, mime_entity, account_tbl_item->digest_type, &smime_file_path, &err)) { + EM_DEBUG_EXCEPTION("em_core_smime_set_clear_signed_message is failed : [%d]", err); + goto FINISH_OFF; + } + + EM_DEBUG_LOG("smime_file_path : %s", smime_file_path); + name = strrchr(smime_file_path, '/'); + + new_attachment_data.attachment_name = EM_SAFE_STRDUP(name + 1); + new_attachment_data.attachment_path = EM_SAFE_STRDUP(smime_file_path); + + attachment_count += 1; + + break; + case EMAIL_SMIME_ENCRYPTED: /* Encryption message */ + address_length = EM_SAFE_STRLEN(input_mail_data->full_address_to) + EM_SAFE_STRLEN(input_mail_data->full_address_cc) + EM_SAFE_STRLEN(input_mail_data->full_address_bcc); + + other_certificate_list = em_malloc(address_length + 3); + + SNPRINTF(other_certificate_list, address_length + 2, "%s;%s;%s", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc); + + EM_DEBUG_LOG("to:[%s], cc:[%s], bcc:[%s]", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc); + EM_DEBUG_LOG("length : [%d], email_address : [%s]", address_length, other_certificate_list); + + if (!emcore_smime_set_encrypt_message(other_certificate_list, mime_entity, account_tbl_item->cipher_type, &smime_file_path, &err)) { + EM_DEBUG_EXCEPTION("emcore_smime_set_encrypt_message is failed : [%d]", err); + goto FINISH_OFF; + } + + EM_DEBUG_LOG("smime_file_path : %s", smime_file_path); + name = strrchr(smime_file_path, '/'); + + new_attachment_data.attachment_name = EM_SAFE_STRDUP(name + 1); + new_attachment_data.attachment_path = EM_SAFE_STRDUP(smime_file_path); + + attachment_count = 1; + + break; + default: /* Signed and Encryption message */ + address_length = EM_SAFE_STRLEN(input_mail_data->full_address_to) + EM_SAFE_STRLEN(input_mail_data->full_address_cc) + EM_SAFE_STRLEN(input_mail_data->full_address_bcc); + + other_certificate_list = em_malloc(address_length + 3); + + SNPRINTF(other_certificate_list, address_length + 2, "%s;%s;%s", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc); + + EM_DEBUG_LOG("to:[%s], cc:[%s], bcc:[%s]", input_mail_data->full_address_to, input_mail_data->full_address_cc, input_mail_data->full_address_bcc); + EM_DEBUG_LOG("length : [%d], email_address : [%s]", address_length, other_certificate_list); + + if (!emcore_smime_set_signed_and_encrypt_message(other_certificate_list, account_tbl_item->certificate_path, mime_entity, account_tbl_item->cipher_type, account_tbl_item->digest_type, &smime_file_path, &err)) { + EM_DEBUG_EXCEPTION("em_core_smime_set_signed_and_encrypt_message is failed : [%d]", err); + goto FINISH_OFF; + } + + EM_DEBUG_LOG("smime_file_path : %s", smime_file_path); + name = strrchr(smime_file_path, '/'); + + new_attachment_data.attachment_name = EM_SAFE_STRDUP(name + 1); + new_attachment_data.attachment_path = EM_SAFE_STRDUP(smime_file_path); + + attachment_count = 1; + + break; + } + + if (!emcore_get_file_size(smime_file_path, &file_size, NULL)) { + EM_DEBUG_EXCEPTION("emcore_get_file_size failed"); + goto FINISH_OFF; + } + + new_attachment_data.attachment_size = file_size; + new_attachment_data.save_status = 1; + + new_attachment_list = (email_attachment_data_t *)em_malloc(sizeof(email_attachment_data_t) * attachment_count); + if (new_attachment_list == NULL) { + EM_DEBUG_EXCEPTION("em_malloc failed"); + goto FINISH_OFF; + } + + if (input_attachment_data_list != NULL) + new_attachment_list = input_attachment_data_list; + + new_attachment_list[attachment_count-1] = new_attachment_data; + + input_mail_data->smime_type = smime_type; + input_mail_data->file_path_mime_entity = EM_SAFE_STRDUP(mime_entity); + input_mail_data->digest_type = account_tbl_item->digest_type; + + ret = true; + +FINISH_OFF: + if (output_attachment_count) + *output_attachment_count = attachment_count; + + if (output_attachment_data_list) + *output_attachment_data_list = new_attachment_list; + + *output_mail_data = input_mail_data; + + return ret; +} + + |