Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder(MessageDigest::Algorithm mesDigAlgorithm,
			Certificate &cert, PrivateKey &privKey, bool attached)
		throw (Pkcs7Exception)
{
	int rc;
	PKCS7_SIGNER_INFO *si;
	PKCS7_set_type(this->pkcs7, NID_pkcs7_signed);
	PKCS7_content_new(this->pkcs7, NID_pkcs7_data);
	if (!attached)
	{
		PKCS7_set_detached(this->pkcs7, 1);
	}
	si = PKCS7_add_signature(this->pkcs7, cert.getX509(), privKey.getEvpPkey(), MessageDigest::getMessageDigest(mesDigAlgorithm));
	if (!si)
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_SIGNER, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true);
	}
	rc = PKCS7_add_certificate(this->pkcs7, cert.getX509());
	if (!rc)
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_CERTIFICATE, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true);
	}
	this->state = Pkcs7Builder::INIT;
}
Exemple #2
0
static LUA_FUNCTION(openssl_pkcs7_add)
{
  PKCS7 *p7 = CHECK_OBJECT(1, PKCS7, "openssl.pkcs7");
  int n = lua_gettop(L);
  int i, ret;
  ret = 1;
  luaL_argcheck(L, lua_isuserdata(L, 2), 2, "must supply certificate or crl object");
  for (i = 2; i <= n; i++)
  {
    luaL_argcheck(L, auxiliar_isclass(L, "openssl.x509", i) || auxiliar_isclass(L, "openssl.x509_crl", i),
                  i, "must supply certificate or crl object");

    if (auxiliar_isclass(L, "openssl.x509", i))
    {
      X509* x = CHECK_OBJECT(i, X509, "openssl.x509");
      ret = PKCS7_add_certificate(p7, x);
    }
    else
    {
      X509_CRL *crl = CHECK_OBJECT(i, X509_CRL, "openssl.x509_crl");
      ret = PKCS7_add_crl(p7, crl);
    }
    luaL_argcheck(L, ret, i, "add to pkcs7 fail");
  }
  return openssl_pushresult(L, ret);
}
Exemple #3
0
void pki_pkcs7::addCert(pki_x509 *crt)
{
	if (p7 == NULL || crt == NULL)
		return;
	PKCS7_add_certificate(p7, crt->getCert());
	openssl_error();
}
Exemple #4
0
int PKI_X509_PKCS7_add_signer ( PKI_X509_PKCS7 *p7, PKI_X509_CERT *signer,
			PKI_X509_KEYPAIR *k, PKI_DIGEST_ALG *md ) {

	PKCS7_SIGNER_INFO *signerInfo = NULL;

	if ( !p7 || !signer || !k ) {
		if ( !p7 ) PKI_log_debug ( "!p7");
		if ( !signer ) PKI_log_debug ( "!signer");
		if ( !k ) PKI_log_debug ( "!key");
		return PKI_ERR;
	}

	if ( !p7->value || !signer->value || !k->value ) {
		if ( !p7->value ) PKI_log_debug ( "!p7->value");
		if ( !signer->value ) PKI_log_debug ( "!signer->value");
		if ( !k->value ) PKI_log_debug ( "!key->value");
		return PKI_ERR;
	}

	if( !md ) md = PKI_DIGEST_ALG_DEFAULT;

	if((signerInfo = PKCS7_add_signature( p7->value, 
					signer->value, k->value, md)) == NULL) {
		return ( PKI_ERR );
	}
	PKCS7_add_certificate ( p7->value, signer->value );

	return ( PKI_OK );

}
Exemple #5
0
extern "C" int32_t CryptoNative_Pkcs7AddCertificate(PKCS7* p7, X509* x509)
{
    if (p7 == nullptr || x509 == nullptr)
    {
        return 0;
    }

    return PKCS7_add_certificate(p7, x509);
}
Exemple #6
0
int32_t CryptoNative_Pkcs7AddCertificate(PKCS7* p7, X509* x509)
{
    if (p7 == NULL || x509 == NULL)
    {
        return 0;
    }

    return PKCS7_add_certificate(p7, x509);
}
Exemple #7
0
int PKI_X509_PKCS7_add_cert (PKI_X509_PKCS7 *p7, PKI_X509_CERT *x) {

	if ( !p7 || !p7->value || !x || !x->value ) {
		PKI_log_err( "PKI_X509_PKCS7_add_cert()::Missing required param!");
		return PKI_ERR;
	}

	PKCS7_add_certificate( p7->value, x->value );

	return( PKI_OK );
}
static VALUE
ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
{
    PKCS7 *pkcs7;
    X509 *x509;

    GetPKCS7(self, pkcs7);
    x509 = GetX509CertPtr(cert);  /* NO NEED TO DUP */
    if (!PKCS7_add_certificate(pkcs7, x509)){
	ossl_raise(ePKCS7Error, NULL);
    }

    return self;
}
void Pkcs7SignedDataBuilder::addCertificate(Certificate &cert) throw (Pkcs7Exception, InvalidStateException)
{
	int rc;
	if (this->state != Pkcs7Builder::INIT && this->state != Pkcs7Builder::UPDATE)
	{
		throw InvalidStateException("Pkcs7SignedDataBuilder::addCertificate");
	}

	rc = PKCS7_add_certificate(this->pkcs7, cert.getX509());
	if (!rc)
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_CERTIFICATE, "Pkcs7SignedDataBuilder::addCertificate", true);
	}
}
Exemple #10
0
int PKI_X509_PKCS7_add_cert_stack ( PKI_X509_PKCS7 *p7, 
						PKI_X509_CERT_STACK *x_sk ) {
	int i;

	if( !p7 || !p7->value || !x_sk ) {
		PKI_log_err( "PKI_X509_PKCS7_add_crl_stack()::Missing param!");
		return PKI_ERR;
	}

	for( i=0; i < PKI_STACK_X509_CERT_elements( x_sk ); i++ ) {
		PKI_X509_CERT *x = NULL;

		if(( x = PKI_STACK_X509_CERT_get_num( x_sk, i )) == NULL) {
			continue;
		}

		PKCS7_add_certificate( p7->value, x->value );
	}

	return ( PKI_OK );
}
void Pkcs7SignedDataBuilder::addSigner(MessageDigest::Algorithm mesDigAlgorithm, Certificate &cert, PrivateKey &privKey)
		throw (Pkcs7Exception, InvalidStateException)
{
	int rc;
	if (this->state != Pkcs7Builder::INIT)
	{
		throw InvalidStateException("Pkcs7SignedDataBuilder::addSigner");
	}
	if (!PKCS7_add_signature(this->pkcs7, cert.getX509(), privKey.getEvpPkey(), MessageDigest::getMessageDigest(mesDigAlgorithm)))
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_SIGNER, "Pkcs7SignedDataBuilder::addSigner", true);
	}
	rc = PKCS7_add_certificate(this->pkcs7, cert.getX509());
	if (!rc)//inversor adicionado (martin 28/11/07)
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_CERTIFICATE, "Pkcs7SignedDataBuilder::addSigner", true);
	}
}
void Pkcs7SignedDataBuilder::init(MessageDigest::Algorithm mesDigAlgorithm, Certificate &cert,
			PrivateKey &privKey, bool attached)
	throw (Pkcs7Exception)
{
	int rc;
	if (this->state != Pkcs7Builder::NO_INIT)
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		if (this->state == Pkcs7Builder::UPDATE)
		{
			BIO_free(this->p7bio);
			this->p7bio = NULL;
		}
	}
	this->pkcs7 = PKCS7_new();
	PKCS7_set_type(this->pkcs7, NID_pkcs7_signed);
	if (!attached)
	{
		PKCS7_set_detached(this->pkcs7, 1);
	}
	if (!PKCS7_add_signature(this->pkcs7, cert.getX509(), privKey.getEvpPkey(), MessageDigest::getMessageDigest(mesDigAlgorithm)))
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_SIGNER, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true);
	}
	rc = PKCS7_add_certificate(this->pkcs7, cert.getX509());
	if (!rc)//inversor adicionado (martin 28/11/07)
	{
		PKCS7_free(this->pkcs7);
		this->pkcs7 = NULL;
		throw Pkcs7Exception(Pkcs7Exception::ADDING_CERTIFICATE, "Pkcs7SignedDataBuilder::Pkcs7SignedDataBuilder", true);
	}
	this->state = Pkcs7Builder::INIT;
}
Exemple #13
0
/*******************************************************************************
函数名称: cert_pkcs7_wrap
功能描述: 将要发送的消息采用PKCS#7格式进行编码
输入参数: struct scep *s, SCEP操作的结构体指针。
     s32 hasra, 是否使用RA证书,1,使用;0,不使用

输出参数: 无
返 回 值: 1,成功;-1,失败
--------------------------------------------------------------------------------
最近一次修改记录:
修改作者:王朝
修改目的:添加新函数
修改日期:2009年12月28日
*********************************************************************************/
s32 cert_pkcs7_wrap(struct scep *s, s32 hasra)
{
	BIO *databio = NULL;
	BIO	*encbio = NULL;
	BIO	*pkcs7bio = NULL;
	BIO	*memorybio = NULL;
	BIO	*outbio = NULL;
	BIO	*base64bio = NULL;
	u8 *buffer = NULL;
	s32	len = 0;
	STACK_OF(X509) *recipients = NULL;
	PKCS7 *p7enc = NULL;
	PKCS7_SIGNER_INFO *si = NULL;
	STACK_OF(X509_ATTRIBUTE) *attributes = NULL;
	X509 *signercert = NULL;
	EVP_PKEY *signerkey = NULL;
    s32 retval = -1;

    /* sender nonce */
	s->sender_nonce_len = 16;
	s->sender_nonce = (u8 *)malloc((u32)s->sender_nonce_len);
	RAND_bytes(s->sender_nonce, s->sender_nonce_len);

	/* Prepare data payload */
	switch(s->request_type)
    {
		case SCEP_REQUEST_PKCSREQ:

			s->request_type_str = SCEP_REQUEST_PKCSREQ_STR;

			/* Signer cert */
			signercert = s->signercert;
			signerkey = s->signerkey;

			/* Read request in memory bio */
			databio = BIO_new(BIO_s_mem());
			if ((i2d_X509_REQ_bio(databio, cert_request)) <= 0)
            {
                goto end;
			}
			(void)BIO_flush(databio);
			BIO_set_flags(databio, BIO_FLAGS_MEM_RDONLY);
			break;

		case SCEP_REQUEST_GETCERTINIT:

			/* Set printable message type */
			s->request_type_str = SCEP_REQUEST_GETCERTINIT_STR;

			/* Signer cert */
			signercert = s->signercert;
			signerkey = s->signerkey;

			/* Read data in memory bio */
			databio = BIO_new(BIO_s_mem());
			if ((i2d_pkcs7_issuer_and_subject_bio(databio,	s->ias_getcertinit)) <= 0)
            {
				goto end;
			}
			(void)BIO_flush(databio);
			BIO_set_flags(databio, BIO_FLAGS_MEM_RDONLY);
			break;

        default:
            goto end;
	}
	/* Below this is the common code for all request_type */

	/* Read in the payload */
	s->request_len = BIO_get_mem_data(databio, &s->request_payload);

	BIO_free(databio);
    databio = NULL;

	/* Create encryption certificate stack */
	if (NULL == (recipients = sk_X509_new_null() ))
    {
		goto end;
	}

	/* Use different CA cert for encryption if requested */
	if (1 == hasra)
    {
		if (sk_X509_push(recipients, cert_encert) <= 0)
        {
			goto end;
		}
	}
    else
    {
        /* Use same CA cert also for encryption */
		if (sk_X509_push(recipients, cert_cacert) <= 0)
        {
			goto end;
		}
	}

	/* Create BIO for encryption  */
	if ((encbio = BIO_new_mem_buf(s->request_payload,s->request_len)) == NULL)
    {
        goto end;
	}

	/* Encrypt */
	if (NULL == (p7enc = PKCS7_encrypt(recipients, encbio,	cert_enc_alg, PKCS7_BINARY)))
    {
        goto end;
	}

    BIO_free(encbio);
    encbio = NULL;
    sk_X509_free(recipients);
    recipients = NULL;

	/* Write encrypted data */
	memorybio = BIO_new(BIO_s_mem());
	if (i2d_PKCS7_bio(memorybio, p7enc) <= 0)
    {
        goto end;
	}

    PKCS7_free(p7enc);
    p7enc = NULL;
	(void)BIO_flush(memorybio);
	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY);
	len = BIO_get_mem_data(memorybio, &buffer);

	/* Create outer PKCS#7  */
	s->request_p7 = PKCS7_new();
	if (s->request_p7 == NULL)
    {
		goto end;
	}
	if (!PKCS7_set_type(s->request_p7, NID_pkcs7_signed))
    {
		goto end;
	}

	/* Add signer certificate  and signature */
	PKCS7_add_certificate(s->request_p7, signercert);
	if ((si = PKCS7_add_signature(s->request_p7,signercert, signerkey, cert_sig_alg)) == NULL)
    {
        goto end;
	}

	/* Set signed attributes */
	attributes = sk_X509_ATTRIBUTE_new_null();
	cert_add_attribute_string(attributes, nid_transId, s->transaction_id);
	cert_add_attribute_string(attributes, nid_messageType, s->request_type_str);
	cert_add_attribute_octet(attributes, nid_senderNonce, (s8 *)(s->sender_nonce),s->sender_nonce_len);
	PKCS7_set_signed_attributes(si, attributes);
    sk_X509_ATTRIBUTE_free(attributes);
    attributes = NULL;

	/* Add contentType */
	if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)))
    {
        goto end;
	}


	/* Create new content */
	if (!PKCS7_content_new(s->request_p7, NID_pkcs7_data))
    {
		goto end;
	}

	/* Write data  */
	pkcs7bio = PKCS7_dataInit(s->request_p7, NULL);
	if (pkcs7bio == NULL)
    {
		goto end;
	}
	if (len != BIO_write(pkcs7bio, buffer, len))
    {
		goto end;
	}

    BIO_free(memorybio);
    memorybio = NULL;

	/* Finalize PKCS#7  */
	if (!PKCS7_dataFinal(s->request_p7, pkcs7bio))
    {
        goto end;
	}

	/* base64-encode the data */

	/* Create base64 filtering bio */
	memorybio = BIO_new(BIO_s_mem());
	base64bio = BIO_new(BIO_f_base64());
	outbio = BIO_push(base64bio, memorybio);

	/* Copy PKCS#7 */
	i2d_PKCS7_bio(outbio, s->request_p7);
	(void)BIO_flush(outbio);
	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY);
	s->request_len = BIO_get_mem_data(memorybio, &s->request_payload);

    retval = 1;

   end:

    if(NULL != databio)
    {
        BIO_free(databio);
    }

    if(NULL != encbio)
    {
        BIO_free(encbio);
    }
    
    if(NULL != p7enc)
    {
        PKCS7_free(p7enc);
    }

    if(NULL != pkcs7bio)
    {
        BIO_free(pkcs7bio);
    }

    if(NULL != memorybio)
    {
        BIO_free(memorybio);
    }

    if(NULL != base64bio)
    {
        BIO_free(base64bio);
    }

	if(NULL != recipients)
	{
        sk_X509_free(recipients);
    }

    if(NULL != attributes)
	{
        sk_X509_ATTRIBUTE_free(attributes);
    }

	return retval;
}
int create_envelope(PluginInstance *inst, u8 **data, int *datalen)
{
        int r;
        PKCS7 *p7 = NULL;
        X509 *x509 = NULL;
	PKCS7_SIGNER_INFO *si = NULL;
        EVP_PKEY *pkey = NULL;
	BIO *in = NULL, *p7bio = NULL;
	u8 *buf;
        
	r = extract_certificate_and_pkey(inst, &x509, &pkey);
	if (r)
		goto err;
        p7 = PKCS7_new();
        if (p7 == NULL) {
        	r = -1;
        	goto err;
        }
        r = PKCS7_set_type(p7, NID_pkcs7_signed);
        if (r != 1) {
        	r = -1;
                goto err;
	}
	EVP_add_digest(EVP_sha1());
        si = PKCS7_add_signature(p7, x509, pkey, EVP_sha1());
        if (si == NULL) {
        	r = -1;
		goto err;
	}
	PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT,
				   OBJ_nid2obj(NID_pkcs7_data));
	r = PKCS7_add_certificate(p7, x509);
	if (r != 1) {
		printf("PKCS7_add_certificate failed.\n");
		goto err;
	}
	PKCS7_content_new(p7, NID_pkcs7_data);

	p7bio = PKCS7_dataInit(p7, NULL);
	if (p7bio == NULL) {
        	r = -1;
		goto err;
	}
	in = BIO_new_mem_buf(inst->signdata, inst->signdata_len);
	if (in == NULL) {
		r = -1;
		goto err;
	}
	for (;;) {
		char lbuf[1024];
		int i = BIO_read(in, lbuf, sizeof(lbuf));
		if (i <= 0)
			break;
		BIO_write(p7bio, lbuf, i);
	}
	if (!PKCS7_dataFinal(p7, p7bio)) {
		r = -1;
		goto err;
	}
	/* FIXME: remove this */
	r = i2d_PKCS7(p7, NULL);
	if (r <= 0) {
		r = -1;
		goto err;
	}
	buf = (u8 *) malloc(r);
	if (buf == NULL)
		goto err;
	*data = buf;
	r = i2d_PKCS7(p7, &buf);
	*datalen = r;
	if (r <= 0) {
		free(buf);
		r = -1;
		goto err;
	}
	r = 0;
err:
	if (p7)
		PKCS7_free(p7);
	if (in)
		BIO_free(in);
	if (p7bio)
		BIO_free(p7bio);
#if 0
	if (si)
		PKCS7_SIGNER_INFO_free(si);
#endif
	if (pkey)
		EVP_PKEY_free(pkey);
	if (x509)
		X509_free(x509);
	if (r) {
#if 0
		ERR_load_crypto_strings();
		ERR_print_errors_fp(stderr);
#endif
	}
        return r;
}
Exemple #15
0
/*
 * Wrap data in PKCS#7 envelopes and base64-encode the result.
 * Data is PKCS#10 request in PKCSReq, or pkcs7_issuer_and_subject
 * structure in GetCertInitial and PKCS7_ISSUER_AND_SERIAL in
 * GetCert and GETCrl.
 */
int pkcs7_wrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info)
{
    BIO *databio = NULL;
    BIO *encbio = NULL;
    BIO *pkcs7bio = NULL;
    BIO *memorybio = NULL;
    BIO *outbio = NULL;
    unsigned char *buffer = NULL;
    int len = 0;
    STACK_OF(X509) *recipients = NULL;
    PKCS7 *p7enc = NULL;
    PKCS7_SIGNER_INFO *si;
    STACK_OF(X509_ATTRIBUTE) *attributes;
    X509 *signercert = NULL;
    EVP_PKEY *signerkey = NULL;
    int ret = SCEP_PKISTATUS_P7;
    char *payload = NULL;
    int payload_len;

    /* Create a new sender nonce for all messages
     * XXXXXXXXXXXXXX should it be per transaction? */
    s->sender_nonce_len = 16;
    free(s->sender_nonce);/* Clean up from previous runs */
    s->sender_nonce = (char *)malloc(s->sender_nonce_len * sizeof(char));
    RAND_bytes((unsigned char *) s->sender_nonce, s->sender_nonce_len);

    /* Prepare data payload */
    switch (s->request_type) {
        case SCEP_REQUEST_PKCSREQ:
            /*
             * Set printable message type
             * We set this later as an autheticated attribute
             * "messageType".
             */
            s->request_type_str = SCEP_REQUEST_PKCSREQ_STR;

            /* Signer cert */
            signercert = s->signercert;
            signerkey = s->signerkey;

            /* Create inner PKCS#7  */
            if (ctx->verbose){
                qeo_log_i("creating inner PKCS#7");
            }

            /* Read request in memory bio */
            databio = BIO_new(BIO_s_mem());
            if (i2d_X509_REQ_bio(databio, op_info->request) <= 0) {
                qeo_log_e("error writing certificate request in bio");
                goto error;
            }
            (void)BIO_flush(databio);
            break;

        case SCEP_REQUEST_GETCERTINIT:

            /* Set printable message type */
            s->request_type_str = SCEP_REQUEST_GETCERTINIT_STR;

            /* Signer cert */
            signercert = s->signercert;
            signerkey = s->signerkey;

            /* Create inner PKCS#7  */
            if (ctx->verbose){
                qeo_log_i("creating inner PKCS#7");
            }

            /* Read data in memory bio */
            databio = BIO_new(BIO_s_mem());
            if (i2d_pkcs7_issuer_and_subject_bio(databio, s->ias_getcertinit)) {
                qeo_log_e("error writing GetCertInitial data in bio");
                goto error;
            }
            (void)BIO_flush(databio);
            break;
    }
    /* Below this is the common code for all request_type */

    /* Read in the payload */
    payload_len = BIO_get_mem_data(databio, &payload);
    if (ctx->verbose){
        qeo_log_i("data payload size: %d bytes", payload_len);
    }

    /* Create encryption certificate stack */
    if ((recipients = sk_X509_new(NULL) ) == NULL) {
        qeo_log_e("error creating certificate stack");
        goto error;
    }
    if (sk_X509_push(recipients, op_info->racert) <= 0) {
        qeo_log_e("error adding recipient encryption certificate");
        goto error;
    }

    /* Create BIO for encryption  */
    if ((encbio = BIO_new_mem_buf(payload, payload_len)) == NULL ) {
        qeo_log_e("error creating data bio");
        goto error;
    }

    /* Encrypt */
    if (!(p7enc = PKCS7_encrypt(recipients, encbio, ctx->enc_alg, PKCS7_BINARY))) {
        qeo_log_e("request payload encrypt failed");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("successfully encrypted payload");
    }

    /* Write encrypted data */
    memorybio = BIO_new(BIO_s_mem());
    if (i2d_PKCS7_bio(memorybio, p7enc) <= 0) {
        qeo_log_e("error writing encrypted data");
        goto error;
    }
    (void)BIO_flush(memorybio);
    BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY);
    len = BIO_get_mem_data(memorybio, &buffer);
    BIO_free(memorybio);
    memorybio=NULL;
    if (ctx->verbose){
        qeo_log_i("envelope size: %d bytes", len);
    }
    if (ctx->debug) {
        qeo_log_i("printing PEM fomatted PKCS#7");
        PEM_write_PKCS7(stdout, p7enc);
    }

    /* Create outer PKCS#7  */
    if (ctx->verbose){
        qeo_log_i("creating outer PKCS#7");
    }
    s->request_p7 = PKCS7_new();
    if (s->request_p7 == NULL ) {
        qeo_log_e("failed creating PKCS#7 for signing");
        goto error;
    }
    if (!PKCS7_set_type(s->request_p7, NID_pkcs7_signed)) {
        qeo_log_e("failed setting PKCS#7 type");
        goto error;
    }

    /* Add signer certificate  and signature */
    PKCS7_add_certificate(s->request_p7, signercert);
    if ((si = PKCS7_add_signature(s->request_p7, signercert, signerkey, ctx->sig_alg)) == NULL ) {
        qeo_log_e("error adding PKCS#7 signature");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("signature added successfully");
    }

    /* Set signed attributes */
    if (ctx->verbose){
        qeo_log_i("adding signed attributes");
    }
    attributes = sk_X509_ATTRIBUTE_new_null();
    add_attribute_string(attributes, ctx->nid_transId, s->transaction_id, ctx);
    add_attribute_string(attributes, ctx->nid_messageType, s->request_type_str, ctx);
    add_attribute_octet(attributes, ctx->nid_senderNonce, s->sender_nonce, s->sender_nonce_len, ctx);
    PKCS7_set_signed_attributes(si, attributes);
    sk_X509_ATTRIBUTE_pop_free(attributes, X509_ATTRIBUTE_free);

    /* Add contentType */
    if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))) {
        qeo_log_e("error adding NID_pkcs9_contentType");
        goto error;
    }

    /* Create new content */
    if (!PKCS7_content_new(s->request_p7, NID_pkcs7_data)) {
        qeo_log_e("failed setting PKCS#7 content type");
        goto error;
    }

    /* Write data  */
    pkcs7bio = PKCS7_dataInit(s->request_p7, NULL );
    if (pkcs7bio == NULL ) {
        qeo_log_e("error opening bio for writing PKCS#7 data");
        goto error;
    }
    if (len != BIO_write(pkcs7bio, buffer, len)) {
        qeo_log_e("error writing PKCS#7 data");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("PKCS#7 data written successfully");
    }

    /* Finalize PKCS#7  */
    if (!PKCS7_dataFinal(s->request_p7, pkcs7bio)) {
        qeo_log_e("error finalizing outer PKCS#7");
        goto error;
    }
    if (ctx->debug) {
        qeo_log_i("printing PEM fomatted PKCS#7");
        PEM_write_PKCS7(stdout, s->request_p7);
    }

    /* base64-encode the data */
    if (ctx->verbose){
        qeo_log_i("applying base64 encoding");
    }

    /* Create base64 filtering bio */
    memorybio = BIO_new(BIO_s_mem());
    outbio = BIO_push(BIO_new(BIO_f_base64()), memorybio);

    /* Copy PKCS#7 */
    i2d_PKCS7_bio(outbio, s->request_p7);
    (void)BIO_flush(outbio);
    payload_len = BIO_get_mem_data(memorybio, &payload);
    s->request_payload = (char*) malloc(sizeof(char)*payload_len);
    if (!s->request_payload){
        goto error;
    }
    s->request_len = payload_len;
    memcpy(s->request_payload, payload, s->request_len);
    if (ctx->verbose){
        qeo_log_i("base64 encoded payload size: %d bytes", payload_len);
    }

    ret = 0;
error:
    BIO_free(databio);
    BIO_free(encbio);
    BIO_free_all(pkcs7bio);
    BIO_free(memorybio);
    BIO_free(outbio);
    if (recipients != NULL){
        sk_X509_free(recipients);/* Only free the stack, not the certificates */
    }
    PKCS7_free(p7enc);
    OPENSSL_free(buffer);
    return ret;
}
Exemple #16
0
/* will return 0, 1, 3, or 99 */
static int
_pkgtrans(char *device1, char *device2, char **pkg, int options,
    keystore_handle_t keystore, char *keystore_alias)
{
	BIO			*p7_bio = NULL;
	EVP_PKEY		*privkey = NULL;
	PKCS7			*sec_pkcs7 = NULL;
	PKCS7_SIGNER_INFO	*sec_signerinfo = NULL;
	PKG_ERR			*err;
	STACK_OF(X509)		*cacerts = NULL;
	STACK_OF(X509)		*clcerts = NULL;
	STACK_OF(X509)		*sec_chain = NULL;
	X509			*pubcert = NULL;
	boolean_t		making_sig = B_FALSE;
	char			*src, *dst;
	int			errflg, i, n;
	struct			dm_buf *hdr;

	making_sig = (keystore != NULL) ? B_TRUE : B_FALSE;

	if (making_sig) {

		/* new error object */
		err = pkgerr_new();

		/* find matching cert and key */
		if (find_key_cert_pair(err, keystore,
		    keystore_alias, &privkey, &pubcert) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/* get CA certificates */
		if (find_ca_certs(err, keystore, &cacerts) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/* get CL (aka "chain") certificates */
		if (find_cl_certs(err, keystore, &clcerts) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/* initialize PKCS7 object to be filled in later */
		sec_pkcs7 = PKCS7_new();
		(void) PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed);
		sec_signerinfo = PKCS7_add_signature(sec_pkcs7,
		    pubcert, privkey, EVP_sha1());

		if (sec_signerinfo == NULL) {
			progerr(gettext(ERR_SEC), keystore_alias);
			ERR_print_errors_fp(stderr);
			pkgerr_free(err);
			return (1);
		}

		/* add signer cert into signature */
		(void) PKCS7_add_certificate(sec_pkcs7, pubcert);

		/* attempt to resolve cert chain starting at the signer cert */
		if (get_cert_chain(err, pubcert, clcerts, cacerts,
		    &sec_chain) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/*
		 * add the verification chain of certs into the signature.
		 * The first cert is the user cert, which we don't need,
		 * since it's baked in already, so skip it
		 */
		for (i = 1; i < sk_X509_num(sec_chain); i++) {
			(void) PKCS7_add_certificate(sec_pkcs7,
			    sk_X509_value(sec_chain, i));
		}

		pkgerr_free(err);
		err = NULL;
	}

	if (signal_received > 0) {
		return (1);
	}

	/* transfer spool to appropriate device */
	if (devtype(device1, &srcdev)) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_BADDEV), device1);
		return (1);
	}
	srcdev.rdonly++;

	/* check for datastream */
	ids_name = NULL;
	if (srcdev.bdevice) {
		if (n = _getvol(srcdev.bdevice, NULL, NULL,
		    pkg_gt("Insert %v into %p."), srcdev.norewind)) {
			cleanup();
			if (n == 3)
				return (3);
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_GETVOL));
			return (1);
		}
		if (ds_readbuf(srcdev.cdevice))
			ids_name = srcdev.cdevice;
	}

	if (srcdev.cdevice && !srcdev.bdevice)
		ids_name = srcdev.cdevice;
	else if (srcdev.pathname) {
		ids_name = srcdev.pathname;
		if (access(ids_name, 0) == -1) {
			progerr(ERR_TRANSFER);
			logerr(pkg_gt(MSG_GETVOL));
			return (1);
		}
	}

	if (!ids_name && device2 == (char *)0) {
		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
			cleanup();
			return (n);
		}
		if (srcdev.mount && *srcdev.mount)
			pkgdir = strdup(srcdev.mount);
		return (0);
	}

	if (ids_name && device2 == (char *)0) {
		tmppath = tmpnam(NULL);
		tmppath = strdup(tmppath);
		if (tmppath == NULL) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_MEM));
			return (1);
		}
		if (mkdir(tmppath, 0755)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_MKDIR), tmppath);
			return (1);
		}
		device2 = tmppath;
	}

	if (devtype(device2, &dstdev)) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_BADDEV), device2);
		return (1);
	}

	if ((srcdev.cdevice && dstdev.cdevice) &&
	    strcmp(srcdev.cdevice, dstdev.cdevice) == 0) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_SAMEDEV));
		return (1);
	}

	ods_name = NULL;
	if (dstdev.cdevice && !dstdev.bdevice || dstdev.pathname)
		options |= PT_ODTSTREAM;

	if (options & PT_ODTSTREAM) {
		if (!((ods_name = dstdev.cdevice) != NULL ||
		    (ods_name = dstdev.pathname) != NULL)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_BADDEV), device2);
			return (1);
		}
		if (ids_name) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_TWODSTREAM));
			return (1);
		}
	} else {
		/*
		 * output device isn't a stream.  If we're making a signed
		 * package, then fail, since we can't make signed,
		 * non-stream pkgs
		 */
		if (making_sig) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(ERR_CANTSIGN));
			return (1);
		}
	}

	if ((srcdev.dirname && dstdev.dirname) &&
	    strcmp(srcdev.dirname, dstdev.dirname) == 0) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_SAMEDEV));
		return (1);
	}

	if ((srcdev.pathname && dstdev.pathname) &&
	    strcmp(srcdev.pathname, dstdev.pathname) == 0) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_SAMEDEV));
		return (1);
	}

	if (signal_received > 0) {
		return (1);
	}

	if (ids_name) {
		if (srcdev.cdevice && !srcdev.bdevice &&
		(n = _getvol(srcdev.cdevice, NULL, NULL, NULL,
		    srcdev.norewind))) {
			cleanup();
			if (n == 3)
				return (3);
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_GETVOL));
			return (1);
		}
		if (srcdev.dirname = tmpnam(NULL))
			tmpdir = srcdev.dirname = strdup(srcdev.dirname);

		if ((srcdev.dirname == NULL) || mkdir(srcdev.dirname, 0755) ||
		    chdir(srcdev.dirname)) {
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_NOTEMP), srcdev.dirname);
			cleanup();
			return (1);
		}
		if (ds_init(ids_name, pkg, srcdev.norewind)) {
			cleanup();
			return (1);
		}
	} else if (srcdev.mount) {
		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
			cleanup();
			return (n);
		}
	}

	src = srcdev.dirname;
	dst = dstdev.dirname;

	if (chdir(src)) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_CHDIR), src);
		cleanup();
		return (1);
	}

	if (signal_received > 0) {
		return (1);
	}

	xpkg = pkg = gpkglist(src, pkg, NULL);
	if (!pkg) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_NOPKGS), src);
		cleanup();
		return (1);
	}

	for (nxpkg = 0; pkg[nxpkg]; /* void */) {
		nxpkg++; /* count */
	}

	if (ids_name) {
		ds_order(pkg); /* order requests */
	}

	if (signal_received > 0) {
		return (1);
	}

	if (options & PT_ODTSTREAM) {
		char line[128];

		if (!dstdev.pathname &&
		    (n = _getvol(ods_name, NULL, DM_FORMAT, NULL,
		    dstdev.norewind))) {
			cleanup();
			if (n == 3)
				return (3);
			progerr(pkg_gt(ERR_TRANSFER));
			logerr(pkg_gt(MSG_GETVOL));
			return (1);
		}
		if ((hdr = genheader(src, pkg)) == NULL) {
			cleanup();
			return (1);
		}
		if (making_sig) {
			/* start up signature data stream */
			(void) PKCS7_content_new(sec_pkcs7, NID_pkcs7_data);
			(void) PKCS7_set_detached(sec_pkcs7, 1);
			p7_bio = PKCS7_dataInit(sec_pkcs7, NULL);

			/*
			 * Here we generate all the data that will go into
			 * the package, and send it through the signature
			 * generator, essentially calculating the signature
			 * of the entire package so we can place it in the
			 * header.  Otherwise we'd have to place it at the end
			 * of the pkg, which would break the ABI
			 */
			if (!(options & PT_SILENT)) {
				(void) fprintf(stderr, pkg_gt(MSG_SIGNING),
				    get_subject_display_name(pubcert));
			}
			if (dump_hdr_and_pkgs(p7_bio, hdr, pkg) != 0) {
			    progerr(gettext(ERR_NOGEN));
			    logerr(pkg_gt(MSG_GETVOL));
			    cleanup();
			    return (1);

			}

			BIO_flush(p7_bio);

			/*
			 * now generate PKCS7 signature
			 */
			if (!PKCS7_dataFinal(sec_pkcs7, p7_bio)) {
			    progerr(gettext(ERR_NOGEN));
			    logerr(pkg_gt(MSG_GETVOL));
			    cleanup();
			    return (1);
			}

			(void) BIO_free(p7_bio);
		}

		/* write out header to stream, which includes signature */
		if (wdsheader(hdr, src, ods_name, pkg, sec_pkcs7)) {
			cleanup();
			return (1);
		}

		if (sec_pkcs7 != NULL) {
			/* nuke in-memory signature for safety */
			PKCS7_free(sec_pkcs7);
			sec_pkcs7 = NULL;
		}

		ds_volno = 1; /* number of volumes in datastream */
		pinput = hdrbuf.text_buffer;
		/* skip past first line in header */
		(void) mgets(line, 128);
	}

	if (signal_received > 0) {
		return (1);
	}

	errflg = 0;

	for (i = 0; pkg[i]; i++) {

		if (signal_received > 0) {
			return (1);
		}

		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
			if (n = pkgmount(&dstdev, NULL, 0, 0, 1)) {
				cleanup();
				return (n);
			}
		}
		if (errflg = pkgxfer(pkg[i], options)) {
			pkg[i] = NULL;
			if ((options & PT_ODTSTREAM) || (errflg != 2))
				break;
		} else if (strcmp(dstinst, pkg[i]))
			pkg[i] = strdup(dstinst);
	}

	if (!(options & PT_ODTSTREAM) && dst) {
		pkgdir = strdup(dst);
	}

	/*
	 * No cleanup of temporary directories created in this
	 * function is done here. The calling function must do
	 * the cleanup.
	 */

	return (signal_received > 0 ? 1 : errflg);
}
Exemple #17
0
/*
 * Wrap data in PKCS#7 envelopes and base64-encode the result.
 * Data is PKCS#10 request in PKCSReq, or pkcs7_issuer_and_subject
 * structure in GetCertInitial and PKCS7_ISSUER_AND_SERIAL in
 * GetCert and GETCrl.
 */
int pkcs7_wrap(struct scep *s) {
	BIO			*databio = NULL;
	BIO			*encbio = NULL;
	BIO			*pkcs7bio = NULL;
	BIO			*memorybio = NULL;
	BIO			*outbio = NULL;
	BIO			*base64bio = NULL;
	unsigned char		*buffer = NULL;
	int			rc, len = 0;
	STACK_OF(X509)		*recipients;
	PKCS7			*p7enc;
	PKCS7_SIGNER_INFO	*si;
	STACK_OF(X509_ATTRIBUTE) *attributes;
	X509			*signercert = NULL;
	EVP_PKEY		*signerkey = NULL;

	/* Create a new sender nonce for all messages 
	 * XXXXXXXXXXXXXX should it be per transaction? */
	s->sender_nonce_len = 16;
	s->sender_nonce = (unsigned char *)malloc(s->sender_nonce_len); 
	RAND_bytes(s->sender_nonce, s->sender_nonce_len);

	/* Prepare data payload */
	switch(s->request_type) {
		case SCEP_REQUEST_PKCSREQ:
			/*
			 * Set printable message type
			 * We set this later as an autheticated attribute
			 * "messageType".
			 */
			s->request_type_str = SCEP_REQUEST_PKCSREQ_STR;

			/* Signer cert */
			signercert = s->signercert;
			signerkey = s->signerkey;

			/* Create inner PKCS#7  */
			if (v_flag)
				printf("%s: creating inner PKCS#7\n", pname);

			/* Read request in memory bio */
			databio = BIO_new(BIO_s_mem());
			if ((rc = i2d_X509_REQ_bio(databio, request)) <= 0) {
				fprintf(stderr, "%s: error writing "
					"certificate request in bio\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_P7);
			}
			BIO_flush(databio);
			BIO_set_flags(databio, BIO_FLAGS_MEM_RDONLY); 
			break;

		case SCEP_REQUEST_GETCERTINIT:

			/* Set printable message type */
			s->request_type_str = SCEP_REQUEST_GETCERTINIT_STR;

			/* Signer cert */
			signercert = s->signercert;
			signerkey = s->signerkey;

			/* Create inner PKCS#7  */
			if (v_flag)
				printf("%s: creating inner PKCS#7\n", pname);

			/* Read data in memory bio */
			databio = BIO_new(BIO_s_mem());
			if ((rc = i2d_pkcs7_issuer_and_subject_bio(databio,
						s->ias_getcertinit)) <= 0) {
				fprintf(stderr, "%s: error writing "
					"GetCertInitial data in bio\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_P7);
			}
			BIO_flush(databio);
			BIO_set_flags(databio, BIO_FLAGS_MEM_RDONLY); 
			break;

		case SCEP_REQUEST_GETCERT:
			/* Set printable message type */
			s->request_type_str = SCEP_REQUEST_GETCERT_STR;

			/* Signer cert */
			signercert = localcert;
			signerkey = rsa;

			/* Read data in memory bio */
			databio = BIO_new(BIO_s_mem());
			if ((rc = i2d_PKCS7_ISSUER_AND_SERIAL_bio(databio,
						s->ias_getcert)) <= 0) {
				fprintf(stderr, "%s: error writing "
					"GetCert data in bio\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_P7);
			}
			BIO_flush(databio);
			BIO_set_flags(databio, BIO_FLAGS_MEM_RDONLY); 
			break;

		case SCEP_REQUEST_GETCRL:
			/* Set printable message type */
			s->request_type_str = SCEP_REQUEST_GETCRL_STR;

			/* Signer cert */
			signercert = localcert;
			signerkey = rsa;

			/* Read data in memory bio */
			databio = BIO_new(BIO_s_mem());
			if ((rc = i2d_PKCS7_ISSUER_AND_SERIAL_bio(databio,
						s->ias_getcrl)) <= 0) {
				fprintf(stderr, "%s: error writing "
					"GetCert data in bio\n", pname);
				ERR_print_errors_fp(stderr);
				exit (SCEP_PKISTATUS_P7);
			}
			BIO_flush(databio);
			BIO_set_flags(databio, BIO_FLAGS_MEM_RDONLY); 
			break;
	}
	/* Below this is the common code for all request_type */

	/* Read in the payload */
	s->request_len = BIO_get_mem_data(databio, &s->request_payload);
	if (v_flag)
		printf("%s: data payload size: %d bytes\n", pname,
				s->request_len);
	BIO_free(databio);

	/* Create encryption certificate stack */
	if ((recipients = sk_X509_new(NULL)) == NULL) {
		fprintf(stderr, "%s: error creating "
					"certificate stack\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	/* Use different CA cert for encryption if requested */
	if (e_flag) {
		if (sk_X509_push(recipients, encert) <= 0) {
			fprintf(stderr, "%s: error adding recipient encryption "
					"certificate\n", pname);
			ERR_print_errors_fp(stderr);
			exit (SCEP_PKISTATUS_P7);
		}
	/* Use same CA cert also for encryption */
	} else {
		if (sk_X509_push(recipients, cacert) <= 0) {
			fprintf(stderr, "%s: error adding recipient encryption "
					"certificate\n", pname);
			ERR_print_errors_fp(stderr);
			exit (SCEP_PKISTATUS_P7);
		}
	}

	/* Create BIO for encryption  */
	if ((encbio = BIO_new_mem_buf(s->request_payload,
				s->request_len)) == NULL) {
		fprintf(stderr, "%s: error creating data " "bio\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	} 

	/* Encrypt */
	if (!(p7enc = PKCS7_encrypt(recipients, encbio,
					enc_alg, PKCS7_BINARY))) {
		fprintf(stderr, "%s: request payload encrypt failed\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: successfully encrypted payload\n", pname);

	/* Write encrypted data */
	memorybio = BIO_new(BIO_s_mem());
	if (i2d_PKCS7_bio(memorybio, p7enc) <= 0) {
		fprintf(stderr, "%s: error writing encrypted data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	BIO_flush(memorybio);
	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); 
	len = BIO_get_mem_data(memorybio, &buffer);
	if (v_flag)
		printf("%s: envelope size: %d bytes\n", pname, len);
	if (d_flag) {
		printf("%s: printing PEM fomatted PKCS#7\n", pname);
		PEM_write_PKCS7(stdout, p7enc);
	}
	BIO_free(memorybio); 

	/* Create outer PKCS#7  */
	if (v_flag)
		printf("%s: creating outer PKCS#7\n", pname);
	s->request_p7 = PKCS7_new();
	if (s->request_p7 == NULL) {
		fprintf(stderr, "%s: failed creating PKCS#7 for signing\n",
					pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (!PKCS7_set_type(s->request_p7, NID_pkcs7_signed)) {
		fprintf(stderr, "%s: failed setting PKCS#7 type\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Add signer certificate  and signature */
	PKCS7_add_certificate(s->request_p7, signercert);
	if ((si = PKCS7_add_signature(s->request_p7,
				signercert, signerkey, sig_alg)) == NULL) {
		fprintf(stderr, "%s: error adding PKCS#7 signature\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: signature added successfully\n", pname);

	/* Set signed attributes */
	if (v_flag)
		printf("%s: adding signed attributes\n", pname);
	attributes = sk_X509_ATTRIBUTE_new_null();	
	add_attribute_string(attributes, nid_transId, s->transaction_id);
	add_attribute_string(attributes, nid_messageType, s->request_type_str);
	add_attribute_octet(attributes, nid_senderNonce, s->sender_nonce,
			s->sender_nonce_len);
	PKCS7_set_signed_attributes(si, attributes);
	
	/* Add contentType */
	if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
			V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))) {
		fprintf(stderr, "%s: error adding NID_pkcs9_contentType\n",
					pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Create new content */
	if (!PKCS7_content_new(s->request_p7, NID_pkcs7_data)) {
		fprintf(stderr, "%s: failed setting PKCS#7 content type\n",
					pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Write data  */
	pkcs7bio = PKCS7_dataInit(s->request_p7, NULL);
	if (pkcs7bio == NULL) {
		fprintf(stderr, "%s: error opening bio for writing PKCS#7 "
			"data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (len != BIO_write(pkcs7bio, buffer, len)) {
		fprintf(stderr, "%s: error writing PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: PKCS#7 data written successfully\n", pname);

	/* Finalize PKCS#7  */
	if (!PKCS7_dataFinal(s->request_p7, pkcs7bio)) {
		fprintf(stderr, "%s: error finalizing outer PKCS#7\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (d_flag) {
		printf("%s: printing PEM fomatted PKCS#7\n", pname);
		PEM_write_PKCS7(stdout, s->request_p7);
	}

	/* base64-encode the data */
	if (v_flag)
		printf("%s: applying base64 encoding\n",pname);

	/* Create base64 filtering bio */
	memorybio = BIO_new(BIO_s_mem());
	base64bio = BIO_new(BIO_f_base64());
	outbio = BIO_push(base64bio, memorybio);

	/* Copy PKCS#7 */
	i2d_PKCS7_bio(outbio, s->request_p7);
	BIO_flush(outbio);
	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY);
	s->request_len = BIO_get_mem_data(memorybio, &s->request_payload);
	if (v_flag)
		printf("%s: base64 encoded payload size: %d bytes\n",
				pname, s->request_len);
	BIO_free(outbio);

	return (0);
}
Exemple #18
0
char* sign_and_encrypt(const char *data, RSA *rsa, X509 *x509, X509 *PPx509, int verbose)
/* sign and encrypt button data for safe delivery to paypal */
{
	char *ret = NULL;
	EVP_PKEY *pkey;
	PKCS7 *p7 = NULL;
	BIO *p7bio = NULL;
	BIO *bio = NULL;
	PKCS7_SIGNER_INFO* si;
	int len;
	char *str;

	pkey = EVP_PKEY_new();

	if (EVP_PKEY_set1_RSA(pkey, rsa) == 0)
	{
		fprintf(stderr,"Fatal Error: Unable to create EVP_KEY from RSA key\n");fflush(stderr);
		goto end;
	} else if (verbose) {
		printf("Successfully created EVP_KEY from RSA key\n");
	}

	/* Create a signed and enveloped PKCS7 */
	p7 = PKCS7_new();
	PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped);

	si = PKCS7_add_signature(p7, x509, pkey, EVP_sha1());

	if (si) {
		if (PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT,
			OBJ_nid2obj(NID_pkcs7_data)) <= 0)
		{
			fprintf(stderr,"Fatal Error: Unable to add signed attribute to certificate\n");
			fprintf(stderr,"OpenSSL Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
			fflush(stderr);
			goto end;
		} else if (verbose) {
			printf("Successfully added signed attribute to certificate\n");
		}

	} else {
		fprintf(stderr,"Fatal Error: Failed to sign PKCS7\n");fflush(stderr);
		goto end;
	}

	/* Encryption */
	if (PKCS7_set_cipher(p7, EVP_des_ede3_cbc()) <= 0)
	{
		fprintf(stderr,"Fatal Error: Failed to set encryption algorithm\n");
		fprintf(stderr,"OpenSSL Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
		fflush(stderr);
		goto end;
	} else if (verbose) {
		printf("Successfully added encryption algorithm\n");
	}

	if (PKCS7_add_recipient(p7, PPx509) <= 0)
	{
		fprintf(stderr,"Fatal Error: Failed to add PKCS7 recipient\n");
		fprintf(stderr,"OpenSSL Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
		fflush(stderr);
		goto end;
	} else if (verbose) {
		printf("Successfully added recipient\n");
	}

	if (PKCS7_add_certificate(p7, x509) <= 0)
	{
		fprintf(stderr,"Fatal Error: Failed to add PKCS7 certificate\n");
		fprintf(stderr,"OpenSSL Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
		fflush(stderr);
		goto end;
	} else if (verbose) {
		printf("Successfully added certificate\n");
	}

	p7bio = PKCS7_dataInit(p7, NULL);
	if (!p7bio) {
		fprintf(stderr,"OpenSSL Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
		fflush(stderr);
		goto end;
	}

	/* Pump data to special PKCS7 BIO. This encrypts and signs it. */
	BIO_write(p7bio, data, strlen(data));
	BIO_flush(p7bio);
	PKCS7_dataFinal(p7, p7bio);

	/* Write PEM encoded PKCS7 */
	bio = BIO_new(BIO_s_mem());

	if (!bio || (PEM_write_bio_PKCS7(bio, p7) == 0))
	{
		fprintf(stderr,"Fatal Error: Failed to create PKCS7 PEM\n");fflush(stderr);
	} else if (verbose) {
		printf("Successfully created PKCS7 PEM\n");
	}

	BIO_flush(bio);
	len = BIO_get_mem_data(bio, &str);
	ret = malloc(sizeof(char)*(len+1));
	memcpy(ret, str, len);
	ret[len] = 0;

end:
	/* Free everything */
	if (bio)
		BIO_free_all(bio);
	if (p7bio)
		BIO_free_all(p7bio);
	if (p7)
		PKCS7_free(p7);
	if (pkey)
		EVP_PKEY_free(pkey);
	return ret;
}
Exemple #19
0
int main(int argc, char* argv[]) 
{ 
PKCS7 *p7, *innerp7; 
FILE *fp = NULL; 
EVP_PKEY *pkey = NULL; 
PKCS7_SIGNER_INFO *p7i; 
PKCS7_RECIP_INFO *pri; 
BIO *mybio, *inbio; 
X509 *user; 
X509_ALGOR *md; 
int ret, len; 
unsigned char data[2048], *p, *buf; 
unsigned char* greet = "hello openssl"; 

unsigned long errorno; 
unsigned char* errordesc; 

OpenSSL_add_all_algorithms(); //必须要显式进行调用 

inbio = BIO_new(BIO_s_mem()); 
ret = BIO_write(inbio, greet, strlen(greet)); 

p7 = PKCS7_new(); 
ret = PKCS7_set_type(p7, NID_pkcs7_signedAndEnveloped); 


//加载用户证书 
fp = fopen("mycert4p12.cer", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
user = d2i_X509(NULL, (const unsigned char**)&p, len); 
ret = PKCS7_add_certificate(p7, user); 
pri = PKCS7_add_recipient(p7, user); 

//读取私钥 
fp = fopen("myprivkey.pem", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&p, len); 

//第一个用户增加SignerInfo到列表中 
p7i = PKCS7_add_signature(p7, user, pkey, EVP_md5()); 

//加载用户证书 
fp = fopen("user2.cer", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
user = d2i_X509(NULL, (const unsigned char**)&p, len); 
ret = PKCS7_add_certificate(p7, user); 
pri = PKCS7_add_recipient(p7, user); 

//读取私钥 
fp = fopen("user2_privatekey.pem", "rb"); 
if(fp == NULL) return 0; 
len = fread(data, 1, 1024, fp); 
fclose(fp); 
p = data; 
pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, (const unsigned char**)&p, len); 

//第二个签名者增加到SignerInfo列表中 
p7i = PKCS7_add_signature(p7, user, pkey, EVP_md5()); 

ret = PKCS7_set_cipher(p7, EVP_des_ede3_cbc()); 

ret = PKCS7_final(p7, inbio, 0); //制作数字信封 

len = i2d_PKCS7(p7, NULL); 
p = buf = malloc(len); 
len = i2d_PKCS7(p7, &p); 
printf("in i2d len = %d\n", len); 

fp = fopen("p7signandenv.cer", "wb"); 
fwrite(buf, len, 1, fp); 
fclose(fp); 

PKCS7_free(p7); 
} 
Exemple #20
0
/* will return 0, 1, 3, or 99 */
static int
_pkgtrans(char *device1, char *device2, char **pkg, int options,
    keystore_handle_t keystore, char *keystore_alias)
{
#ifdef	USE_KEYSTORE
	BIO			*p7_bio = NULL;
	EVP_PKEY		*privkey = NULL;
#endif
	PKCS7			*sec_pkcs7 = NULL;
#ifdef	USE_KEYSTORE
	PKCS7_SIGNER_INFO	*sec_signerinfo = NULL;
	PKG_ERR			*err;
	STACK_OF(X509)		*cacerts = NULL;
	STACK_OF(X509)		*clcerts = NULL;
	STACK_OF(X509)		*sec_chain = NULL;
	X509			*pubcert = NULL;
#endif
	boolean_t		making_sig = B_FALSE;
	char			*src, *dst;
	int			errflg, i, n;
	struct			dm_buf *hdr;

	making_sig = (keystore != NULL) ? B_TRUE : B_FALSE;

#ifdef	USE_KEYSTORE
	if (making_sig) {

		/* new error object */
		err = pkgerr_new();

		/* find matching cert and key */
		if (find_key_cert_pair(err, keystore,
		    keystore_alias, &privkey, &pubcert) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/* get CA certificates */
		if (find_ca_certs(err, keystore, &cacerts) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/* get CL (aka "chain") certificates */
		if (find_cl_certs(err, keystore, &clcerts) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/* initialize PKCS7 object to be filled in later */
		sec_pkcs7 = PKCS7_new();
		PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed);
		sec_signerinfo = PKCS7_add_signature(sec_pkcs7,
		    pubcert, privkey, EVP_sha1());

		if (sec_signerinfo == NULL) {
			progerr(gettext(ERR_SEC), keystore_alias);
			ERR_print_errors_fp(stderr);
			pkgerr_free(err);
			return (1);
		}

		/* add signer cert into signature */
		PKCS7_add_certificate(sec_pkcs7, pubcert);

		/* attempt to resolve cert chain starting at the signer cert */
		if (get_cert_chain(err, pubcert, clcerts, cacerts,
		    &sec_chain) != 0) {
			pkgerr(err);
			pkgerr_free(err);
			return (1);
		}

		/*
		 * add the verification chain of certs into the signature.
		 * The first cert is the user cert, which we don't need,
		 * since it's baked in already, so skip it
		 */
		for (i = 1; i < sk_X509_num(sec_chain); i++) {
			PKCS7_add_certificate(sec_pkcs7,
			    sk_X509_value(sec_chain, i));
		}

		pkgerr_free(err);
		err = NULL;
	}
#endif	/* USE_KEYSTORE */

	if (signal_received > 0) {
		return (1);
	}

	/* transfer spool to appropriate device */
	if (devtype(device1, &srcdev)) {
		progerr(pkg_gt(ERR_TRANSFER));
		logerr(pkg_gt(MSG_BADDEV), device1);
		return (1);
	}
	srcdev.rdonly++;

	/* check for datastream */
	ids_name = NULL;
	if (srcdev.bdevice) {
		if (ds_readbuf(srcdev.cdevice))
			ids_name = srcdev.cdevice;
	}

	if (srcdev.cdevice && !srcdev.bdevice)
		ids_name = srcdev.cdevice;
	else if (srcdev.pathname) {
		ids_name = srcdev.pathname;
		if (access(ids_name, 0) == -1) {
			progerr(ERR_TRANSFER);
			logerr(pkg_gt(MSG_GETVOL));
			return (1);
		}
	}

	if (!ids_name && device2 == (char *)0) {
		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
			cleanup();
			return (n);
		}
		if (srcdev.mount && *srcdev.mount)
			pkgdir = strdup(srcdev.mount);
		return (0);
	}

	if (ids_name && device2 == (char *)0) {
		char	template[] = "/var/tmp/ptXXXXXX";
Exemple #21
0
int smime_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL, *indata = NULL;
    EVP_PKEY *key = NULL;
    PKCS7 *p7 = NULL;
    STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
    STACK_OF(X509) *encerts = NULL, *other = NULL;
    X509 *cert = NULL, *recip = NULL, *signer = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    const EVP_CIPHER *cipher = NULL;
    const EVP_MD *sign_md = NULL;
    const char *CAfile = NULL, *CApath = NULL, *prog = NULL;
    char *certfile = NULL, *keyfile = NULL, *contfile = NULL, *inrand = NULL;
    char *infile = NULL, *outfile = NULL, *signerfile = NULL, *recipfile =
        NULL;
    char *passinarg = NULL, *passin = NULL, *to = NULL, *from =
        NULL, *subject = NULL;
    OPTION_CHOICE o;
    int noCApath = 0, noCAfile = 0;
    int flags = PKCS7_DETACHED, operation = 0, ret = 0, need_rand = 0, indef =
        0;
    int informat = FORMAT_SMIME, outformat = FORMAT_SMIME, keyform =
        FORMAT_PEM;
    int vpmtouched = 0, rv = 0;
    ENGINE *e = NULL;
    const char *mime_eol = "\n";

    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, smime_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(smime_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENCRYPT:
            operation = SMIME_ENCRYPT;
            break;
        case OPT_DECRYPT:
            operation = SMIME_DECRYPT;
            break;
        case OPT_SIGN:
            operation = SMIME_SIGN;
            break;
        case OPT_RESIGN:
            operation = SMIME_RESIGN;
            break;
        case OPT_VERIFY:
            operation = SMIME_VERIFY;
            break;
        case OPT_PK7OUT:
            operation = SMIME_PK7OUT;
            break;
        case OPT_TEXT:
            flags |= PKCS7_TEXT;
            break;
        case OPT_NOINTERN:
            flags |= PKCS7_NOINTERN;
            break;
        case OPT_NOVERIFY:
            flags |= PKCS7_NOVERIFY;
            break;
        case OPT_NOCHAIN:
            flags |= PKCS7_NOCHAIN;
            break;
        case OPT_NOCERTS:
            flags |= PKCS7_NOCERTS;
            break;
        case OPT_NOATTR:
            flags |= PKCS7_NOATTR;
            break;
        case OPT_NODETACH:
            flags &= ~PKCS7_DETACHED;
            break;
        case OPT_NOSMIMECAP:
            flags |= PKCS7_NOSMIMECAP;
            break;
        case OPT_BINARY:
            flags |= PKCS7_BINARY;
            break;
        case OPT_NOSIGS:
            flags |= PKCS7_NOSIGS;
            break;
        case OPT_STREAM:
        case OPT_INDEF:
            indef = 1;
            break;
        case OPT_NOINDEF:
            indef = 0;
            break;
        case OPT_CRLFEOL:
            flags |= PKCS7_CRLFEOL;
            mime_eol = "\r\n";
            break;
        case OPT_RAND:
            inrand = opt_arg();
            need_rand = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_TO:
            to = opt_arg();
            break;
        case OPT_FROM:
            from = opt_arg();
            break;
        case OPT_SUBJECT:
            subject = opt_arg();
            break;
        case OPT_SIGNER:
            /* If previous -signer argument add signer to list */
            if (signerfile) {
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                if (keyfile == NULL)
                    keyfile = signerfile;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
                keyfile = NULL;
            }
            signerfile = opt_arg();
            break;
        case OPT_RECIP:
            recipfile = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_arg(), &sign_md))
                goto opthelp;
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &cipher))
                goto opthelp;
            break;
        case OPT_INKEY:
            /* If previous -inkey argument add signer to list */
            if (keyfile) {
                if (signerfile == NULL) {
                    BIO_printf(bio_err,
                               "%s: Must have -signer before -inkey\n", prog);
                    goto opthelp;
                }
                if (sksigners == NULL
                    && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(sksigners, signerfile);
                signerfile = NULL;
                if (skkeys == NULL
                    && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                    goto end;
                sk_OPENSSL_STRING_push(skkeys, keyfile);
            }
            keyfile = opt_arg();
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
                goto opthelp;
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_CONTENT:
            contfile = opt_arg();
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto opthelp;
            vpmtouched++;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
        BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
        goto opthelp;
    }

    if (operation & SMIME_SIGNERS) {
        /* Check to see if any final signer needs to be appended */
        if (keyfile && !signerfile) {
            BIO_puts(bio_err, "Illegal -inkey without -signer\n");
            goto opthelp;
        }
        if (signerfile) {
            if (!sksigners
                && (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(sksigners, signerfile);
            if (!skkeys && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            if (!keyfile)
                keyfile = signerfile;
            sk_OPENSSL_STRING_push(skkeys, keyfile);
        }
        if (!sksigners) {
            BIO_printf(bio_err, "No signer certificate specified\n");
            goto opthelp;
        }
        signerfile = NULL;
        keyfile = NULL;
        need_rand = 1;
    } else if (operation == SMIME_DECRYPT) {
        if (!recipfile && !keyfile) {
            BIO_printf(bio_err,
                       "No recipient certificate or key specified\n");
            goto opthelp;
        }
    } else if (operation == SMIME_ENCRYPT) {
        if (argc == 0) {
            BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
            goto opthelp;
        }
        need_rand = 1;
    } else if (!operation)
        goto opthelp;

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (need_rand) {
        app_RAND_load_file(NULL, (inrand != NULL));
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
    }

    ret = 2;

    if (!(operation & SMIME_SIGNERS))
        flags &= ~PKCS7_DETACHED;

    if (!(operation & SMIME_OP)) {
        if (flags & PKCS7_BINARY)
            outformat = FORMAT_BINARY;
    }

    if (!(operation & SMIME_IP)) {
        if (flags & PKCS7_BINARY)
            informat = FORMAT_BINARY;
    }

    if (operation == SMIME_ENCRYPT) {
        if (!cipher) {
#ifndef OPENSSL_NO_DES
            cipher = EVP_des_ede3_cbc();
#else
            BIO_printf(bio_err, "No cipher selected\n");
            goto end;
#endif
        }
        encerts = sk_X509_new_null();
        if (!encerts)
            goto end;
        while (*argv) {
            cert = load_cert(*argv, FORMAT_PEM,
                             "recipient certificate file");
            if (cert == NULL)
                goto end;
            sk_X509_push(encerts, cert);
            cert = NULL;
            argv++;
        }
    }

    if (certfile) {
        if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
                        "certificate file")) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (recipfile && (operation == SMIME_DECRYPT)) {
        if ((recip = load_cert(recipfile, FORMAT_PEM,
                               "recipient certificate file")) == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (operation == SMIME_DECRYPT) {
        if (!keyfile)
            keyfile = recipfile;
    } else if (operation == SMIME_SIGN) {
        if (!keyfile)
            keyfile = signerfile;
    } else
        keyfile = NULL;

    if (keyfile) {
        key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
        if (!key)
            goto end;
    }

    in = bio_open_default(infile, 'r', informat);
    if (in == NULL)
        goto end;

    if (operation & SMIME_IP) {
        if (informat == FORMAT_SMIME)
            p7 = SMIME_read_PKCS7(in, &indata);
        else if (informat == FORMAT_PEM)
            p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
        else if (informat == FORMAT_ASN1)
            p7 = d2i_PKCS7_bio(in, NULL);
        else {
            BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
            goto end;
        }

        if (!p7) {
            BIO_printf(bio_err, "Error reading S/MIME message\n");
            goto end;
        }
        if (contfile) {
            BIO_free(indata);
            if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
                BIO_printf(bio_err, "Can't read content file %s\n", contfile);
                goto end;
            }
        }
    }

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (operation == SMIME_VERIFY) {
        if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
            goto end;
        X509_STORE_set_verify_cb(store, smime_cb);
        if (vpmtouched)
            X509_STORE_set1_param(store, vpm);
    }

    ret = 3;

    if (operation == SMIME_ENCRYPT) {
        if (indef)
            flags |= PKCS7_STREAM;
        p7 = PKCS7_encrypt(encerts, in, cipher, flags);
    } else if (operation & SMIME_SIGNERS) {
        int i;
        /*
         * If detached data content we only enable streaming if S/MIME output
         * format.
         */
        if (operation == SMIME_SIGN) {
            if (flags & PKCS7_DETACHED) {
                if (outformat == FORMAT_SMIME)
                    flags |= PKCS7_STREAM;
            } else if (indef)
                flags |= PKCS7_STREAM;
            flags |= PKCS7_PARTIAL;
            p7 = PKCS7_sign(NULL, NULL, other, in, flags);
            if (!p7)
                goto end;
            if (flags & PKCS7_NOCERTS) {
                for (i = 0; i < sk_X509_num(other); i++) {
                    X509 *x = sk_X509_value(other, i);
                    PKCS7_add_certificate(p7, x);
                }
            }
        } else
            flags |= PKCS7_REUSE_DIGEST;
        for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
            signerfile = sk_OPENSSL_STRING_value(sksigners, i);
            keyfile = sk_OPENSSL_STRING_value(skkeys, i);
            signer = load_cert(signerfile, FORMAT_PEM,
                               "signer certificate");
            if (!signer)
                goto end;
            key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
            if (!key)
                goto end;
            if (!PKCS7_sign_add_signer(p7, signer, key, sign_md, flags))
                goto end;
            X509_free(signer);
            signer = NULL;
            EVP_PKEY_free(key);
            key = NULL;
        }
        /* If not streaming or resigning finalize structure */
        if ((operation == SMIME_SIGN) && !(flags & PKCS7_STREAM)) {
            if (!PKCS7_final(p7, in, flags))
                goto end;
        }
    }

    if (!p7) {
        BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
        goto end;
    }

    ret = 4;
    if (operation == SMIME_DECRYPT) {
        if (!PKCS7_decrypt(p7, key, recip, out, flags)) {
            BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
            goto end;
        }
    } else if (operation == SMIME_VERIFY) {
        STACK_OF(X509) *signers;
        if (PKCS7_verify(p7, other, store, indata, out, flags))
            BIO_printf(bio_err, "Verification successful\n");
        else {
            BIO_printf(bio_err, "Verification failure\n");
            goto end;
        }
        signers = PKCS7_get0_signers(p7, other, flags);
        if (!save_certs(signerfile, signers)) {
            BIO_printf(bio_err, "Error writing signers to %s\n", signerfile);
            ret = 5;
            goto end;
        }
        sk_X509_free(signers);
    } else if (operation == SMIME_PK7OUT)
        PEM_write_bio_PKCS7(out, p7);
    else {
        if (to)
            BIO_printf(out, "To: %s%s", to, mime_eol);
        if (from)
            BIO_printf(out, "From: %s%s", from, mime_eol);
        if (subject)
            BIO_printf(out, "Subject: %s%s", subject, mime_eol);
        if (outformat == FORMAT_SMIME) {
            if (operation == SMIME_RESIGN)
                rv = SMIME_write_PKCS7(out, p7, indata, flags);
            else
                rv = SMIME_write_PKCS7(out, p7, in, flags);
        } else if (outformat == FORMAT_PEM)
            rv = PEM_write_bio_PKCS7_stream(out, p7, in, flags);
        else if (outformat == FORMAT_ASN1)
            rv = i2d_PKCS7_bio_stream(out, p7, in, flags);
        else {
            BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
            goto end;
        }
        if (rv == 0) {
            BIO_printf(bio_err, "Error writing output\n");
            ret = 3;
            goto end;
        }
    }
    ret = 0;
 end:
    if (need_rand)
        app_RAND_write_file(NULL);
    if (ret)
        ERR_print_errors(bio_err);
    sk_X509_pop_free(encerts, X509_free);
    sk_X509_pop_free(other, X509_free);
    X509_VERIFY_PARAM_free(vpm);
    sk_OPENSSL_STRING_free(sksigners);
    sk_OPENSSL_STRING_free(skkeys);
    X509_STORE_free(store);
    X509_free(cert);
    X509_free(recip);
    X509_free(signer);
    EVP_PKEY_free(key);
    PKCS7_free(p7);
    release_engine(e);
    BIO_free(in);
    BIO_free(indata);
    BIO_free_all(out);
    OPENSSL_free(passin);
    return (ret);
}
Exemple #22
0
/* Allocate the SCEP_MSG structures */
SCEP_MSG *SCEP_MSG_new( int messageType, X509 *cert, EVP_PKEY *pkey,
		X509 *recip_cert, SCEP_MSG *inMsg, X509_REQ *req,
		X509 *issued_cert, SCEP_ISSUER_AND_SUBJECT *cert_info,
		PKCS7_ISSUER_AND_SERIAL *ias, X509_CRL *crl, X509 *cacert,
		EVP_CIPHER cipher ) {

	SCEP_MSG *msg = NULL;
	PKCS7_SIGNER_INFO *si = NULL;
	EVP_MD *dgst=NULL;

	unsigned char *raw_data = NULL;
	int envelope = 0;
	long raw_len = 0;

	BIO *debug_bio = NULL;
	BIO *p7ebio = NULL;
	BIO *inbio = NULL;

	char buf[256];

        if ((debug_bio=BIO_new(BIO_s_file())) != NULL)
		BIO_set_fp(debug_bio,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

	//if( !cert || !pkey || !recip_cert )
	if( !cert || !pkey )
		return NULL;

	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] Generating New SCEP-Message...\n", __FILE__, __LINE__);

	/* Allocate memory and initialize structures */
	if((msg = SCEP_MSG_new_null()) == NULL) return NULL;
	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] Allocate memory\n", __FILE__, __LINE__);
	
	/* Signed Infos */
	dgst = (EVP_MD *) EVP_get_digestbyname("md5");
	if( (si = PKCS7_SIGNER_INFO_new()) == NULL ) goto err;
	if(!PKCS7_SIGNER_INFO_set(si, cert, pkey, dgst)) goto err;
	sk_PKCS7_SIGNER_INFO_push( msg->sk_signer_info, si );
	msg->signer_ias = si->issuer_and_serial;

	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] signer infos set\n", __FILE__, __LINE__);

	/* If pkey, let's add to the message structure to ease
	 * message encryption (enveloped data content creation) */
	SCEP_MSG_set_pkey ( msg, pkey );
	// msg->signer_pkey = pkey;

	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] encryption key set\n", __FILE__, __LINE__);

	/* If not explicit, we guess the certificate to be present
	 * in the passed inMsg structure, if any. Otherwise ERROR! */
	if( !recip_cert && inMsg ) recip_cert = inMsg->signer_cert;

	/* Set the messageType */
	SCEP_set_messageType ( msg, messageType );

	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] message type set\n", __FILE__, __LINE__);
	switch( messageType ) {
		case MSG_CERTREP:
			if (debug)
		        	BIO_printf( debug_bio, "%s:%d: [Debug Info] Actions for CERTREP\n", __FILE__, __LINE__);
			msg->env_data.NID_p7data = NID_pkcs7_signed;
                        msg->env_data.p7 = PKCS7_new();
                        PKCS7_set_type( msg->env_data.p7, NID_pkcs7_signed );
                        PKCS7_content_new( msg->env_data.p7, NID_pkcs7_data );
			if( issued_cert ) {
				if (debug)
					BIO_printf( debug_bio, 
						"%s:%d: creating inner degenerated PKCS7... \n", 
						__FILE__, __LINE__);
				/* Adds issued certificate */
				PKCS7_add_certificate( msg->env_data.p7, issued_cert );
//				PKCS7_add_certificate( msg->env_data.p7, cert );
				envelope = 1;
				if (debug)
					BIO_printf( debug_bio, "%s:%d: done \n", __FILE__, __LINE__);
			} else if( crl ) {
				if (debug)
					BIO_printf( debug_bio, 
						"%s:%d: Adding CRL ... \n", 
						__FILE__, __LINE__);
				/* Adds crl */
				PKCS7_add_crl( msg->env_data.p7, crl );
				envelope = 1;
				if (debug)
				        BIO_printf( debug_bio, "%s:%d: done \n", __FILE__, __LINE__);
				
			} 
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
			break;
		case MSG_PKCSREQ:
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] Actions for PKCSREQ\n", __FILE__, __LINE__);
			/* The inner pkcs7 structure is signed
			 * and enveloped and the data is to be
			 * the X509_REQ passed */
			msg->env_data.NID_p7data = 
			 	NID_pkcs7_signedAndEnveloped;

			if( req ) { 
				msg->env_data.content.req = req;

				/* Ask for the data p7 to be generated and
				 * encrypted */
				envelope = 1;
			}
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
			break;
		case MSG_GETCRL:
			if (debug)
			{
				BIO_printf( debug_bio, "%s:%d: [Debug Info] Actions for GETCRL\n", __FILE__, __LINE__);
				BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
			}
			break;
		case MSG_GETCERT:
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] Actions for GETCERT\n", __FILE__, __LINE__);
			msg->env_data.NID_p7data = 
				NID_pkcs7_signedAndEnveloped;
			/* If it is a query for a general certificate
			 * the CAcert should be included in the enveloped
			 * data*/
			/* Otherwise, if it is a request for its own
			 * certificate, the self-signed certificate should
			 * be included */
			// if( cacert )
			// 	msg->env_data.cacert = cacert;

			/* Issuer and Serial should be present ! */
			if( !ias ) goto err;
			msg->env_data.content.ias = ias;
			envelope = 1;
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
			break;
		case MSG_GETCERTINITIAL:
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] Actions for GETCERTINITIAL\n", __FILE__, __LINE__);
			msg->env_data.NID_p7data = NID_pkcs7_signed;
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
			break;
		case MSG_V2REQUEST: /* Not currently handled */
			if (debug) {
				BIO_printf( debug_bio, "%s:%d: [Debug Info] Actions for V2REQUEST\n", __FILE__, __LINE__);
				BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
			}
		default:
			goto err;
	}
	
	if (debug)
		BIO_printf( debug_bio, "%s:%d: Debug ... \n", __FILE__, __LINE__);

	/* If different from NULL, we have to encode something */
	if( envelope == 1 ) {
		if (debug)
			BIO_printf( debug_bio, "%s:%d: [Debug Info] encode\n", __FILE__, __LINE__);
		/* Encrypt the message data */
		if( !SCEP_MSG_encrypt( msg, recip_cert, cipher )) goto err;
		if (debug)
			BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
	}

	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] add sign-cert to structure\n", __FILE__, __LINE__);
	/* Signer certificate */
	msg->signer_cert = cert;
	if (debug)
		PEM_write_bio_SCEP_MSG( debug_bio, msg, pkey );

	if (debug)
		BIO_printf( debug_bio, "%s:%d: [Debug Info] add attributes\n", __FILE__, __LINE__);
	/* Set message attributes, if any */
	if ( inMsg ) {
		char *tmp = NULL;
		int len = 0;
		if (debug)
			BIO_printf( debug_bio, "%s:%d: [Debug Info] take data from request\n", __FILE__, __LINE__);

		switch ( msg->messageType ) {
		   default:
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info]   set transId\n", __FILE__, __LINE__);
			/* The transId is ever required */
			tmp = SCEP_get_string_attr_by_name( inMsg->attrs, "transId");
			if( tmp ) {
				SCEP_set_transId( msg, tmp, strlen(tmp));
				OPENSSL_free( tmp );
				if (debug)
					BIO_printf( debug_bio, "%s:%d: [Debug Info]    done\n", __FILE__, __LINE__);
			}

			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info]   set recipient nonce (sendernonce from req)\n", __FILE__, __LINE__);
			/* Copy the sendernonce to the recipient nonce and
			 * generate a new sendernonce for the generated msg */
			tmp = SCEP_get_octect_attr_by_name( inMsg->attrs, 
					"senderNonce", &len);
			if( tmp ) {
				if (debug)
					BIO_printf( debug_bio, "%s:%d: [Debug Info]    %d\n", __FILE__, __LINE__, tmp);
				SCEP_set_recipientNonce( msg, tmp, len );
				OPENSSL_free( tmp );
			}
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info]   set sender nonce\n", __FILE__, __LINE__);
			SCEP_set_senderNonce_new(msg);
			if (debug)
				BIO_printf( debug_bio, "%s:%d: [Debug Info]    done\n", __FILE__, __LINE__);
		}
		if (debug)
			BIO_printf( debug_bio, "%s:%d: [Debug Info]   set pki_status\n", __FILE__, __LINE__);
		SCEP_set_pkiStatus ( msg, PKI_PENDING );
		if (debug) {
			BIO_printf( debug_bio, "%s:%d: [Debug Info]    done\n", __FILE__, __LINE__);
			BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
		}
	} else {
		if (debug)
			BIO_printf( debug_bio, "%s:%d: [Debug Info] generate new data\n", __FILE__, __LINE__);
		SCEP_set_senderNonce_new ( msg );
		SCEP_set_recipientNonce_new ( msg );
		SCEP_set_transId_new ( msg );
		if (debug)
			BIO_printf( debug_bio, "%s:%d: [Debug Info] done\n", __FILE__, __LINE__);
	}

	if (debug)
		PEM_write_bio_SCEP_MSG( debug_bio, msg, pkey );
	return (msg);
err:
	ERR_print_errors_fp(stderr);
	return(NULL);
}