10Sstevel@tonic-gate /* crypto/pkcs7/pk7_doit.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate * All rights reserved.
40Sstevel@tonic-gate *
50Sstevel@tonic-gate * This package is an SSL implementation written
60Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate * the following conditions are aheared to. The following conditions
110Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation
130Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate * the code are not to be removed.
180Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate * as the author of the parts of the library used.
200Sstevel@tonic-gate * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate *
230Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate * are met:
260Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate * must display the following acknowledgement:
330Sstevel@tonic-gate * "This product includes cryptographic software written by
340Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate * being used are not cryptographic related :-).
370Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate * SUCH DAMAGE.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be
550Sstevel@tonic-gate * copied and put under another distribution licence
560Sstevel@tonic-gate * [including the GNU Public Licence.]
570Sstevel@tonic-gate */
580Sstevel@tonic-gate
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include "cryptlib.h"
610Sstevel@tonic-gate #include <openssl/rand.h>
620Sstevel@tonic-gate #include <openssl/objects.h>
630Sstevel@tonic-gate #include <openssl/x509.h>
640Sstevel@tonic-gate #include <openssl/x509v3.h>
65*2139Sjp161948 #include <openssl/err.h>
660Sstevel@tonic-gate
670Sstevel@tonic-gate static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
680Sstevel@tonic-gate void *value);
690Sstevel@tonic-gate static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
700Sstevel@tonic-gate
PKCS7_type_is_other(PKCS7 * p7)710Sstevel@tonic-gate static int PKCS7_type_is_other(PKCS7* p7)
720Sstevel@tonic-gate {
730Sstevel@tonic-gate int isOther=1;
740Sstevel@tonic-gate
750Sstevel@tonic-gate int nid=OBJ_obj2nid(p7->type);
760Sstevel@tonic-gate
770Sstevel@tonic-gate switch( nid )
780Sstevel@tonic-gate {
790Sstevel@tonic-gate case NID_pkcs7_data:
800Sstevel@tonic-gate case NID_pkcs7_signed:
810Sstevel@tonic-gate case NID_pkcs7_enveloped:
820Sstevel@tonic-gate case NID_pkcs7_signedAndEnveloped:
830Sstevel@tonic-gate case NID_pkcs7_digest:
840Sstevel@tonic-gate case NID_pkcs7_encrypted:
850Sstevel@tonic-gate isOther=0;
860Sstevel@tonic-gate break;
870Sstevel@tonic-gate default:
880Sstevel@tonic-gate isOther=1;
890Sstevel@tonic-gate }
900Sstevel@tonic-gate
910Sstevel@tonic-gate return isOther;
920Sstevel@tonic-gate
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
PKCS7_get_octet_string(PKCS7 * p7)950Sstevel@tonic-gate static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate if ( PKCS7_type_is_data(p7))
980Sstevel@tonic-gate return p7->d.data;
990Sstevel@tonic-gate if ( PKCS7_type_is_other(p7) && p7->d.other
1000Sstevel@tonic-gate && (p7->d.other->type == V_ASN1_OCTET_STRING))
1010Sstevel@tonic-gate return p7->d.other->value.octet_string;
1020Sstevel@tonic-gate return NULL;
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate
PKCS7_bio_add_digest(BIO ** pbio,X509_ALGOR * alg)105*2139Sjp161948 static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
106*2139Sjp161948 {
107*2139Sjp161948 BIO *btmp;
108*2139Sjp161948 const EVP_MD *md;
109*2139Sjp161948 if ((btmp=BIO_new(BIO_f_md())) == NULL)
110*2139Sjp161948 {
111*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
112*2139Sjp161948 goto err;
113*2139Sjp161948 }
114*2139Sjp161948
115*2139Sjp161948 md=EVP_get_digestbyobj(alg->algorithm);
116*2139Sjp161948 if (md == NULL)
117*2139Sjp161948 {
118*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
119*2139Sjp161948 goto err;
120*2139Sjp161948 }
121*2139Sjp161948
122*2139Sjp161948 BIO_set_md(btmp,md);
123*2139Sjp161948 if (*pbio == NULL)
124*2139Sjp161948 *pbio=btmp;
125*2139Sjp161948 else if (!BIO_push(*pbio,btmp))
126*2139Sjp161948 {
127*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
128*2139Sjp161948 goto err;
129*2139Sjp161948 }
130*2139Sjp161948 btmp=NULL;
131*2139Sjp161948
132*2139Sjp161948 return 1;
133*2139Sjp161948
134*2139Sjp161948 err:
135*2139Sjp161948 if (btmp)
136*2139Sjp161948 BIO_free(btmp);
137*2139Sjp161948 return 0;
138*2139Sjp161948
139*2139Sjp161948 }
140*2139Sjp161948
PKCS7_dataInit(PKCS7 * p7,BIO * bio)1410Sstevel@tonic-gate BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
1420Sstevel@tonic-gate {
1430Sstevel@tonic-gate int i;
1440Sstevel@tonic-gate BIO *out=NULL,*btmp=NULL;
145*2139Sjp161948 X509_ALGOR *xa = NULL;
1460Sstevel@tonic-gate const EVP_CIPHER *evp_cipher=NULL;
1470Sstevel@tonic-gate STACK_OF(X509_ALGOR) *md_sk=NULL;
1480Sstevel@tonic-gate STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
1490Sstevel@tonic-gate X509_ALGOR *xalg=NULL;
1500Sstevel@tonic-gate PKCS7_RECIP_INFO *ri=NULL;
1510Sstevel@tonic-gate EVP_PKEY *pkey;
152*2139Sjp161948 ASN1_OCTET_STRING *os=NULL;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate i=OBJ_obj2nid(p7->type);
1550Sstevel@tonic-gate p7->state=PKCS7_S_HEADER;
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate switch (i)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate case NID_pkcs7_signed:
1600Sstevel@tonic-gate md_sk=p7->d.sign->md_algs;
161*2139Sjp161948 os = PKCS7_get_octet_string(p7->d.sign->contents);
1620Sstevel@tonic-gate break;
1630Sstevel@tonic-gate case NID_pkcs7_signedAndEnveloped:
1640Sstevel@tonic-gate rsk=p7->d.signed_and_enveloped->recipientinfo;
1650Sstevel@tonic-gate md_sk=p7->d.signed_and_enveloped->md_algs;
1660Sstevel@tonic-gate xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
1670Sstevel@tonic-gate evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
1680Sstevel@tonic-gate if (evp_cipher == NULL)
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,
1710Sstevel@tonic-gate PKCS7_R_CIPHER_NOT_INITIALIZED);
1720Sstevel@tonic-gate goto err;
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate break;
1750Sstevel@tonic-gate case NID_pkcs7_enveloped:
1760Sstevel@tonic-gate rsk=p7->d.enveloped->recipientinfo;
1770Sstevel@tonic-gate xalg=p7->d.enveloped->enc_data->algorithm;
1780Sstevel@tonic-gate evp_cipher=p7->d.enveloped->enc_data->cipher;
1790Sstevel@tonic-gate if (evp_cipher == NULL)
1800Sstevel@tonic-gate {
1810Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,
1820Sstevel@tonic-gate PKCS7_R_CIPHER_NOT_INITIALIZED);
1830Sstevel@tonic-gate goto err;
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate break;
186*2139Sjp161948 case NID_pkcs7_digest:
187*2139Sjp161948 xa = p7->d.digest->md;
188*2139Sjp161948 os = PKCS7_get_octet_string(p7->d.digest->contents);
189*2139Sjp161948 break;
1900Sstevel@tonic-gate default:
1910Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
1920Sstevel@tonic-gate goto err;
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate
195*2139Sjp161948 for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
196*2139Sjp161948 if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
197*2139Sjp161948 goto err;
1980Sstevel@tonic-gate
199*2139Sjp161948 if (xa && !PKCS7_bio_add_digest(&out, xa))
200*2139Sjp161948 goto err;
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate if (evp_cipher != NULL)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate unsigned char key[EVP_MAX_KEY_LENGTH];
2050Sstevel@tonic-gate unsigned char iv[EVP_MAX_IV_LENGTH];
2060Sstevel@tonic-gate int keylen,ivlen;
2070Sstevel@tonic-gate int jj,max;
2080Sstevel@tonic-gate unsigned char *tmp;
2090Sstevel@tonic-gate EVP_CIPHER_CTX *ctx;
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
2120Sstevel@tonic-gate {
2130Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
2140Sstevel@tonic-gate goto err;
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate BIO_get_cipher_ctx(btmp, &ctx);
2170Sstevel@tonic-gate keylen=EVP_CIPHER_key_length(evp_cipher);
2180Sstevel@tonic-gate ivlen=EVP_CIPHER_iv_length(evp_cipher);
2190Sstevel@tonic-gate xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
2200Sstevel@tonic-gate if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
221*2139Sjp161948 if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
222*2139Sjp161948 goto err;
223*2139Sjp161948 if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
224*2139Sjp161948 goto err;
225*2139Sjp161948 if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
226*2139Sjp161948 goto err;
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate if (ivlen > 0) {
2290Sstevel@tonic-gate if (xalg->parameter == NULL)
2300Sstevel@tonic-gate xalg->parameter=ASN1_TYPE_new();
2310Sstevel@tonic-gate if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
2320Sstevel@tonic-gate goto err;
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate /* Lets do the pub key stuff :-) */
2360Sstevel@tonic-gate max=0;
2370Sstevel@tonic-gate for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
2400Sstevel@tonic-gate if (ri->cert == NULL)
2410Sstevel@tonic-gate {
2420Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
2430Sstevel@tonic-gate goto err;
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate pkey=X509_get_pubkey(ri->cert);
2460Sstevel@tonic-gate jj=EVP_PKEY_size(pkey);
2470Sstevel@tonic-gate EVP_PKEY_free(pkey);
2480Sstevel@tonic-gate if (max < jj) max=jj;
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
2530Sstevel@tonic-gate goto err;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
2580Sstevel@tonic-gate pkey=X509_get_pubkey(ri->cert);
2590Sstevel@tonic-gate jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
2600Sstevel@tonic-gate EVP_PKEY_free(pkey);
2610Sstevel@tonic-gate if (jj <= 0)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
2640Sstevel@tonic-gate OPENSSL_free(tmp);
2650Sstevel@tonic-gate goto err;
2660Sstevel@tonic-gate }
267*2139Sjp161948 if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
268*2139Sjp161948 {
269*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAINIT,
270*2139Sjp161948 ERR_R_MALLOC_FAILURE);
271*2139Sjp161948 OPENSSL_free(tmp);
272*2139Sjp161948 goto err;
273*2139Sjp161948 }
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate OPENSSL_free(tmp);
2760Sstevel@tonic-gate OPENSSL_cleanse(key, keylen);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if (out == NULL)
2790Sstevel@tonic-gate out=btmp;
2800Sstevel@tonic-gate else
2810Sstevel@tonic-gate BIO_push(out,btmp);
2820Sstevel@tonic-gate btmp=NULL;
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate if (bio == NULL)
2860Sstevel@tonic-gate {
2870Sstevel@tonic-gate if (PKCS7_is_detached(p7))
2880Sstevel@tonic-gate bio=BIO_new(BIO_s_null());
289*2139Sjp161948 else if (os && os->length > 0)
290*2139Sjp161948 bio = BIO_new_mem_buf(os->data, os->length);
291*2139Sjp161948 if(bio == NULL)
2920Sstevel@tonic-gate {
293*2139Sjp161948 bio=BIO_new(BIO_s_mem());
294*2139Sjp161948 BIO_set_mem_eof_return(bio,0);
2950Sstevel@tonic-gate }
296*2139Sjp161948 }
2970Sstevel@tonic-gate BIO_push(out,bio);
2980Sstevel@tonic-gate bio=NULL;
2990Sstevel@tonic-gate if (0)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate err:
3020Sstevel@tonic-gate if (out != NULL)
3030Sstevel@tonic-gate BIO_free_all(out);
3040Sstevel@tonic-gate if (btmp != NULL)
3050Sstevel@tonic-gate BIO_free_all(btmp);
3060Sstevel@tonic-gate out=NULL;
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate return(out);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
pkcs7_cmp_ri(PKCS7_RECIP_INFO * ri,X509 * pcert)311*2139Sjp161948 static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
312*2139Sjp161948 {
313*2139Sjp161948 int ret;
314*2139Sjp161948 ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
315*2139Sjp161948 pcert->cert_info->issuer);
316*2139Sjp161948 if (ret)
317*2139Sjp161948 return ret;
318*2139Sjp161948 return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
319*2139Sjp161948 ri->issuer_and_serial->serial);
320*2139Sjp161948 }
321*2139Sjp161948
3220Sstevel@tonic-gate /* int */
PKCS7_dataDecode(PKCS7 * p7,EVP_PKEY * pkey,BIO * in_bio,X509 * pcert)3230Sstevel@tonic-gate BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate int i,j;
3260Sstevel@tonic-gate BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
3270Sstevel@tonic-gate unsigned char *tmp=NULL;
3280Sstevel@tonic-gate X509_ALGOR *xa;
3290Sstevel@tonic-gate ASN1_OCTET_STRING *data_body=NULL;
3300Sstevel@tonic-gate const EVP_MD *evp_md;
3310Sstevel@tonic-gate const EVP_CIPHER *evp_cipher=NULL;
3320Sstevel@tonic-gate EVP_CIPHER_CTX *evp_ctx=NULL;
3330Sstevel@tonic-gate X509_ALGOR *enc_alg=NULL;
3340Sstevel@tonic-gate STACK_OF(X509_ALGOR) *md_sk=NULL;
3350Sstevel@tonic-gate STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
3360Sstevel@tonic-gate X509_ALGOR *xalg=NULL;
3370Sstevel@tonic-gate PKCS7_RECIP_INFO *ri=NULL;
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate i=OBJ_obj2nid(p7->type);
3400Sstevel@tonic-gate p7->state=PKCS7_S_HEADER;
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate switch (i)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate case NID_pkcs7_signed:
3450Sstevel@tonic-gate data_body=PKCS7_get_octet_string(p7->d.sign->contents);
3460Sstevel@tonic-gate md_sk=p7->d.sign->md_algs;
3470Sstevel@tonic-gate break;
3480Sstevel@tonic-gate case NID_pkcs7_signedAndEnveloped:
3490Sstevel@tonic-gate rsk=p7->d.signed_and_enveloped->recipientinfo;
3500Sstevel@tonic-gate md_sk=p7->d.signed_and_enveloped->md_algs;
3510Sstevel@tonic-gate data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
3520Sstevel@tonic-gate enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
3530Sstevel@tonic-gate evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
3540Sstevel@tonic-gate if (evp_cipher == NULL)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
3570Sstevel@tonic-gate goto err;
3580Sstevel@tonic-gate }
3590Sstevel@tonic-gate xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
3600Sstevel@tonic-gate break;
3610Sstevel@tonic-gate case NID_pkcs7_enveloped:
3620Sstevel@tonic-gate rsk=p7->d.enveloped->recipientinfo;
3630Sstevel@tonic-gate enc_alg=p7->d.enveloped->enc_data->algorithm;
3640Sstevel@tonic-gate data_body=p7->d.enveloped->enc_data->enc_data;
3650Sstevel@tonic-gate evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
3660Sstevel@tonic-gate if (evp_cipher == NULL)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
3690Sstevel@tonic-gate goto err;
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate xalg=p7->d.enveloped->enc_data->algorithm;
3720Sstevel@tonic-gate break;
3730Sstevel@tonic-gate default:
3740Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
3750Sstevel@tonic-gate goto err;
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate /* We will be checking the signature */
3790Sstevel@tonic-gate if (md_sk != NULL)
3800Sstevel@tonic-gate {
3810Sstevel@tonic-gate for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate xa=sk_X509_ALGOR_value(md_sk,i);
3840Sstevel@tonic-gate if ((btmp=BIO_new(BIO_f_md())) == NULL)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
3870Sstevel@tonic-gate goto err;
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate j=OBJ_obj2nid(xa->algorithm);
3910Sstevel@tonic-gate evp_md=EVP_get_digestbynid(j);
3920Sstevel@tonic-gate if (evp_md == NULL)
3930Sstevel@tonic-gate {
3940Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
3950Sstevel@tonic-gate goto err;
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate BIO_set_md(btmp,evp_md);
3990Sstevel@tonic-gate if (out == NULL)
4000Sstevel@tonic-gate out=btmp;
4010Sstevel@tonic-gate else
4020Sstevel@tonic-gate BIO_push(out,btmp);
4030Sstevel@tonic-gate btmp=NULL;
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate if (evp_cipher != NULL)
4080Sstevel@tonic-gate {
4090Sstevel@tonic-gate #if 0
4100Sstevel@tonic-gate unsigned char key[EVP_MAX_KEY_LENGTH];
4110Sstevel@tonic-gate unsigned char iv[EVP_MAX_IV_LENGTH];
4120Sstevel@tonic-gate unsigned char *p;
4130Sstevel@tonic-gate int keylen,ivlen;
4140Sstevel@tonic-gate int max;
4150Sstevel@tonic-gate X509_OBJECT ret;
4160Sstevel@tonic-gate #endif
4170Sstevel@tonic-gate int jj;
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
4220Sstevel@tonic-gate goto err;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate /* It was encrypted, we need to decrypt the secret key
4260Sstevel@tonic-gate * with the private key */
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate /* Find the recipientInfo which matches the passed certificate
4290Sstevel@tonic-gate * (if any)
4300Sstevel@tonic-gate */
4310Sstevel@tonic-gate
432*2139Sjp161948 if (pcert) {
433*2139Sjp161948 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
434*2139Sjp161948 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
435*2139Sjp161948 if (!pkcs7_cmp_ri(ri, pcert))
436*2139Sjp161948 break;
437*2139Sjp161948 ri=NULL;
438*2139Sjp161948 }
439*2139Sjp161948 if (ri == NULL) {
440*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
441*2139Sjp161948 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
442*2139Sjp161948 goto err;
443*2139Sjp161948 }
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate jj=EVP_PKEY_size(pkey);
4470Sstevel@tonic-gate tmp=(unsigned char *)OPENSSL_malloc(jj+10);
4480Sstevel@tonic-gate if (tmp == NULL)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
4510Sstevel@tonic-gate goto err;
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate
454*2139Sjp161948 /* If we haven't got a certificate try each ri in turn */
455*2139Sjp161948
456*2139Sjp161948 if (pcert == NULL)
4570Sstevel@tonic-gate {
458*2139Sjp161948 for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
459*2139Sjp161948 {
460*2139Sjp161948 ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
461*2139Sjp161948 jj=EVP_PKEY_decrypt(tmp,
462*2139Sjp161948 M_ASN1_STRING_data(ri->enc_key),
463*2139Sjp161948 M_ASN1_STRING_length(ri->enc_key),
464*2139Sjp161948 pkey);
465*2139Sjp161948 if (jj > 0)
466*2139Sjp161948 break;
467*2139Sjp161948 ERR_clear_error();
468*2139Sjp161948 ri = NULL;
469*2139Sjp161948 }
470*2139Sjp161948 if (ri == NULL)
471*2139Sjp161948 {
472*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
473*2139Sjp161948 PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
474*2139Sjp161948 goto err;
475*2139Sjp161948 }
476*2139Sjp161948 }
477*2139Sjp161948 else
478*2139Sjp161948 {
479*2139Sjp161948 jj=EVP_PKEY_decrypt(tmp,
480*2139Sjp161948 M_ASN1_STRING_data(ri->enc_key),
481*2139Sjp161948 M_ASN1_STRING_length(ri->enc_key), pkey);
482*2139Sjp161948 if (jj <= 0)
483*2139Sjp161948 {
484*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
485*2139Sjp161948 ERR_R_EVP_LIB);
486*2139Sjp161948 goto err;
487*2139Sjp161948 }
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate evp_ctx=NULL;
4910Sstevel@tonic-gate BIO_get_cipher_ctx(etmp,&evp_ctx);
492*2139Sjp161948 if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
493*2139Sjp161948 goto err;
4940Sstevel@tonic-gate if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
4950Sstevel@tonic-gate goto err;
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
4980Sstevel@tonic-gate /* Some S/MIME clients don't use the same key
4990Sstevel@tonic-gate * and effective key length. The key length is
5000Sstevel@tonic-gate * determined by the size of the decrypted RSA key.
5010Sstevel@tonic-gate */
5020Sstevel@tonic-gate if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
5030Sstevel@tonic-gate {
5040Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATADECODE,
5050Sstevel@tonic-gate PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
5060Sstevel@tonic-gate goto err;
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate }
509*2139Sjp161948 if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
510*2139Sjp161948 goto err;
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate OPENSSL_cleanse(tmp,jj);
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate if (out == NULL)
5150Sstevel@tonic-gate out=etmp;
5160Sstevel@tonic-gate else
5170Sstevel@tonic-gate BIO_push(out,etmp);
5180Sstevel@tonic-gate etmp=NULL;
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate #if 1
5220Sstevel@tonic-gate if (PKCS7_is_detached(p7) || (in_bio != NULL))
5230Sstevel@tonic-gate {
5240Sstevel@tonic-gate bio=in_bio;
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate else
5270Sstevel@tonic-gate {
5280Sstevel@tonic-gate #if 0
5290Sstevel@tonic-gate bio=BIO_new(BIO_s_mem());
5300Sstevel@tonic-gate /* We need to set this so that when we have read all
5310Sstevel@tonic-gate * the data, the encrypt BIO, if present, will read
5320Sstevel@tonic-gate * EOF and encode the last few bytes */
5330Sstevel@tonic-gate BIO_set_mem_eof_return(bio,0);
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate if (data_body->length > 0)
5360Sstevel@tonic-gate BIO_write(bio,(char *)data_body->data,data_body->length);
5370Sstevel@tonic-gate #else
5380Sstevel@tonic-gate if (data_body->length > 0)
5390Sstevel@tonic-gate bio = BIO_new_mem_buf(data_body->data,data_body->length);
5400Sstevel@tonic-gate else {
5410Sstevel@tonic-gate bio=BIO_new(BIO_s_mem());
5420Sstevel@tonic-gate BIO_set_mem_eof_return(bio,0);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate #endif
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate BIO_push(out,bio);
5470Sstevel@tonic-gate bio=NULL;
5480Sstevel@tonic-gate #endif
5490Sstevel@tonic-gate if (0)
5500Sstevel@tonic-gate {
5510Sstevel@tonic-gate err:
5520Sstevel@tonic-gate if (out != NULL) BIO_free_all(out);
5530Sstevel@tonic-gate if (btmp != NULL) BIO_free_all(btmp);
5540Sstevel@tonic-gate if (etmp != NULL) BIO_free_all(etmp);
5550Sstevel@tonic-gate if (bio != NULL) BIO_free_all(bio);
5560Sstevel@tonic-gate out=NULL;
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate if (tmp != NULL)
5590Sstevel@tonic-gate OPENSSL_free(tmp);
5600Sstevel@tonic-gate return(out);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
PKCS7_find_digest(EVP_MD_CTX ** pmd,BIO * bio,int nid)563*2139Sjp161948 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
564*2139Sjp161948 {
565*2139Sjp161948 for (;;)
566*2139Sjp161948 {
567*2139Sjp161948 bio=BIO_find_type(bio,BIO_TYPE_MD);
568*2139Sjp161948 if (bio == NULL)
569*2139Sjp161948 {
570*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
571*2139Sjp161948 return NULL;
572*2139Sjp161948 }
573*2139Sjp161948 BIO_get_md_ctx(bio,pmd);
574*2139Sjp161948 if (*pmd == NULL)
575*2139Sjp161948 {
576*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
577*2139Sjp161948 return NULL;
578*2139Sjp161948 }
579*2139Sjp161948 if (EVP_MD_CTX_type(*pmd) == nid)
580*2139Sjp161948 return bio;
581*2139Sjp161948 bio=BIO_next(bio);
582*2139Sjp161948 }
583*2139Sjp161948 return NULL;
584*2139Sjp161948 }
585*2139Sjp161948
PKCS7_dataFinal(PKCS7 * p7,BIO * bio)5860Sstevel@tonic-gate int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
5870Sstevel@tonic-gate {
5880Sstevel@tonic-gate int ret=0;
5890Sstevel@tonic-gate int i,j;
5900Sstevel@tonic-gate BIO *btmp;
5910Sstevel@tonic-gate BUF_MEM *buf_mem=NULL;
5920Sstevel@tonic-gate BUF_MEM *buf=NULL;
5930Sstevel@tonic-gate PKCS7_SIGNER_INFO *si;
5940Sstevel@tonic-gate EVP_MD_CTX *mdc,ctx_tmp;
5950Sstevel@tonic-gate STACK_OF(X509_ATTRIBUTE) *sk;
5960Sstevel@tonic-gate STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
5970Sstevel@tonic-gate ASN1_OCTET_STRING *os=NULL;
5980Sstevel@tonic-gate
5990Sstevel@tonic-gate EVP_MD_CTX_init(&ctx_tmp);
6000Sstevel@tonic-gate i=OBJ_obj2nid(p7->type);
6010Sstevel@tonic-gate p7->state=PKCS7_S_HEADER;
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate switch (i)
6040Sstevel@tonic-gate {
6050Sstevel@tonic-gate case NID_pkcs7_signedAndEnveloped:
6060Sstevel@tonic-gate /* XXXXXXXXXXXXXXXX */
6070Sstevel@tonic-gate si_sk=p7->d.signed_and_enveloped->signer_info;
608*2139Sjp161948 if (!(os=M_ASN1_OCTET_STRING_new()))
609*2139Sjp161948 {
610*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
611*2139Sjp161948 goto err;
612*2139Sjp161948 }
6130Sstevel@tonic-gate p7->d.signed_and_enveloped->enc_data->enc_data=os;
6140Sstevel@tonic-gate break;
6150Sstevel@tonic-gate case NID_pkcs7_enveloped:
6160Sstevel@tonic-gate /* XXXXXXXXXXXXXXXX */
617*2139Sjp161948 if (!(os=M_ASN1_OCTET_STRING_new()))
618*2139Sjp161948 {
619*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
620*2139Sjp161948 goto err;
621*2139Sjp161948 }
6220Sstevel@tonic-gate p7->d.enveloped->enc_data->enc_data=os;
6230Sstevel@tonic-gate break;
6240Sstevel@tonic-gate case NID_pkcs7_signed:
6250Sstevel@tonic-gate si_sk=p7->d.sign->signer_info;
6260Sstevel@tonic-gate os=PKCS7_get_octet_string(p7->d.sign->contents);
6270Sstevel@tonic-gate /* If detached data then the content is excluded */
6280Sstevel@tonic-gate if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
6290Sstevel@tonic-gate M_ASN1_OCTET_STRING_free(os);
6300Sstevel@tonic-gate p7->d.sign->contents->d.data = NULL;
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate break;
633*2139Sjp161948
634*2139Sjp161948 case NID_pkcs7_digest:
635*2139Sjp161948 os=PKCS7_get_octet_string(p7->d.digest->contents);
636*2139Sjp161948 /* If detached data then the content is excluded */
637*2139Sjp161948 if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
638*2139Sjp161948 {
639*2139Sjp161948 M_ASN1_OCTET_STRING_free(os);
640*2139Sjp161948 p7->d.digest->contents->d.data = NULL;
641*2139Sjp161948 }
642*2139Sjp161948 break;
643*2139Sjp161948
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate if (si_sk != NULL)
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate if ((buf=BUF_MEM_new()) == NULL)
6490Sstevel@tonic-gate {
650*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
6510Sstevel@tonic-gate goto err;
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
6540Sstevel@tonic-gate {
6550Sstevel@tonic-gate si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
6560Sstevel@tonic-gate if (si->pkey == NULL) continue;
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate j=OBJ_obj2nid(si->digest_alg->algorithm);
6590Sstevel@tonic-gate
6600Sstevel@tonic-gate btmp=bio;
661*2139Sjp161948
662*2139Sjp161948 btmp = PKCS7_find_digest(&mdc, btmp, j);
663*2139Sjp161948
664*2139Sjp161948 if (btmp == NULL)
665*2139Sjp161948 goto err;
666*2139Sjp161948
6670Sstevel@tonic-gate /* We now have the EVP_MD_CTX, lets do the
6680Sstevel@tonic-gate * signing. */
6690Sstevel@tonic-gate EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
6700Sstevel@tonic-gate if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
6710Sstevel@tonic-gate {
672*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
6730Sstevel@tonic-gate goto err;
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate sk=si->auth_attr;
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate /* If there are attributes, we add the digest
6790Sstevel@tonic-gate * attribute and only sign the attributes */
6800Sstevel@tonic-gate if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
6810Sstevel@tonic-gate {
6820Sstevel@tonic-gate unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
6830Sstevel@tonic-gate unsigned int md_len, alen;
6840Sstevel@tonic-gate ASN1_OCTET_STRING *digest;
6850Sstevel@tonic-gate ASN1_UTCTIME *sign_time;
6860Sstevel@tonic-gate const EVP_MD *md_tmp;
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate /* Add signing time if not already present */
6890Sstevel@tonic-gate if (!PKCS7_get_signed_attribute(si,
6900Sstevel@tonic-gate NID_pkcs9_signingTime))
6910Sstevel@tonic-gate {
692*2139Sjp161948 if (!(sign_time=X509_gmtime_adj(NULL,0)))
693*2139Sjp161948 {
694*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
695*2139Sjp161948 ERR_R_MALLOC_FAILURE);
696*2139Sjp161948 goto err;
697*2139Sjp161948 }
6980Sstevel@tonic-gate PKCS7_add_signed_attribute(si,
6990Sstevel@tonic-gate NID_pkcs9_signingTime,
7000Sstevel@tonic-gate V_ASN1_UTCTIME,sign_time);
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate /* Add digest */
7040Sstevel@tonic-gate md_tmp=EVP_MD_CTX_md(&ctx_tmp);
7050Sstevel@tonic-gate EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
706*2139Sjp161948 if (!(digest=M_ASN1_OCTET_STRING_new()))
707*2139Sjp161948 {
708*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
709*2139Sjp161948 ERR_R_MALLOC_FAILURE);
710*2139Sjp161948 goto err;
711*2139Sjp161948 }
712*2139Sjp161948 if (!M_ASN1_OCTET_STRING_set(digest,md_data,
713*2139Sjp161948 md_len))
714*2139Sjp161948 {
715*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
716*2139Sjp161948 ERR_R_MALLOC_FAILURE);
717*2139Sjp161948 goto err;
718*2139Sjp161948 }
7190Sstevel@tonic-gate PKCS7_add_signed_attribute(si,
7200Sstevel@tonic-gate NID_pkcs9_messageDigest,
7210Sstevel@tonic-gate V_ASN1_OCTET_STRING,digest);
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate /* Now sign the attributes */
7240Sstevel@tonic-gate EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
7250Sstevel@tonic-gate alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
7260Sstevel@tonic-gate ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
7270Sstevel@tonic-gate if(!abuf) goto err;
7280Sstevel@tonic-gate EVP_SignUpdate(&ctx_tmp,abuf,alen);
7290Sstevel@tonic-gate OPENSSL_free(abuf);
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
7330Sstevel@tonic-gate if (si->pkey->type == EVP_PKEY_DSA)
7340Sstevel@tonic-gate ctx_tmp.digest=EVP_dss1();
7350Sstevel@tonic-gate #endif
736*2139Sjp161948 #ifndef OPENSSL_NO_ECDSA
737*2139Sjp161948 if (si->pkey->type == EVP_PKEY_EC)
738*2139Sjp161948 ctx_tmp.digest=EVP_ecdsa();
739*2139Sjp161948 #endif
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
7420Sstevel@tonic-gate (unsigned int *)&buf->length,si->pkey))
7430Sstevel@tonic-gate {
744*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
7450Sstevel@tonic-gate goto err;
7460Sstevel@tonic-gate }
7470Sstevel@tonic-gate if (!ASN1_STRING_set(si->enc_digest,
7480Sstevel@tonic-gate (unsigned char *)buf->data,buf->length))
7490Sstevel@tonic-gate {
750*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
7510Sstevel@tonic-gate goto err;
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate }
755*2139Sjp161948 else if (i == NID_pkcs7_digest)
756*2139Sjp161948 {
757*2139Sjp161948 unsigned char md_data[EVP_MAX_MD_SIZE];
758*2139Sjp161948 unsigned int md_len;
759*2139Sjp161948 if (!PKCS7_find_digest(&mdc, bio,
760*2139Sjp161948 OBJ_obj2nid(p7->d.digest->md->algorithm)))
761*2139Sjp161948 goto err;
762*2139Sjp161948 EVP_DigestFinal_ex(mdc,md_data,&md_len);
763*2139Sjp161948 M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
764*2139Sjp161948 }
7650Sstevel@tonic-gate
7660Sstevel@tonic-gate if (!PKCS7_is_detached(p7))
7670Sstevel@tonic-gate {
7680Sstevel@tonic-gate btmp=BIO_find_type(bio,BIO_TYPE_MEM);
7690Sstevel@tonic-gate if (btmp == NULL)
7700Sstevel@tonic-gate {
771*2139Sjp161948 PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
7720Sstevel@tonic-gate goto err;
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate BIO_get_mem_ptr(btmp,&buf_mem);
7750Sstevel@tonic-gate /* Mark the BIO read only then we can use its copy of the data
7760Sstevel@tonic-gate * instead of making an extra copy.
7770Sstevel@tonic-gate */
7780Sstevel@tonic-gate BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
7790Sstevel@tonic-gate BIO_set_mem_eof_return(btmp, 0);
7800Sstevel@tonic-gate os->data = (unsigned char *)buf_mem->data;
7810Sstevel@tonic-gate os->length = buf_mem->length;
7820Sstevel@tonic-gate #if 0
7830Sstevel@tonic-gate M_ASN1_OCTET_STRING_set(os,
7840Sstevel@tonic-gate (unsigned char *)buf_mem->data,buf_mem->length);
7850Sstevel@tonic-gate #endif
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate ret=1;
7880Sstevel@tonic-gate err:
7890Sstevel@tonic-gate EVP_MD_CTX_cleanup(&ctx_tmp);
7900Sstevel@tonic-gate if (buf != NULL) BUF_MEM_free(buf);
7910Sstevel@tonic-gate return(ret);
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate
PKCS7_dataVerify(X509_STORE * cert_store,X509_STORE_CTX * ctx,BIO * bio,PKCS7 * p7,PKCS7_SIGNER_INFO * si)7940Sstevel@tonic-gate int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
7950Sstevel@tonic-gate PKCS7 *p7, PKCS7_SIGNER_INFO *si)
7960Sstevel@tonic-gate {
7970Sstevel@tonic-gate PKCS7_ISSUER_AND_SERIAL *ias;
7980Sstevel@tonic-gate int ret=0,i;
7990Sstevel@tonic-gate STACK_OF(X509) *cert;
8000Sstevel@tonic-gate X509 *x509;
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate if (PKCS7_type_is_signed(p7))
8030Sstevel@tonic-gate {
8040Sstevel@tonic-gate cert=p7->d.sign->cert;
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate else if (PKCS7_type_is_signedAndEnveloped(p7))
8070Sstevel@tonic-gate {
8080Sstevel@tonic-gate cert=p7->d.signed_and_enveloped->cert;
8090Sstevel@tonic-gate }
8100Sstevel@tonic-gate else
8110Sstevel@tonic-gate {
8120Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
8130Sstevel@tonic-gate goto err;
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate /* XXXXXXXXXXXXXXXXXXXXXXX */
8160Sstevel@tonic-gate ias=si->issuer_and_serial;
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
8190Sstevel@tonic-gate
8200Sstevel@tonic-gate /* were we able to find the cert in passed to us */
8210Sstevel@tonic-gate if (x509 == NULL)
8220Sstevel@tonic-gate {
8230Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
8240Sstevel@tonic-gate goto err;
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate
8270Sstevel@tonic-gate /* Lets verify */
8280Sstevel@tonic-gate if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
8290Sstevel@tonic-gate {
8300Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
8310Sstevel@tonic-gate goto err;
8320Sstevel@tonic-gate }
8330Sstevel@tonic-gate X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
8340Sstevel@tonic-gate i=X509_verify_cert(ctx);
8350Sstevel@tonic-gate if (i <= 0)
8360Sstevel@tonic-gate {
8370Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
8380Sstevel@tonic-gate X509_STORE_CTX_cleanup(ctx);
8390Sstevel@tonic-gate goto err;
8400Sstevel@tonic-gate }
8410Sstevel@tonic-gate X509_STORE_CTX_cleanup(ctx);
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate return PKCS7_signatureVerify(bio, p7, si, x509);
8440Sstevel@tonic-gate err:
8450Sstevel@tonic-gate return ret;
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
PKCS7_signatureVerify(BIO * bio,PKCS7 * p7,PKCS7_SIGNER_INFO * si,X509 * x509)8480Sstevel@tonic-gate int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
8490Sstevel@tonic-gate X509 *x509)
8500Sstevel@tonic-gate {
8510Sstevel@tonic-gate ASN1_OCTET_STRING *os;
8520Sstevel@tonic-gate EVP_MD_CTX mdc_tmp,*mdc;
8530Sstevel@tonic-gate int ret=0,i;
8540Sstevel@tonic-gate int md_type;
8550Sstevel@tonic-gate STACK_OF(X509_ATTRIBUTE) *sk;
8560Sstevel@tonic-gate BIO *btmp;
8570Sstevel@tonic-gate EVP_PKEY *pkey;
8580Sstevel@tonic-gate
8590Sstevel@tonic-gate EVP_MD_CTX_init(&mdc_tmp);
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate if (!PKCS7_type_is_signed(p7) &&
8620Sstevel@tonic-gate !PKCS7_type_is_signedAndEnveloped(p7)) {
8630Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
8640Sstevel@tonic-gate PKCS7_R_WRONG_PKCS7_TYPE);
8650Sstevel@tonic-gate goto err;
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate md_type=OBJ_obj2nid(si->digest_alg->algorithm);
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate btmp=bio;
8710Sstevel@tonic-gate for (;;)
8720Sstevel@tonic-gate {
8730Sstevel@tonic-gate if ((btmp == NULL) ||
8740Sstevel@tonic-gate ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
8750Sstevel@tonic-gate {
8760Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
8770Sstevel@tonic-gate PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
8780Sstevel@tonic-gate goto err;
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate BIO_get_md_ctx(btmp,&mdc);
8810Sstevel@tonic-gate if (mdc == NULL)
8820Sstevel@tonic-gate {
8830Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
8840Sstevel@tonic-gate ERR_R_INTERNAL_ERROR);
8850Sstevel@tonic-gate goto err;
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate if (EVP_MD_CTX_type(mdc) == md_type)
8880Sstevel@tonic-gate break;
8890Sstevel@tonic-gate /* Workaround for some broken clients that put the signature
8900Sstevel@tonic-gate * OID instead of the digest OID in digest_alg->algorithm
8910Sstevel@tonic-gate */
8920Sstevel@tonic-gate if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
8930Sstevel@tonic-gate break;
8940Sstevel@tonic-gate btmp=BIO_next(btmp);
8950Sstevel@tonic-gate }
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate /* mdc is the digest ctx that we want, unless there are attributes,
8980Sstevel@tonic-gate * in which case the digest is the signed attributes */
8990Sstevel@tonic-gate EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate sk=si->auth_attr;
9020Sstevel@tonic-gate if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
9030Sstevel@tonic-gate {
9040Sstevel@tonic-gate unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
9050Sstevel@tonic-gate unsigned int md_len, alen;
9060Sstevel@tonic-gate ASN1_OCTET_STRING *message_digest;
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
9090Sstevel@tonic-gate message_digest=PKCS7_digest_from_attributes(sk);
9100Sstevel@tonic-gate if (!message_digest)
9110Sstevel@tonic-gate {
9120Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
9130Sstevel@tonic-gate PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
9140Sstevel@tonic-gate goto err;
9150Sstevel@tonic-gate }
9160Sstevel@tonic-gate if ((message_digest->length != (int)md_len) ||
9170Sstevel@tonic-gate (memcmp(message_digest->data,md_dat,md_len)))
9180Sstevel@tonic-gate {
9190Sstevel@tonic-gate #if 0
9200Sstevel@tonic-gate {
9210Sstevel@tonic-gate int ii;
9220Sstevel@tonic-gate for (ii=0; ii<message_digest->length; ii++)
9230Sstevel@tonic-gate printf("%02X",message_digest->data[ii]); printf(" sent\n");
9240Sstevel@tonic-gate for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate #endif
9270Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
9280Sstevel@tonic-gate PKCS7_R_DIGEST_FAILURE);
9290Sstevel@tonic-gate ret= -1;
9300Sstevel@tonic-gate goto err;
9310Sstevel@tonic-gate }
9320Sstevel@tonic-gate
9330Sstevel@tonic-gate EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL);
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
9360Sstevel@tonic-gate ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
9370Sstevel@tonic-gate EVP_VerifyUpdate(&mdc_tmp, abuf, alen);
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate OPENSSL_free(abuf);
9400Sstevel@tonic-gate }
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate os=si->enc_digest;
9430Sstevel@tonic-gate pkey = X509_get_pubkey(x509);
9440Sstevel@tonic-gate if (!pkey)
9450Sstevel@tonic-gate {
9460Sstevel@tonic-gate ret = -1;
9470Sstevel@tonic-gate goto err;
9480Sstevel@tonic-gate }
9490Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
9500Sstevel@tonic-gate if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
9510Sstevel@tonic-gate #endif
952*2139Sjp161948 #ifndef OPENSSL_NO_ECDSA
953*2139Sjp161948 if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
954*2139Sjp161948 #endif
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
9570Sstevel@tonic-gate EVP_PKEY_free(pkey);
9580Sstevel@tonic-gate if (i <= 0)
9590Sstevel@tonic-gate {
9600Sstevel@tonic-gate PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
9610Sstevel@tonic-gate PKCS7_R_SIGNATURE_FAILURE);
9620Sstevel@tonic-gate ret= -1;
9630Sstevel@tonic-gate goto err;
9640Sstevel@tonic-gate }
9650Sstevel@tonic-gate else
9660Sstevel@tonic-gate ret=1;
9670Sstevel@tonic-gate err:
9680Sstevel@tonic-gate EVP_MD_CTX_cleanup(&mdc_tmp);
9690Sstevel@tonic-gate return(ret);
9700Sstevel@tonic-gate }
9710Sstevel@tonic-gate
PKCS7_get_issuer_and_serial(PKCS7 * p7,int idx)9720Sstevel@tonic-gate PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
9730Sstevel@tonic-gate {
9740Sstevel@tonic-gate STACK_OF(PKCS7_RECIP_INFO) *rsk;
9750Sstevel@tonic-gate PKCS7_RECIP_INFO *ri;
9760Sstevel@tonic-gate int i;
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate i=OBJ_obj2nid(p7->type);
9790Sstevel@tonic-gate if (i != NID_pkcs7_signedAndEnveloped) return(NULL);
9800Sstevel@tonic-gate rsk=p7->d.signed_and_enveloped->recipientinfo;
9810Sstevel@tonic-gate ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
9820Sstevel@tonic-gate if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
9830Sstevel@tonic-gate ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
9840Sstevel@tonic-gate return(ri->issuer_and_serial);
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate
PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO * si,int nid)9870Sstevel@tonic-gate ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
9880Sstevel@tonic-gate {
9890Sstevel@tonic-gate return(get_attribute(si->auth_attr,nid));
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate
PKCS7_get_attribute(PKCS7_SIGNER_INFO * si,int nid)9920Sstevel@tonic-gate ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
9930Sstevel@tonic-gate {
9940Sstevel@tonic-gate return(get_attribute(si->unauth_attr,nid));
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
get_attribute(STACK_OF (X509_ATTRIBUTE)* sk,int nid)9970Sstevel@tonic-gate static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
9980Sstevel@tonic-gate {
9990Sstevel@tonic-gate int i;
10000Sstevel@tonic-gate X509_ATTRIBUTE *xa;
10010Sstevel@tonic-gate ASN1_OBJECT *o;
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate o=OBJ_nid2obj(nid);
10040Sstevel@tonic-gate if (!o || !sk) return(NULL);
10050Sstevel@tonic-gate for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
10060Sstevel@tonic-gate {
10070Sstevel@tonic-gate xa=sk_X509_ATTRIBUTE_value(sk,i);
10080Sstevel@tonic-gate if (OBJ_cmp(xa->object,o) == 0)
10090Sstevel@tonic-gate {
10100Sstevel@tonic-gate if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
10110Sstevel@tonic-gate return(sk_ASN1_TYPE_value(xa->value.set,0));
10120Sstevel@tonic-gate else
10130Sstevel@tonic-gate return(NULL);
10140Sstevel@tonic-gate }
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate return(NULL);
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate
PKCS7_digest_from_attributes(STACK_OF (X509_ATTRIBUTE)* sk)10190Sstevel@tonic-gate ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
10200Sstevel@tonic-gate {
10210Sstevel@tonic-gate ASN1_TYPE *astype;
10220Sstevel@tonic-gate if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
10230Sstevel@tonic-gate return astype->value.octet_string;
10240Sstevel@tonic-gate }
10250Sstevel@tonic-gate
PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO * p7si,STACK_OF (X509_ATTRIBUTE)* sk)10260Sstevel@tonic-gate int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
10270Sstevel@tonic-gate STACK_OF(X509_ATTRIBUTE) *sk)
10280Sstevel@tonic-gate {
10290Sstevel@tonic-gate int i;
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate if (p7si->auth_attr != NULL)
10320Sstevel@tonic-gate sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
10330Sstevel@tonic-gate p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
10340Sstevel@tonic-gate for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
10350Sstevel@tonic-gate {
10360Sstevel@tonic-gate if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
10370Sstevel@tonic-gate X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
10380Sstevel@tonic-gate == NULL)
10390Sstevel@tonic-gate return(0);
10400Sstevel@tonic-gate }
10410Sstevel@tonic-gate return(1);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
PKCS7_set_attributes(PKCS7_SIGNER_INFO * p7si,STACK_OF (X509_ATTRIBUTE)* sk)10440Sstevel@tonic-gate int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
10450Sstevel@tonic-gate {
10460Sstevel@tonic-gate int i;
10470Sstevel@tonic-gate
10480Sstevel@tonic-gate if (p7si->unauth_attr != NULL)
10490Sstevel@tonic-gate sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
10500Sstevel@tonic-gate X509_ATTRIBUTE_free);
10510Sstevel@tonic-gate p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
10520Sstevel@tonic-gate for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
10530Sstevel@tonic-gate {
10540Sstevel@tonic-gate if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
10550Sstevel@tonic-gate X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
10560Sstevel@tonic-gate == NULL)
10570Sstevel@tonic-gate return(0);
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate return(1);
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate
PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO * p7si,int nid,int atrtype,void * value)10620Sstevel@tonic-gate int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
10630Sstevel@tonic-gate void *value)
10640Sstevel@tonic-gate {
10650Sstevel@tonic-gate return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
10660Sstevel@tonic-gate }
10670Sstevel@tonic-gate
PKCS7_add_attribute(PKCS7_SIGNER_INFO * p7si,int nid,int atrtype,void * value)10680Sstevel@tonic-gate int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
10690Sstevel@tonic-gate void *value)
10700Sstevel@tonic-gate {
10710Sstevel@tonic-gate return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
10720Sstevel@tonic-gate }
10730Sstevel@tonic-gate
add_attribute(STACK_OF (X509_ATTRIBUTE)** sk,int nid,int atrtype,void * value)10740Sstevel@tonic-gate static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
10750Sstevel@tonic-gate void *value)
10760Sstevel@tonic-gate {
10770Sstevel@tonic-gate X509_ATTRIBUTE *attr=NULL;
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate if (*sk == NULL)
10800Sstevel@tonic-gate {
10810Sstevel@tonic-gate *sk = sk_X509_ATTRIBUTE_new_null();
10820Sstevel@tonic-gate new_attrib:
10830Sstevel@tonic-gate attr=X509_ATTRIBUTE_create(nid,atrtype,value);
10840Sstevel@tonic-gate sk_X509_ATTRIBUTE_push(*sk,attr);
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate else
10870Sstevel@tonic-gate {
10880Sstevel@tonic-gate int i;
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++)
10910Sstevel@tonic-gate {
10920Sstevel@tonic-gate attr=sk_X509_ATTRIBUTE_value(*sk,i);
10930Sstevel@tonic-gate if (OBJ_obj2nid(attr->object) == nid)
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate X509_ATTRIBUTE_free(attr);
10960Sstevel@tonic-gate attr=X509_ATTRIBUTE_create(nid,atrtype,value);
10970Sstevel@tonic-gate sk_X509_ATTRIBUTE_set(*sk,i,attr);
10980Sstevel@tonic-gate goto end;
10990Sstevel@tonic-gate }
11000Sstevel@tonic-gate }
11010Sstevel@tonic-gate goto new_attrib;
11020Sstevel@tonic-gate }
11030Sstevel@tonic-gate end:
11040Sstevel@tonic-gate return(1);
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate
1107