Commit 55ec5861 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Modify S/MIME application so the -signer option writes the signer(s)

to a file if we are verifying.
parent 5a9a4b29
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ static X509 *load_cert(char *file);
static EVP_PKEY *load_key(char *file);
static STACK_OF(X509) *load_certs(char *file);
static X509_STORE *setup_verify(char *CAfile, char *CApath);
static int save_certs(char *signerfile, STACK_OF(X509) *signers);

#define SMIME_OP	0x10
#define SMIME_ENCRYPT	(1 | SMIME_OP)
@@ -261,7 +262,7 @@ int MAIN(int argc, char **argv)
		}
	}

	if(signerfile) {
	if(signerfile && (operation == SMIME_SIGN)) {
		if(!(signer = load_cert(signerfile))) {
			BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile);
			goto end;
@@ -276,7 +277,7 @@ int MAIN(int argc, char **argv)
		}
	}

	if(recipfile) {
	if(recipfile && (operation == SMIME_DECRYPT)) {
		if(!(recip = load_cert(recipfile))) {
			BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile);
			ERR_print_errors(bio_err);
@@ -341,6 +342,8 @@ int MAIN(int argc, char **argv)
			BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
		else ret = 0;
	} else if(operation == SMIME_VERIFY) {
		STACK_OF(X509) *signers;
		signers = PKCS7_iget_signers(p7, other, flags);
		if(PKCS7_verify(p7, other, store, indata, out, flags)) {
			BIO_printf(bio_err, "Verification Successful\n");
			ret = 0;
@@ -348,6 +351,12 @@ int MAIN(int argc, char **argv)
			BIO_printf(bio_err, "Verification Failure\n");
			ret = 5;
		}
		if(!save_certs(signerfile, signers)) {
			BIO_printf(bio_err, "Error writing signers to %s\n",
								signerfile);
			ret = 2;
		}
		sk_X509_free(signers);
	} else if(operation == SMIME_PK7OUT) {
		PEM_write_bio_PKCS7(out, p7);
	} else {
@@ -444,3 +453,17 @@ static X509_STORE *setup_verify(char *CAfile, char *CApath)
	X509_STORE_free(store);
	return NULL;
}

int save_certs(char *signerfile, STACK_OF(X509) *signers)
{
	int i;
	BIO *tmp;
	if(!signerfile) return 1;
	tmp = BIO_new_file(signerfile, "w");
	if(!tmp) return 0;
	for(i = 0; i < sk_X509_num(signers); i++)
		PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
	BIO_free(tmp);
	return 1;
}
	
+54 −29
Original line number Diff line number Diff line
@@ -144,14 +144,13 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
	X509 *signer;
	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
	PKCS7_SIGNER_INFO *si;
	PKCS7_ISSUER_AND_SERIAL *ias;
	X509_STORE_CTX cert_ctx;
	char buf[4096];
	int i, j=0;
	BIO *p7bio;
	BIO *tmpout;

	if(OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
	if(!PKCS7_type_is_signed(p7)) {
				PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
		return 0;
	}
@@ -176,34 +175,9 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
	}


	if(!(signers = sk_X509_new(NULL))) {
		PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
		return 0;
	}

	/* Collect all the signers together */

	for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
	{
	    si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
	    ias = si->issuer_and_serial;
	    signer = NULL;
		/* If any certificates passed they take priority */
	    if (certs) signer = X509_find_by_issuer_and_serial (certs,
					 	ias->issuer, ias->serial);
	    if (!signer && !(flags & PKCS7_NOINTERN)
			&& p7->d.sign->cert) signer =
		              X509_find_by_issuer_and_serial (p7->d.sign->cert,
					      	ias->issuer, ias->serial);
	    if (!signer) {
			PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
			sk_X509_free(signers);
			return 0;
	    }

	    sk_X509_push(signers, signer);
	}
	signers = PKCS7_iget_signers(p7, certs, flags);

	if(!signers) return 0;

	/* Now verify the certificates */

@@ -281,6 +255,57 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
	return 0;
}

STACK_OF(X509) *PKCS7_iget_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
{
	STACK_OF(X509) *signers;
	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
	PKCS7_SIGNER_INFO *si;
	PKCS7_ISSUER_AND_SERIAL *ias;
	X509 *signer;
	int i;

	if(!PKCS7_type_is_signed(p7)) {
		PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
		return NULL;
	}
	if(!(signers = sk_X509_new(NULL))) {
		PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,ERR_R_MALLOC_FAILURE);
		return NULL;
	}

	/* Collect all the signers together */

	sinfos = PKCS7_get_signer_info(p7);

	if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
		PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_NO_SIGNERS);
		return 0;
	}

	for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
	{
	    si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
	    ias = si->issuer_and_serial;
	    signer = NULL;
		/* If any certificates passed they take priority */
	    if (certs) signer = X509_find_by_issuer_and_serial (certs,
					 	ias->issuer, ias->serial);
	    if (!signer && !(flags & PKCS7_NOINTERN)
			&& p7->d.sign->cert) signer =
		              X509_find_by_issuer_and_serial (p7->d.sign->cert,
					      	ias->issuer, ias->serial);
	    if (!signer) {
			PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
			sk_X509_free(signers);
			return 0;
	    }

	    sk_X509_push(signers, signer);
	}
	return signers;
}


/* Build a complete PKCS#7 enveloped data */

PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher,
+3 −0
Original line number Diff line number Diff line
@@ -396,6 +396,7 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
							BIO *data, int flags);
int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
					BIO *indata, BIO *out, int flags);
STACK_OF(X509) *PKCS7_iget_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags);
PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher,
								int flags);
int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags);
@@ -431,6 +432,7 @@ int SMIME_text(BIO *in, BIO *out);
#define PKCS7_F_PKCS7_DATAVERIFY			 107
#define PKCS7_F_PKCS7_DECRYPT				 114
#define PKCS7_F_PKCS7_ENCRYPT				 115
#define PKCS7_F_PKCS7_IGET_SIGNERS			 124
#define PKCS7_F_PKCS7_SET_CIPHER			 108
#define PKCS7_F_PKCS7_SET_CONTENT			 109
#define PKCS7_F_PKCS7_SET_TYPE				 110
@@ -463,6 +465,7 @@ int SMIME_text(BIO *in, BIO *out);
#define PKCS7_R_NO_MULTIPART_BOUNDARY			 137
#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE	 115
#define PKCS7_R_NO_SIGNATURES_ON_DATA			 123
#define PKCS7_R_NO_SIGNERS				 142
#define PKCS7_R_NO_SIG_CONTENT_TYPE			 138
#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE	 104
#define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR		 124
+2 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ static ERR_STRING_DATA PKCS7_str_functs[]=
{ERR_PACK(0,PKCS7_F_PKCS7_DATAVERIFY,0),	"PKCS7_dataVerify"},
{ERR_PACK(0,PKCS7_F_PKCS7_DECRYPT,0),	"PKCS7_decrypt"},
{ERR_PACK(0,PKCS7_F_PKCS7_ENCRYPT,0),	"PKCS7_encrypt"},
{ERR_PACK(0,PKCS7_F_PKCS7_IGET_SIGNERS,0),	"PKCS7_iget_signers"},
{ERR_PACK(0,PKCS7_F_PKCS7_SET_CIPHER,0),	"PKCS7_set_cipher"},
{ERR_PACK(0,PKCS7_F_PKCS7_SET_CONTENT,0),	"PKCS7_set_content"},
{ERR_PACK(0,PKCS7_F_PKCS7_SET_TYPE,0),	"PKCS7_set_type"},
@@ -114,6 +115,7 @@ static ERR_STRING_DATA PKCS7_str_reasons[]=
{PKCS7_R_NO_MULTIPART_BOUNDARY           ,"no multipart boundary"},
{PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE,"no recipient matches certificate"},
{PKCS7_R_NO_SIGNATURES_ON_DATA           ,"no signatures on data"},
{PKCS7_R_NO_SIGNERS                      ,"no signers"},
{PKCS7_R_NO_SIG_CONTENT_TYPE             ,"no sig content type"},
{PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE,"operation not supported on this type"},
{PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR       ,"pkcs7 add signature error"},