/* pk7_smime.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
- * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, int flags)
{
- PKCS7 *p7;
+ PKCS7 *p7 = NULL;
PKCS7_SIGNER_INFO *si;
- BIO *p7bio;
- STACK_OF(X509_ALGOR) *smcap;
+ BIO *p7bio = NULL;
+ STACK_OF(X509_ALGOR) *smcap = NULL;
int i;
if(!X509_check_private_key(signcert, pkey)) {
return NULL;
}
- PKCS7_set_type(p7, NID_pkcs7_signed);
+ if (!PKCS7_set_type(p7, NID_pkcs7_signed))
+ goto err;
- PKCS7_content_new(p7, NID_pkcs7_data);
+ if (!PKCS7_content_new(p7, NID_pkcs7_data))
+ goto err;
- if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) {
+ if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) {
PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
- return NULL;
+ goto err;
}
if(!(flags & PKCS7_NOCERTS)) {
- PKCS7_add_certificate(p7, signcert);
+ if (!PKCS7_add_certificate(p7, signcert))
+ goto err;
if(certs) for(i = 0; i < sk_X509_num(certs); i++)
- PKCS7_add_certificate(p7, sk_X509_value(certs, i));
+ if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i)))
+ goto err;
}
if(!(flags & PKCS7_NOATTR)) {
- PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
- V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
+ if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
+ V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)))
+ goto err;
/* Add SMIMECapabilities */
if(!(flags & PKCS7_NOSMIMECAP))
{
if(!(smcap = sk_X509_ALGOR_new_null())) {
PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
#ifndef OPENSSL_NO_DES
- PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1);
+ if (!PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1))
+ goto err;
#endif
#ifndef OPENSSL_NO_RC2
- PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128);
- PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64);
+ if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128))
+ goto err;
+ if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64))
+ goto err;
#endif
#ifndef OPENSSL_NO_DES
- PKCS7_simple_smimecap (smcap, NID_des_cbc, -1);
+ if (!PKCS7_simple_smimecap (smcap, NID_des_cbc, -1))
+ goto err;
#endif
#ifndef OPENSSL_NO_RC2
- PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40);
+ if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40))
+ goto err;
#endif
- PKCS7_add_attrib_smimecap (si, smcap);
+ if (!PKCS7_add_attrib_smimecap (si, smcap))
+ goto err;
sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
+ smcap = NULL;
}
}
+ if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
+
if (flags & PKCS7_STREAM)
return p7;
+
if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
SMIME_crlf_copy(data, p7bio, flags);
- if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
- if (!PKCS7_dataFinal(p7,p7bio)) {
+ if (!PKCS7_dataFinal(p7,p7bio)) {
PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN);
- return NULL;
+ goto err;
}
- BIO_free_all(p7bio);
+ BIO_free_all(p7bio);
return p7;
+err:
+ sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
+ BIO_free_all(p7bio);
+ PKCS7_free(p7);
+ return NULL;
}
int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
char buf[4096];
int i, j=0, k, ret = 0;
BIO *p7bio;
- BIO *tmpout;
+ BIO *tmpin, *tmpout;
if(!p7) {
PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
/* Check for revocation status here */
}
- p7bio=PKCS7_dataInit(p7,indata);
+ /* Performance optimization: if the content is a memory BIO then
+ * store its contents in a temporary read only memory BIO. This
+ * avoids potentially large numbers of slow copies of data which will
+ * occur when reading from a read write memory BIO when signatures
+ * are calculated.
+ */
+
+ if (indata && (BIO_method_type(indata) == BIO_TYPE_MEM))
+ {
+ char *ptr;
+ long len;
+ len = BIO_get_mem_data(indata, &ptr);
+ tmpin = BIO_new_mem_buf(ptr, len);
+ if (tmpin == NULL)
+ {
+ PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ else
+ tmpin = indata;
+
+
+ if (!(p7bio=PKCS7_dataInit(p7,tmpin)))
+ goto err;
if(flags & PKCS7_TEXT) {
if(!(tmpout = BIO_new(BIO_s_mem()))) {
PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
goto err;
}
+ BIO_set_mem_eof_return(tmpout, 0);
} else tmpout = out;
/* We now have to 'read' from p7bio to calculate digests etc. */
ret = 1;
err:
-
- if(indata) BIO_pop(p7bio);
+
+ if (tmpin == indata)
+ {
+ if (indata) BIO_pop(p7bio);
+ }
BIO_free_all(p7bio);
+
sk_X509_free(signers);
return ret;
PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
return NULL;
}
- if(!(signers = sk_X509_new_null())) {
- PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,ERR_R_MALLOC_FAILURE);
- return NULL;
- }
/* Collect all the signers together */
if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS);
- return 0;
+ return NULL;
+ }
+
+ if(!(signers = sk_X509_new_null())) {
+ PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,ERR_R_MALLOC_FAILURE);
+ return NULL;
}
for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
if (!signer) {
PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
sk_X509_free(signers);
- return 0;
+ return NULL;
}
- sk_X509_push(signers, signer);
+ if (!sk_X509_push(signers, signer)) {
+ sk_X509_free(signers);
+ return NULL;
+ }
}
return signers;
}
return NULL;
}
- PKCS7_set_type(p7, NID_pkcs7_enveloped);
+ if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
+ goto err;
if(!PKCS7_set_cipher(p7, cipher)) {
PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER);
goto err;
SMIME_crlf_copy(in, p7bio, flags);
- BIO_flush(p7bio);
+ (void)BIO_flush(p7bio);
if (!PKCS7_dataFinal(p7,p7bio)) {
PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR);
err:
- BIO_free(p7bio);
+ BIO_free_all(p7bio);
PKCS7_free(p7);
return NULL;
return 0;
}
- if(!X509_check_private_key(cert, pkey)) {
+ if(cert && !X509_check_private_key(cert, pkey)) {
PKCS7err(PKCS7_F_PKCS7_DECRYPT,
PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return 0;
/* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
if(!(tmpbuf = BIO_new(BIO_f_buffer()))) {
PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
+ BIO_free_all(tmpmem);
return 0;
}
if(!(bread = BIO_push(tmpbuf, tmpmem))) {
PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
+ BIO_free_all(tmpbuf);
+ BIO_free_all(tmpmem);
return 0;
}
ret = SMIME_text(bread, data);