Skip to content
Snippets Groups Projects

Resolve "SMIME Support"

Merged lazarog98 requested to merge 232-smime-support into dev
6 unresolved threads
Compare and Show latest version
5 files
+ 551
177
Compare changes
  • Side-by-side
  • Inline
Files
5
@@ -12,24 +12,33 @@ STACK_OF(X509)* create_stack_x509(X509 *arr, int len)
{
STACK_OF(X509) *stack = sk_X509_new_null();
int i = len;
while (i>0)
{
while (i>0) {
i--;
sk_X509_push(stack,&(arr[i]));
}
return stack;
}
X509* stack_to_array(STACK_OF(X509) *stack) {
X509 *arr = malloc(sizeof(X509)*sk_X509_num(stack));
char ** stack_to_array(STACK_OF(X509) *stack) {
char **str_arr = malloc(sizeof(char*)*sk_X509_num(stack));
int i = 0;
while (sk_X509_num(stack) > 0) {
arr[i] = *sk_X509_pop(stack);
BIO *out = BIO_new(BIO_s_mem());
char *tmp = NULL;
PEM_write_bio_X509(out, sk_X509_pop(stack));
long size = BIO_get_mem_data(out, &tmp);
char *str_perm = (char *) malloc(size+1);
memcpy(str_perm, tmp, size);
str_perm[size]=0; // To Nullterminate the string
str_arr[i] = str_perm;
i++;
BIO_free(out);
}
return arr;
return str_arr;
}
void OpenSSL_print_ver(void) {
@@ -37,7 +46,6 @@ void OpenSSL_print_ver(void) {
}
void OpenSSL_initialize(void) {
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
}
@@ -52,22 +60,82 @@ int print_test(int a) {
return 0;
}
char * OpenSSL_encrypt(const char *text, const char *pem) {
array_with_length *create_list_of_errors() {
unsigned long err = 0;
linked_list *head = NULL;
linked_list *cur = NULL;
int first = 1;
array_with_length *res = malloc(sizeof(array_with_length));
int length = 0;
unsigned long * arr = NULL;
while ((err = ERR_get_error()) != 0) {
linked_list * newerr = malloc(sizeof(linked_list));
newerr->content = malloc(sizeof(unsigned long));
memcpy(newerr->content, &err, sizeof(unsigned long));
newerr->content = (void*) err;
newerr->next = NULL;
if (first)
{
first=0;
head = newerr;
}
else
{
cur->next=newerr;
}
cur=newerr;
length++;
}
if (length) {
arr = malloc(sizeof(unsigned long*) * length);
linked_list *cur = head;
int i = 0;
while (cur != NULL) {
arr[i] = (unsigned long) cur->content;
linked_list *old = cur;
cur = cur->next;
free(old);
i++;
}
}
res->arr = arr;
res->size = length;
return res;
}
char *get_err_string(unsigned long err) {
ERR_load_crypto_strings();
const char *error = ERR_func_error_string(err);
//printf("\nError: %s", error);
char * error_permanent = (char *) malloc(strlen(error)+1);
error_permanent[strlen(error)]=0; // To Nullterminate the string
memcpy(error_permanent,error,strlen(error));
ERR_free_strings();
return error_permanent;
}
result * OpenSSL_encrypt(const char *text, const char *pem) {
// https://github.com/openssl/openssl/blob/master/demos/cms/cms_enc.c
OpenSSL_initialize();
char *encrypted = NULL, *tmp=NULL;;
// in = string to encrypt, out = encrypted string, rec_cert_bio =
OpenSSL_add_all_algorithms();
char *encrypted = NULL, *tmp=NULL;
BIO *in = NULL, *out = NULL, *rec_cert_bio = NULL;
// recipient certificate
X509 *rec_cert = NULL;
STACK_OF(X509) *cert_stack = NULL;
CMS_ContentInfo *cms = NULL;
unsigned long err = 0;
array_with_length *temp = NULL;
result *res = malloc(sizeof(result));
// this trick allows to hardcode a certificate as a string
rec_cert_bio = BIO_new_mem_buf(pem, (int) strlen(pem));
// rec_cert_bio = BIO_new_file("keys/mykey.pem", "r");
in = BIO_new_mem_buf(text, (int) strlen(text)); // simpletest
if (!rec_cert_bio) {
@@ -86,21 +154,19 @@ char * OpenSSL_encrypt(const char *text, const char *pem) {
// note that if the stack is initialized correctly, the recipient certificate is pushed as a test
if (!cert_stack || !sk_X509_push(cert_stack, rec_cert)) {
printf("Failed at push_stack");
printf("Failed at push_stack");
goto deinit;
}
cms = CMS_encrypt(cert_stack, in, EVP_aes_256_cbc(), CMS_STREAM);
if (!cms)
{
printf("Failed at P7enc");
if (!cms) {
printf("Failed at P7enc");
goto deinit;
}
out = BIO_new(BIO_s_mem());
if (!SMIME_write_CMS(out,cms,in,CMS_STREAM))
{
if (!SMIME_write_CMS(out,cms,in,CMS_STREAM)) {
printf("Failed at SMIME_WRITE");
goto deinit;
}
@@ -109,51 +175,55 @@ char * OpenSSL_encrypt(const char *text, const char *pem) {
long size = BIO_get_mem_data(out, &tmp);
encrypted= (char *) malloc(size+1);
encrypted[size]=0;//To Nullterminate the string
encrypted[size]=0; // To Nullterminate the string
memcpy(encrypted,tmp,size);
res->res = encrypted;
deinit:
// TODO: Collect all errors in a list and return them with the result
while ((err = ERR_get_error()) != 0) printf("\nError: %s", ERR_func_error_string(err));
temp = create_list_of_errors();
res->errors = temp->arr;
res->num_errors = temp->size;
free(temp);
CMS_ContentInfo_free(cms);
BIO_free(in);
BIO_free(out); //also frees tmp
BIO_free(out); // also frees tmp
BIO_free(rec_cert_bio);
X509_free(rec_cert);
OpenSSL_deinitialize();
// OpenSSL ver 1.0.2.f has a bug (seemingly) that causes a crash when freeing cms content info pointers
return (void*) encrypted;
return res;
}
char* OpenSSL_decrypt(const char *str, const char *pem) {
result * OpenSSL_decrypt(const char *str, const char *pem) {
// https://github.com/openssl/openssl/blob/master/demos/cms/cms_dec.c
OpenSSL_initialize();
char *decrypted = NULL, *tmp=NULL;
// https://github.com/openssl/openssl/blob/master/demos/cms/cms_dec.c
// in = string to encrypt, out = encrypted string, rec_cert_bio =
BIO *in = NULL, *out = NULL, *rec_cert_bio = NULL;
// recipient certificate
X509 *rec_cert = NULL;
CMS_ContentInfo *cms = NULL;
EVP_PKEY *rkey = NULL;
unsigned long err = 0;
result *res = malloc(sizeof(result));
array_with_length *temp = NULL;
// this trick allows to hardcode a certificate as a string
rec_cert_bio = BIO_new_mem_buf(pem, (int) strlen(pem));
// rec_cert_bio = BIO_new_file("keys/mykey.pem", "r");
in = BIO_new_mem_buf(str,(int) strlen(str)); // simpletest
if (!rec_cert_bio) {
printf("Failed reading mykey.pem!\n");
goto deinit;
}
rec_cert = PEM_read_bio_X509(rec_cert_bio, NULL, 0, NULL);
if (!rec_cert ) {
printf("Failed reading pem cert\n");
goto deinit;
}
BIO_reset(rec_cert_bio);
rkey = PEM_read_bio_PrivateKey(rec_cert_bio, NULL, 0, NULL);
@@ -164,38 +234,40 @@ char* OpenSSL_decrypt(const char *str, const char *pem) {
cms = SMIME_read_CMS(in, NULL);
if (!cms)
{
if (!cms) {
printf("DEC Failed at SMIME_READ");
while ((err = ERR_get_error()) != 0) printf("\nSMIME ERROR: %s", ERR_func_error_string(err));
goto deinit;
}
out = BIO_new(BIO_s_mem());
if (!CMS_decrypt(cms, rkey, rec_cert, NULL, out, CMS_STREAM))
{
if (!CMS_decrypt(cms, rkey, rec_cert, NULL, out, CMS_STREAM)) {
printf("Failed at Decrypt");
goto deinit;
}
long size = BIO_get_mem_data(out, &tmp);
decrypted= (char *) malloc(size+1);
decrypted[size]=0;//To Nullterminate the string
decrypted[size]=0; // To Nullterminate the string
memcpy(decrypted, tmp, size);
res->res = decrypted;
deinit:
temp = create_list_of_errors();
res->errors = temp->arr;
res->num_errors = temp->size;
free(temp);
CMS_ContentInfo_free(cms);
BIO_free(in);
BIO_free(out); //also frees tmp
BIO_free(out); // also frees tmp
BIO_free(rec_cert_bio);
X509_free(rec_cert);
OpenSSL_deinitialize();
// OpenSSL ver 1.0.2.f has a bug (seemingly) that causes a crash when freeing cms content info pointers
return decrypted;
return res;
}
char * OpenSSL_sign(const char *text, const char *pem, const int detached)
result * OpenSSL_sign(const char *text, const char *pem, const int detached)
{
OpenSSL_initialize();
char *mail = NULL, *tmp=NULL;
@@ -206,11 +278,12 @@ char * OpenSSL_sign(const char *text, const char *pem, const int detached)
CMS_ContentInfo *cms = NULL;
EVP_PKEY *skey = NULL;
int flags = CMS_STREAM | CMS_PARTIAL;
unsigned long err = 0;
result *res = malloc(sizeof(result));
array_with_length *temp = NULL;
if (detached) flags |= CMS_DETACHED;
// rec_cert_bio = BIO_new_file("keys/mykey.pem", "r");
in = BIO_new_mem_buf(text,(int) strlen(text)); // simpletest
sig_cert_bio = BIO_new_mem_buf(pem, (int) strlen(pem));
@@ -242,22 +315,17 @@ char * OpenSSL_sign(const char *text, const char *pem, const int detached)
}
cms = CMS_sign(NULL, NULL, NULL, in, flags);
if (!cms)
{
while ((err = ERR_get_error()) != 0) printf("\nFailed at signstart: %s", ERR_func_error_string(err));
if (!cms) {
goto deinit;
}
if (!CMS_add1_signer(cms, sig_cert, skey, EVP_sha256(), flags))
{
while ((err = ERR_get_error()) != 0) printf("\nFailed at signeradd: %s", ERR_func_error_string(err));
if (!CMS_add1_signer(cms, sig_cert, skey, EVP_sha256(), flags)) {
goto deinit;
}
out = BIO_new(BIO_s_mem());
if (!SMIME_write_CMS(out,cms,in,flags))
{
if (!SMIME_write_CMS(out,cms,in,flags)) {
printf("Failed at SMIME_WRITE");
goto deinit;
}
@@ -266,106 +334,152 @@ char * OpenSSL_sign(const char *text, const char *pem, const int detached)
long size = BIO_get_mem_data(out, &tmp);
mail= (char *) malloc(size+1);
mail[size]=0;//To Nullterminate the string
mail[size]=0; // to Nullterminate the string
memcpy(mail,tmp,size);
res->res = mail;
deinit:
temp = create_list_of_errors();
res->errors = temp->arr;
res->num_errors = temp->size;
free(temp);
CMS_ContentInfo_free(cms);
BIO_free(in);
BIO_free(out); //also frees tmp
BIO_free(out); // also frees tmp
BIO_free(sig_cert_bio);
X509_free(sig_cert);
OpenSSL_deinitialize();
return mail;
return res;
}
struct SMIME_verification * OpenSSL_verify(const char *text, const char *pem_cert) {
struct SMIME_verification *ver = malloc(sizeof(struct SMIME_verification));
result * OpenSSL_verify(const char *text, char **pem_cert, const int num_certs) {
// https://github.com/openssl/openssl/blob/master/demos/cms/cms_dec.c
result *ver = malloc(sizeof(result));
ver->certs = NULL;
ver->errors = NULL;
ver->res = NULL;
OpenSSL_initialize();
char *realtext = NULL, *tmp=NULL;
// https://github.com/openssl/openssl/blob/master/demos/cms/cms_dec.c
// in = string to encrypt, out = encrypted string, rec_cert_bio =
BIO *in = NULL, *out = NULL, *sig_cert_bio = NULL;
BIO *in = NULL, *out = NULL;
// recipient certificate
X509 *sig_cert = NULL;
X509 **sig_certs = malloc(num_certs*sizeof(X509));
STACK_OF(X509) *cert_stack= NULL;
X509_STORE *cert_store = NULL;
CMS_ContentInfo *cms = NULL;
BIO *detached = NULL;
unsigned long err =0;
array_with_length *temp = NULL;
cert_store = X509_STORE_new();
// this trick allows to hardcode a certificate as a string
sig_cert_bio = BIO_new_mem_buf(pem_cert, (int) strlen(pem_cert));
for (int i = 0; i<num_certs; i++) {
BIO *sig_cert_bio = BIO_new_mem_buf(pem_cert[i], (int) strlen(pem_cert[i]));
if (!sig_cert_bio) {
printf("VERT Failed reading mykey.pem!\n");
goto loopend;
}
sig_certs[i] = PEM_read_bio_X509(sig_cert_bio, NULL, 0, NULL);
if (!sig_certs[i] ) {
printf("VERT Failed reading pem cert %d\n |", i);
goto loopend;
}
if (!X509_STORE_add_cert(cert_store, sig_certs[i])) {
printf("VERT Failed at adding cert to store\n");
goto loopend;
}
loopend:
BIO_free(sig_cert_bio);
}
// rec_cert_bio = BIO_new_file("keys/mykey.pem", "r");
in = BIO_new_mem_buf(text,(int) strlen(text)); // simpletest
if (!sig_cert_bio) {
printf("Failed reading mykey.pem!\n");
goto deinit;
}
sig_cert = PEM_read_bio_X509(sig_cert_bio, NULL, 0, NULL);
if (!sig_cert ) {
printf("Failed reading pem cert\n");
goto deinit;
}
if (!X509_STORE_add_cert(cert_store, sig_cert)) {
printf("Failed at adding cert to store\n");
goto deinit;
}
cms = SMIME_read_CMS(in, &detached);
if (!cms)
{
printf("\nVER Failed at SMIME_READ");
if (!cms) {
printf("\nVERT VER Failed at SMIME_READ");
goto deinit;
}
out = BIO_new(BIO_s_mem());
ERR_clear_error();
if (!CMS_verify(cms, NULL, cert_store, detached, out, 0))
{
printf("Verification failed");
// MAKE A LINKED LIST AND PACK ALL THE ERROS THERE
// MAKE A LINKED LIST FOR THE SIGNERS IN THE STRUCT
if (!CMS_verify(cms, NULL, cert_store, detached, out, 0)) {
printf("VERT Verification failed");
goto deinit;
}
BIO_get_mem_data(out, &tmp);
ver->text = malloc(20);
strncpy(ver->text,"test",4);
ver->cert = malloc(2*sizeof(char*));
ver->cert[0] = malloc(20);
strncpy(ver->cert[0], "testcert", 8);
ver->cert[0][8] =0;
ver->cert[1] = malloc(20);
strncpy(ver->cert[1], "trectset", 8);
ver->cert[1][8] =0;
/*decrypted= (char *) malloc(size+1);
decrypted[size]=0;//To Nullterminate the string
memcpy(decrypted, tmp, size);*/
BIO_get_mem_data(out, &tmp);
long size = BIO_get_mem_data(out, &tmp);
realtext= (char *) malloc(size+1);
realtext[size]=0; // To Nullterminate the string
memcpy(realtext, tmp, size);
ver->res = realtext;
cert_stack = CMS_get0_signers(cms);
ver->num_certs = sk_X509_num(cert_stack);
ver->certs = stack_to_array(cert_stack);
deinit:
while ((err = ERR_get_error())) printf("\nSMIME ERROR:: %s", ERR_func_error_string(err));
temp = create_list_of_errors();
ver->errors = temp->arr;
ver->num_errors = temp->size;
free(temp);
CMS_ContentInfo_free(cms);
BIO_free(in);
BIO_free(out); //also frees tmp
BIO_free(sig_cert_bio);
X509_free(sig_cert);
BIO_free(out); // also frees tmp
X509_STORE_free(cert_store);
for (int i =0;i>num_certs;i++) X509_free(sig_certs[i]); //We need to free all certs
OpenSSL_deinitialize();
// OpenSSL ver 1.0.2.f has a bug (seemingly) that causes a crash when freeing cms content info pointers
return ver;
}
char ** init_str_arr(int num)
{
char ** arr = malloc(num*sizeof(char*));
return arr;
}
char ** add_str_to_arr(const char *str, char **arr, int i)
{
int len = strlen(str);
char *newstr = malloc(len+1);
memcpy(newstr, str, len);
newstr[len]=0;
arr[i]=newstr;
return arr;
}
void deallocate_str_arr(char **arr, int len)
{
for (int i=0; i < len; i++){
free(arr[i]);
}
free(arr);
}
char *bin_to_hex ( unsigned char *bin, int len)
{
unsigned char buf[3];
char *res = malloc(2*len+1);
for (int i =0;i<len;i++)
{
sprintf(buf, "%02x", bin[i]);
res[i*2]=buf[0];
res[i*2+1]=buf[1];
}
res[len*2]=0;
return res;
}
Loading