S/MIME decoder
smime-decode.c source
Project updated · 7 April 2006
/*
* smime-decode.c
* + decode S/MIME message
* + print out the plaintext
* + verify signature (for now ignore the certificate chain)
* - can't write opuput to a file (only stdout)
* - doesn't verify the certificate chain
* - can't decrypt encrypted messages
*
* Michal Ludvig <michal@logix.cz> (c) 2003
* Homepage: /devel/smime
*
* This code is public domain. Use it as you want to,
* but don't blame me if something doesn't work as you
* expect.
* NOTE: This code works with cryptography - you should double
* chack and fully understand it before relying on it's output!
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/crypto.h>
#include <openssl/bio.h>
#include <openssl/pkcs7.h>
#include <openssl/err.h>
int
main (int argc, char *argv[])
{
BIO *bin, *bout, *content = NULL;
PKCS7 *p7;
X509_STORE *store = NULL;
X509_LOOKUP *lookup;
int res, flags = 0;
/* Initialize the OpenSSL engine. */
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Open output BIO. */
bout = BIO_new_fp (stdout, BIO_NOCLOSE);
if (! bout)
{
printf ("Can not attach stdout: %s\n", strerror (errno));
return 1;
}
/* Open input BIO. */
if (argc < 2)
{
bin = BIO_new_fp (stdin, BIO_NOCLOSE);
if (! bin)
{
BIO_printf (bout, "Can not attach stdin: %s\n", strerror (errno));
return 1;
}
}
else
{
bin = BIO_new_file (argv[1], "r");
if (! bin)
{
BIO_printf (bout, "%s: %s\n", argv[1], strerror (errno));
return 1;
}
}
/* Prepare for using CA certificates. Useless for now. */
store = X509_STORE_new ();
lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file ());
X509_LOOKUP_load_file (lookup, NULL, X509_FILETYPE_DEFAULT);
lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir ());
X509_LOOKUP_add_dir (lookup, NULL, X509_FILETYPE_DEFAULT);
/* Read and decode S/MIME message. */
p7 = SMIME_read_PKCS7(bin, &content);
if (! p7)
{
BIO_printf (bout, "Read: %s\n", ERR_error_string(ERR_get_error (), NULL));
return 1;
}
/* Exit if it isn't a signed-only message. */
if (PKCS7_type_is_enveloped (p7))
{
printf ("[Message is encrypted - can't handle it]\n");
return 11;
}
if (PKCS7_type_is_signedAndEnveloped (p7))
{
printf ("[Message is signed & encrypted - can't handle it]\n");
return 12;
}
/* IMPORTANT: Verify only the signature, not the certificate!
* This is probably not what you want, because the signature could
* be easily forged! */
flags = PKCS7_NOVERIFY;
/* Verification itself. Plaintext is written to 'bout' BIO. */
res = PKCS7_verify (p7, NULL, store, content, bout, flags);
/* Print a result. */
BIO_printf (bout, "********************\n");
BIO_printf (bout, "[%s signature %s]\n",
PKCS7_get_detached (p7) ? "Detached" : "Embedded",
res == 1 ? "verified" : "broken");
return 0;
}