Tidy up of S/MIME code and add new functions which will make is easier

to create S/MIME signed data with multiple signers.
This commit is contained in:
Dr. Stephen Henson 2006-05-17 17:17:01 +00:00
parent ae519a247f
commit 60f20632e2
3 changed files with 137 additions and 81 deletions

View file

@ -67,89 +67,148 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, int flags)
{
PKCS7 *p7;
PKCS7_SIGNER_INFO *si;
BIO *p7bio;
STACK_OF(X509_ALGOR) *smcap;
int i;
if(!X509_check_private_key(signcert, pkey)) {
PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return NULL;
}
if(!(p7 = PKCS7_new())) {
if(!(p7 = PKCS7_new()))
{
PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
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,NULL))) {
PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
PKCS7_free(p7);
return NULL;
}
if(!(flags & PKCS7_NOCERTS)) {
PKCS7_add_certificate(p7, signcert);
if(certs) for(i = 0; i < sk_X509_num(certs); i++)
PKCS7_add_certificate(p7, sk_X509_value(certs, i));
}
if(!(flags & PKCS7_NOATTR)) {
PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data));
/* Add SMIMECapabilities */
if(!(flags & PKCS7_NOSMIMECAP))
if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags))
{
if(!(smcap = sk_X509_ALGOR_new_null())) {
PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
PKCS7_free(p7);
return NULL;
PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
goto err;
}
#ifndef OPENSSL_NO_DES
PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1);
#endif
#ifndef OPENSSL_NO_RC2
PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128);
PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64);
#endif
#ifndef OPENSSL_NO_DES
PKCS7_simple_smimecap (smcap, NID_des_cbc, -1);
#endif
#ifndef OPENSSL_NO_RC2
PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40);
#endif
PKCS7_add_attrib_smimecap (si, smcap);
sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
}
}
if (flags & PKCS7_STREAM)
if(!(flags & PKCS7_NOCERTS))
{
for(i = 0; i < sk_X509_num(certs); i++)
{
if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i)))
goto err;
}
}
if (flags & (PKCS7_STREAM|PKCS7_PARTIAL))
return p7;
if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
PKCS7_free(p7);
return NULL;
}
if (PKCS7_final(p7, data, flags))
return p7;
err:
PKCS7_free(p7);
return NULL;
}
int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
{
BIO *p7bio;
int ret;
if (!(p7bio = PKCS7_dataInit(p7, NULL)))
{
PKCS7err(PKCS7_F_PKCS7_FINAL,ERR_R_MALLOC_FAILURE);
return 0;
}
SMIME_crlf_copy(data, p7bio, flags);
if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
if(PKCS7_type_is_signed(p7) && (flags & PKCS7_DETACHED))
PKCS7_set_detached(p7, 1);
if (!PKCS7_dataFinal(p7,p7bio))
{
PKCS7err(PKCS7_F_PKCS7_FINAL,PKCS7_R_PKCS7_DATASIGN);
goto err;
}
ret = 1;
err:
BIO_free_all(p7bio);
return ret;
if (!PKCS7_dataFinal(p7,p7bio)) {
PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN);
PKCS7_free(p7);
BIO_free_all(p7bio);
return NULL;
}
BIO_free_all(p7bio);
return p7;
}
/* Check to see if a cipher exists and if so add S/MIME capabilities */
static int add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
{
if (EVP_get_cipherbynid(nid))
return PKCS7_simple_smimecap(sk, nid, arg);
return 1;
}
PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
EVP_PKEY *pkey, const EVP_MD *md,
int flags)
{
PKCS7_SIGNER_INFO *si = NULL;
int si_free = 1;
STACK_OF(X509_ALGOR) *smcap = NULL;
if(!X509_check_private_key(signcert, pkey))
{
PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,
PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
return NULL;
}
if (!(si = PKCS7_add_signature(p7,signcert,pkey, md)))
{
PKCS7err(PKCS7_F_PKCS7_ADD_SIGNER,
PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
return NULL;
}
/* si is now part of p7 so don't free it on error */
si_free = 0;
if(!(flags & PKCS7_NOCERTS))
{
if (!PKCS7_add_certificate(p7, signcert))
goto err;
}
if(!(flags & PKCS7_NOATTR))
{
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_ADD_SIGNER,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (!add_cipher_smcap(smcap, NID_des_ede3_cbc, -1)
|| !add_cipher_smcap(smcap, NID_rc2_cbc, 128)
|| !add_cipher_smcap(smcap, NID_rc2_cbc, 64)
|| !add_cipher_smcap(smcap, NID_des_cbc, -1)
|| !add_cipher_smcap(smcap, NID_rc2_cbc, 40)
|| !PKCS7_add_attrib_smimecap (si, smcap))
goto err;
sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
}
}
return si;
err:
if (smcap)
sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
if (si && si_free)
PKCS7_SIGNER_INFO_free(si);
return NULL;
}
int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
BIO *indata, BIO *out, int flags)
@ -400,22 +459,8 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
}
}
if(!(p7bio = PKCS7_dataInit(p7, NULL))) {
PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
goto err;
}
SMIME_crlf_copy(in, p7bio, flags);
BIO_flush(p7bio);
if (!PKCS7_dataFinal(p7,p7bio)) {
PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR);
goto err;
}
BIO_free_all(p7bio);
return p7;
if (PKCS7_final(p7, in, flags))
return p7;
err:

View file

@ -269,6 +269,7 @@ DECLARE_PKCS12_STACK_OF(PKCS7)
#define PKCS7_CRLFEOL 0x800
#define PKCS7_STREAM 0x1000
#define PKCS7_NOCRL 0x2000
#define PKCS7_PARTIAL 0x4000
/* Flags: for compatibility with older code */
@ -362,6 +363,12 @@ int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,STACK_OF(X509_ATTRIBUTE) *sk);
PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
BIO *data, int flags);
PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7,
X509 *signcert, EVP_PKEY *pkey, const EVP_MD *md,
int flags);
int PKCS7_final(PKCS7 *p7, 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_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags);
@ -407,6 +414,7 @@ void ERR_load_PKCS7_strings(void);
#define PKCS7_F_PKCS7_DECRYPT_RINFO 133
#define PKCS7_F_PKCS7_ENCODE_RINFO 132
#define PKCS7_F_PKCS7_ENCRYPT 115
#define PKCS7_F_PKCS7_FINAL 134
#define PKCS7_F_PKCS7_FIND_DIGEST 127
#define PKCS7_F_PKCS7_GET0_SIGNERS 124
#define PKCS7_F_PKCS7_RECIP_INFO_SET 130
@ -454,6 +462,7 @@ void ERR_load_PKCS7_strings(void);
#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
#define PKCS7_R_PKCS7_ADD_SIGNER_ERROR 153
#define PKCS7_R_PKCS7_DATAFINAL 126
#define PKCS7_R_PKCS7_DATAFINAL_ERROR 125
#define PKCS7_R_PKCS7_DATASIGN 145

View file

@ -89,6 +89,7 @@ static ERR_STRING_DATA PKCS7_str_functs[]=
{ERR_FUNC(PKCS7_F_PKCS7_DECRYPT_RINFO), "PKCS7_DECRYPT_RINFO"},
{ERR_FUNC(PKCS7_F_PKCS7_ENCODE_RINFO), "PKCS7_ENCODE_RINFO"},
{ERR_FUNC(PKCS7_F_PKCS7_ENCRYPT), "PKCS7_encrypt"},
{ERR_FUNC(PKCS7_F_PKCS7_FINAL), "PKCS7_final"},
{ERR_FUNC(PKCS7_F_PKCS7_FIND_DIGEST), "PKCS7_FIND_DIGEST"},
{ERR_FUNC(PKCS7_F_PKCS7_GET0_SIGNERS), "PKCS7_GET0_SIGNERS"},
{ERR_FUNC(PKCS7_F_PKCS7_RECIP_INFO_SET), "PKCS7_RECIP_INFO_set"},
@ -139,6 +140,7 @@ static ERR_STRING_DATA PKCS7_str_reasons[]=
{ERR_REASON(PKCS7_R_NO_SIG_CONTENT_TYPE) ,"no sig content type"},
{ERR_REASON(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE),"operation not supported on this type"},
{ERR_REASON(PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR),"pkcs7 add signature error"},
{ERR_REASON(PKCS7_R_PKCS7_ADD_SIGNER_ERROR),"pkcs7 add signer error"},
{ERR_REASON(PKCS7_R_PKCS7_DATAFINAL) ,"pkcs7 datafinal"},
{ERR_REASON(PKCS7_R_PKCS7_DATAFINAL_ERROR),"pkcs7 datafinal error"},
{ERR_REASON(PKCS7_R_PKCS7_DATASIGN) ,"pkcs7 datasign"},