#include "cryptlib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
+#include "asn1_locl.h"
long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
{
if (nid == NID_pkcs7_signed)
{
ret=p7->detached=(int)larg;
- if (PKCS7_type_is_data(p7->d.sign->contents))
+ if (ret && PKCS7_type_is_data(p7->d.sign->contents))
{
ASN1_OCTET_STRING *os;
os=p7->d.sign->contents->d.data;
p7->d.sign->contents=p7_data;
break;
case NID_pkcs7_digest:
+ if (p7->d.digest->contents != NULL)
+ PKCS7_free(p7->d.digest->contents);
+ p7->d.digest->contents=p7_data;
+ break;
case NID_pkcs7_data:
case NID_pkcs7_enveloped:
case NID_pkcs7_signedAndEnveloped:
p7->type=obj;
if ((p7->d.sign=PKCS7_SIGNED_new()) == NULL)
goto err;
- ASN1_INTEGER_set(p7->d.sign->version,1);
+ if (!ASN1_INTEGER_set(p7->d.sign->version,1))
+ {
+ PKCS7_SIGNED_free(p7->d.sign);
+ p7->d.sign=NULL;
+ goto err;
+ }
break;
case NID_pkcs7_data:
p7->type=obj;
if ((p7->d.signed_and_enveloped=PKCS7_SIGN_ENVELOPE_new())
== NULL) goto err;
ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1);
+ if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version,1))
+ goto err;
p7->d.signed_and_enveloped->enc_data->content_type
= OBJ_nid2obj(NID_pkcs7_data);
break;
p7->type=obj;
if ((p7->d.enveloped=PKCS7_ENVELOPE_new())
== NULL) goto err;
- ASN1_INTEGER_set(p7->d.enveloped->version,0);
+ if (!ASN1_INTEGER_set(p7->d.enveloped->version,0))
+ goto err;
p7->d.enveloped->enc_data->content_type
= OBJ_nid2obj(NID_pkcs7_data);
break;
p7->type=obj;
if ((p7->d.encrypted=PKCS7_ENCRYPT_new())
== NULL) goto err;
- ASN1_INTEGER_set(p7->d.encrypted->version,0);
+ if (!ASN1_INTEGER_set(p7->d.encrypted->version,0))
+ goto err;
p7->d.encrypted->enc_data->content_type
= OBJ_nid2obj(NID_pkcs7_data);
break;
case NID_pkcs7_digest:
+ p7->type=obj;
+ if ((p7->d.digest=PKCS7_DIGEST_new())
+ == NULL) goto err;
+ if (!ASN1_INTEGER_set(p7->d.digest->version,0))
+ goto err;
+ break;
default:
PKCS7err(PKCS7_F_PKCS7_SET_TYPE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
goto err;
return(0);
}
+int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other)
+ {
+ p7->type = OBJ_nid2obj(type);
+ p7->d.other = other;
+ return 1;
+ }
+
int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
{
int i,j,nid;
int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
const EVP_MD *dgst)
{
- int nid;
- char is_dsa;
+ int ret;
- if (pkey->type == EVP_PKEY_DSA || pkey->type == EVP_PKEY_EC)
- is_dsa = 1;
- else
- is_dsa = 0;
/* We now need to add another PKCS7_SIGNER_INFO entry */
- ASN1_INTEGER_set(p7i->version,1);
- X509_NAME_set(&p7i->issuer_and_serial->issuer,
- X509_get_issuer_name(x509));
+ if (!ASN1_INTEGER_set(p7i->version,1))
+ goto err;
+ if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
+ X509_get_issuer_name(x509)))
+ goto err;
/* because ASN1_INTEGER_set is used to set a 'long' we will do
* things the ugly way. */
M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
- p7i->issuer_and_serial->serial=
- M_ASN1_INTEGER_dup(X509_get_serialNumber(x509));
+ if (!(p7i->issuer_and_serial->serial=
+ M_ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
+ goto err;
/* lets keep the pkey around for a while */
CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
p7i->pkey=pkey;
/* Set the algorithms */
- if (is_dsa) p7i->digest_alg->algorithm=OBJ_nid2obj(NID_sha1);
- else
- p7i->digest_alg->algorithm=OBJ_nid2obj(EVP_MD_type(dgst));
- if (p7i->digest_alg->parameter != NULL)
- ASN1_TYPE_free(p7i->digest_alg->parameter);
- if ((p7i->digest_alg->parameter=ASN1_TYPE_new()) == NULL)
- goto err;
- p7i->digest_alg->parameter->type=V_ASN1_NULL;
+ X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)),
+ V_ASN1_NULL, NULL);
- if (p7i->digest_enc_alg->parameter != NULL)
- ASN1_TYPE_free(p7i->digest_enc_alg->parameter);
- nid = EVP_PKEY_type(pkey->type);
- if (nid == EVP_PKEY_RSA)
- {
- p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_rsaEncryption);
- if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new()))
- goto err;
- p7i->digest_enc_alg->parameter->type=V_ASN1_NULL;
- }
- else if (nid == EVP_PKEY_DSA)
+ if (pkey->ameth && pkey->ameth->pkey_ctrl)
{
-#if 1
- /* use 'dsaEncryption' OID for compatibility with other software
- * (PKCS #7 v1.5 does specify how to handle DSA) ... */
- p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsa);
-#else
- /* ... although the 'dsaWithSHA1' OID (as required by RFC 2630 for CMS)
- * would make more sense. */
- p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_dsaWithSHA1);
-#endif
- p7i->digest_enc_alg->parameter = NULL; /* special case for DSA: omit 'parameter'! */
- }
- else if (nid == EVP_PKEY_EC)
- {
- p7i->digest_enc_alg->algorithm=OBJ_nid2obj(NID_ecdsa_with_SHA1);
- if (!(p7i->digest_enc_alg->parameter=ASN1_TYPE_new()))
- goto err;
- p7i->digest_enc_alg->parameter->type=V_ASN1_NULL;
+ ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN,
+ 0, p7i);
+ if (ret > 0)
+ return 1;
+ if (ret != -2)
+ {
+ PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
+ PKCS7_R_SIGNING_CTRL_FAILURE);
+ return 0;
+ }
}
- else
- return(0);
-
- return(1);
+ PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SET,
+ PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
err:
return(0);
}
if (!PKCS7_add_signer(p7,si)) goto err;
return(si);
err:
+ if (si)
+ PKCS7_SIGNER_INFO_free(si);
return(NULL);
}
+int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
+ {
+ if (PKCS7_type_is_digest(p7))
+ {
+ if(!(p7->d.digest->md->parameter = ASN1_TYPE_new()))
+ {
+ PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ p7->d.digest->md->parameter->type = V_ASN1_NULL;
+ p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md));
+ return 1;
+ }
+
+ PKCS7err(PKCS7_F_PKCS7_SET_DIGEST,PKCS7_R_WRONG_CONTENT_TYPE);
+ return 1;
+ }
+
STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7)
{
if (PKCS7_type_is_signed(p7))
return(NULL);
}
+void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
+ X509_ALGOR **pdig, X509_ALGOR **psig)
+ {
+ if (pk)
+ *pk = si->pkey;
+ if (pdig)
+ *pdig = si->digest_alg;
+ if (psig)
+ *psig = si->digest_enc_alg;
+ }
+
+void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc)
+ {
+ if (penc)
+ *penc = ri->key_enc_algor;
+ }
+
PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
{
PKCS7_RECIP_INFO *ri;
int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
{
- ASN1_INTEGER_set(p7i->version,0);
- X509_NAME_set(&p7i->issuer_and_serial->issuer,
- X509_get_issuer_name(x509));
+ if (!ASN1_INTEGER_set(p7i->version,0))
+ return 0;
+ if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
+ X509_get_issuer_name(x509)))
+ return 0;
M_ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
- p7i->issuer_and_serial->serial=
- M_ASN1_INTEGER_dup(X509_get_serialNumber(x509));
+ if (!(p7i->issuer_and_serial->serial=
+ M_ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
+ return 0;
X509_ALGOR_free(p7i->key_enc_algor);
- p7i->key_enc_algor= X509_ALGOR_dup(x509->cert_info->key->algor);
+ if (!(p7i->key_enc_algor= X509_ALGOR_dup(x509->cert_info->key->algor)))
+ return 0;
CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
p7i->cert=x509;